Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / mesa / drivers / dri / radeon / radeon_buffer_objects.c
1 /*
2  * Copyright 2009 Maciej Cencora <m.cencora@gmail.com>
3  *
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining
7  * a copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sublicense, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice (including the
15  * next paragraph) shall be included in all copies or substantial
16  * portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21  * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
22  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25  *
26  */
27
28 #include "radeon_buffer_objects.h"
29
30 #include "main/imports.h"
31 #include "main/mtypes.h"
32 #include "main/bufferobj.h"
33
34 #include "radeon_common.h"
35
36 struct radeon_buffer_object *
37 get_radeon_buffer_object(struct gl_buffer_object *obj)
38 {
39     return (struct radeon_buffer_object *) obj;
40 }
41
42 static struct gl_buffer_object *
43 radeonNewBufferObject(struct gl_context * ctx,
44                       GLuint name,
45                       GLenum target)
46 {
47     struct radeon_buffer_object *obj = CALLOC_STRUCT(radeon_buffer_object);
48
49     _mesa_initialize_buffer_object(&obj->Base, name, target);
50
51     obj->bo = NULL;
52
53     return &obj->Base;
54 }
55
56 /**
57  * Called via glDeleteBuffersARB().
58  */
59 static void
60 radeonDeleteBufferObject(struct gl_context * ctx,
61                          struct gl_buffer_object *obj)
62 {
63     struct radeon_buffer_object *radeon_obj = get_radeon_buffer_object(obj);
64
65     if (obj->Pointer) {
66         radeon_bo_unmap(radeon_obj->bo);
67     }
68
69     if (radeon_obj->bo) {
70         radeon_bo_unref(radeon_obj->bo);
71     }
72
73     free(radeon_obj);
74 }
75
76
77 /**
78  * Allocate space for and store data in a buffer object.  Any data that was
79  * previously stored in the buffer object is lost.  If data is NULL,
80  * memory will be allocated, but no copy will occur.
81  * Called via ctx->Driver.BufferData().
82  * \return GL_TRUE for success, GL_FALSE if out of memory
83  */
84 static GLboolean
85 radeonBufferData(struct gl_context * ctx,
86                  GLenum target,
87                  GLsizeiptrARB size,
88                  const GLvoid * data,
89                  GLenum usage,
90                  struct gl_buffer_object *obj)
91 {
92     radeonContextPtr radeon = RADEON_CONTEXT(ctx);
93     struct radeon_buffer_object *radeon_obj = get_radeon_buffer_object(obj);
94
95     radeon_obj->Base.Size = size;
96     radeon_obj->Base.Usage = usage;
97
98     if (radeon_obj->bo != NULL) {
99         radeon_bo_unref(radeon_obj->bo);
100         radeon_obj->bo = NULL;
101     }
102
103     if (size != 0) {
104         radeon_obj->bo = radeon_bo_open(radeon->radeonScreen->bom,
105                                         0,
106                                         size,
107                                         32,
108                                         RADEON_GEM_DOMAIN_GTT,
109                                         0);
110
111         if (!radeon_obj->bo)
112             return GL_FALSE;
113
114         if (data != NULL) {
115             radeon_bo_map(radeon_obj->bo, GL_TRUE);
116
117             memcpy(radeon_obj->bo->ptr, data, size);
118
119             radeon_bo_unmap(radeon_obj->bo);
120         }
121     }
122     return GL_TRUE;
123 }
124
125 /**
126  * Replace data in a subrange of buffer object.  If the data range
127  * specified by size + offset extends beyond the end of the buffer or
128  * if data is NULL, no copy is performed.
129  * Called via glBufferSubDataARB().
130  */
131 static void
132 radeonBufferSubData(struct gl_context * ctx,
133                     GLenum target,
134                     GLintptrARB offset,
135                     GLsizeiptrARB size,
136                     const GLvoid * data,
137                     struct gl_buffer_object *obj)
138 {
139     radeonContextPtr radeon = RADEON_CONTEXT(ctx);
140     struct radeon_buffer_object *radeon_obj = get_radeon_buffer_object(obj);
141
142     if (radeon_bo_is_referenced_by_cs(radeon_obj->bo, radeon->cmdbuf.cs)) {
143         radeon_firevertices(radeon);
144     }
145
146     radeon_bo_map(radeon_obj->bo, GL_TRUE);
147
148     memcpy(radeon_obj->bo->ptr + offset, data, size);
149
150     radeon_bo_unmap(radeon_obj->bo);
151 }
152
153 /**
154  * Called via glGetBufferSubDataARB()
155  */
156 static void
157 radeonGetBufferSubData(struct gl_context * ctx,
158                        GLenum target,
159                        GLintptrARB offset,
160                        GLsizeiptrARB size,
161                        GLvoid * data,
162                        struct gl_buffer_object *obj)
163 {
164     struct radeon_buffer_object *radeon_obj = get_radeon_buffer_object(obj);
165
166     radeon_bo_map(radeon_obj->bo, GL_FALSE);
167
168     memcpy(data, radeon_obj->bo->ptr + offset, size);
169
170     radeon_bo_unmap(radeon_obj->bo);
171 }
172
173 /**
174  * Called via glMapBufferARB()
175  */
176 static void *
177 radeonMapBuffer(struct gl_context * ctx,
178                 GLenum target,
179                 GLenum access,
180                 struct gl_buffer_object *obj)
181 {
182     struct radeon_buffer_object *radeon_obj = get_radeon_buffer_object(obj);
183
184     if (access == GL_WRITE_ONLY_ARB) {
185         ctx->Driver.Flush(ctx);
186     }
187
188     if (radeon_obj->bo == NULL) {
189         obj->Pointer = NULL;
190         return NULL;
191     }
192
193     radeon_bo_map(radeon_obj->bo, access == GL_WRITE_ONLY_ARB);
194
195     obj->Pointer = radeon_obj->bo->ptr;
196     obj->Length = obj->Size;
197     obj->Offset = 0;
198
199     return obj->Pointer;
200 }
201
202
203 /**
204  * Called via glUnmapBufferARB()
205  */
206 static GLboolean
207 radeonUnmapBuffer(struct gl_context * ctx,
208                   GLenum target,
209                   struct gl_buffer_object *obj)
210 {
211     struct radeon_buffer_object *radeon_obj = get_radeon_buffer_object(obj);
212
213     if (radeon_obj->bo != NULL) {
214         radeon_bo_unmap(radeon_obj->bo);
215     }
216
217     obj->Pointer = NULL;
218     obj->Offset = 0;
219     obj->Length = 0;
220
221     return GL_TRUE;
222 }
223
224 void
225 radeonInitBufferObjectFuncs(struct dd_function_table *functions)
226 {
227     functions->NewBufferObject = radeonNewBufferObject;
228     functions->DeleteBuffer = radeonDeleteBufferObject;
229     functions->BufferData = radeonBufferData;
230     functions->BufferSubData = radeonBufferSubData;
231     functions->GetBufferSubData = radeonGetBufferSubData;
232     functions->MapBuffer = radeonMapBuffer;
233     functions->UnmapBuffer = radeonUnmapBuffer;
234 }