fix STATE_HALF_VECTOR value (bug 10987)
[mesa.git] / src / mesa / drivers / dri / i915tex / intel_buffer_objects.c
1 /**************************************************************************
2 *
3 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * 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, sub license, 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 portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28
29 #include "imports.h"
30 #include "mtypes.h"
31 #include "bufferobj.h"
32
33 #include "intel_context.h"
34 #include "intel_buffer_objects.h"
35 #include "intel_regions.h"
36 #include "dri_bufmgr.h"
37
38 /**
39 * There is some duplication between mesa's bufferobjects and our
40 * bufmgr buffers. Both have an integer handle and a hashtable to
41 * lookup an opaque structure. It would be nice if the handles and
42 * internal structure where somehow shared.
43 */
44 static struct gl_buffer_object *
45 intel_bufferobj_alloc(GLcontext * ctx, GLuint name, GLenum target)
46 {
47 struct intel_context *intel = intel_context(ctx);
48 struct intel_buffer_object *obj = CALLOC_STRUCT(intel_buffer_object);
49
50 _mesa_initialize_buffer_object(&obj->Base, name, target);
51
52 driGenBuffers(intel->intelScreen->regionPool,
53 "bufferobj", 1, &obj->buffer, 64,
54 DRM_BO_FLAG_MEM_LOCAL |
55 DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE,
56 0);
57
58 return &obj->Base;
59 }
60
61
62 /* Break the COW tie to the region. The region gets to keep the data.
63 */
64 void
65 intel_bufferobj_release_region(struct intel_context *intel,
66 struct intel_buffer_object *intel_obj)
67 {
68 assert(intel_obj->region->buffer == intel_obj->buffer);
69 intel_obj->region->pbo = NULL;
70 intel_obj->region = NULL;
71 driBOUnReference(intel_obj->buffer);
72 intel_obj->buffer = NULL;
73
74 /* This leads to a large number of buffer deletion/creation events.
75 * Currently the drm doesn't like that:
76 */
77 driGenBuffers(intel->intelScreen->regionPool,
78 "buffer object", 1, &intel_obj->buffer, 64, 0, 0);
79 LOCK_HARDWARE(intel);
80 driBOData(intel_obj->buffer, intel_obj->Base.Size, NULL, 0);
81 UNLOCK_HARDWARE(intel);
82 }
83
84 /* Break the COW tie to the region. Both the pbo and the region end
85 * up with a copy of the data.
86 */
87 void
88 intel_bufferobj_cow(struct intel_context *intel,
89 struct intel_buffer_object *intel_obj)
90 {
91 assert(intel_obj->region);
92 intel_region_cow(intel->intelScreen, intel_obj->region);
93 }
94
95
96 /**
97 * Deallocate/free a vertex/pixel buffer object.
98 * Called via glDeleteBuffersARB().
99 */
100 static void
101 intel_bufferobj_free(GLcontext * ctx, struct gl_buffer_object *obj)
102 {
103 struct intel_context *intel = intel_context(ctx);
104 struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
105
106 assert(intel_obj);
107
108 if (intel_obj->region) {
109 intel_bufferobj_release_region(intel, intel_obj);
110 }
111 else if (intel_obj->buffer) {
112 driDeleteBuffers(1, &intel_obj->buffer);
113 }
114
115 _mesa_free(intel_obj);
116 }
117
118
119
120 /**
121 * Allocate space for and store data in a buffer object. Any data that was
122 * previously stored in the buffer object is lost. If data is NULL,
123 * memory will be allocated, but no copy will occur.
124 * Called via glBufferDataARB().
125 */
126 static void
127 intel_bufferobj_data(GLcontext * ctx,
128 GLenum target,
129 GLsizeiptrARB size,
130 const GLvoid * data,
131 GLenum usage, struct gl_buffer_object *obj)
132 {
133 struct intel_context *intel = intel_context(ctx);
134 struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
135
136 intel_obj->Base.Size = size;
137 intel_obj->Base.Usage = usage;
138
139 if (intel_obj->region)
140 intel_bufferobj_release_region(intel, intel_obj);
141
142 LOCK_HARDWARE(intel);
143 driBOData(intel_obj->buffer, size, data, 0);
144 UNLOCK_HARDWARE(intel);
145 }
146
147
148 /**
149 * Replace data in a subrange of buffer object. If the data range
150 * specified by size + offset extends beyond the end of the buffer or
151 * if data is NULL, no copy is performed.
152 * Called via glBufferSubDataARB().
153 */
154 static void
155 intel_bufferobj_subdata(GLcontext * ctx,
156 GLenum target,
157 GLintptrARB offset,
158 GLsizeiptrARB size,
159 const GLvoid * data, struct gl_buffer_object *obj)
160 {
161 struct intel_context *intel = intel_context(ctx);
162 struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
163
164 assert(intel_obj);
165
166 if (intel_obj->region)
167 intel_bufferobj_cow(intel, intel_obj);
168
169 driBOSubData(intel_obj->buffer, offset, size, data);
170 }
171
172
173 /**
174 * Called via glGetBufferSubDataARB().
175 */
176 static void
177 intel_bufferobj_get_subdata(GLcontext * ctx,
178 GLenum target,
179 GLintptrARB offset,
180 GLsizeiptrARB size,
181 GLvoid * data, struct gl_buffer_object *obj)
182 {
183 struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
184
185 assert(intel_obj);
186 driBOGetSubData(intel_obj->buffer, offset, size, data);
187 }
188
189
190
191 /**
192 * Called via glMapBufferARB().
193 */
194 static void *
195 intel_bufferobj_map(GLcontext * ctx,
196 GLenum target,
197 GLenum access, struct gl_buffer_object *obj)
198 {
199 struct intel_context *intel = intel_context(ctx);
200 struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
201
202 /* XXX: Translate access to flags arg below:
203 */
204 assert(intel_obj);
205
206 if (intel_obj->region)
207 intel_bufferobj_cow(intel, intel_obj);
208
209 obj->Pointer = driBOMap(intel_obj->buffer,
210 DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0);
211 return obj->Pointer;
212 }
213
214
215 /**
216 * Called via glMapBufferARB().
217 */
218 static GLboolean
219 intel_bufferobj_unmap(GLcontext * ctx,
220 GLenum target, struct gl_buffer_object *obj)
221 {
222 struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
223
224 assert(intel_obj);
225 assert(obj->Pointer);
226 driBOUnmap(intel_obj->buffer);
227 obj->Pointer = NULL;
228 return GL_TRUE;
229 }
230
231 struct _DriBufferObject *
232 intel_bufferobj_buffer(struct intel_context *intel,
233 struct intel_buffer_object *intel_obj, GLuint flag)
234 {
235 if (intel_obj->region) {
236 if (flag == INTEL_WRITE_PART)
237 intel_bufferobj_cow(intel, intel_obj);
238 else if (flag == INTEL_WRITE_FULL)
239 intel_bufferobj_release_region(intel, intel_obj);
240 }
241
242 return intel_obj->buffer;
243 }
244
245 void
246 intel_bufferobj_init(struct intel_context *intel)
247 {
248 GLcontext *ctx = &intel->ctx;
249
250 ctx->Driver.NewBufferObject = intel_bufferobj_alloc;
251 ctx->Driver.DeleteBuffer = intel_bufferobj_free;
252 ctx->Driver.BufferData = intel_bufferobj_data;
253 ctx->Driver.BufferSubData = intel_bufferobj_subdata;
254 ctx->Driver.GetBufferSubData = intel_bufferobj_get_subdata;
255 ctx->Driver.MapBuffer = intel_bufferobj_map;
256 ctx->Driver.UnmapBuffer = intel_bufferobj_unmap;
257 }