|
1 /* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). |
|
2 * |
|
3 * Permission is hereby granted, free of charge, to any person obtaining a |
|
4 * copy of this software and associated documentation files (the "Software"), |
|
5 * to deal in the Software without restriction, including without limitation |
|
6 * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
|
7 * and/or sell copies of the Software, and to permit persons to whom the |
|
8 * Software is furnished to do so, subject to the following conditions: |
|
9 * |
|
10 * The above copyright notice and this permission notice shall be included |
|
11 * in all copies or substantial portions of the Software. |
|
12 * |
|
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
|
14 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
|
16 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN |
|
17 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
|
18 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
|
19 * |
|
20 * Initial Contributors: |
|
21 * Nokia Corporation - initial contribution. |
|
22 * |
|
23 * Contributors: |
|
24 * |
|
25 * Description: |
|
26 * |
|
27 */ |
|
28 |
|
29 #include "common.h" |
|
30 #include "hgl.h" |
|
31 #include "context.h" |
|
32 #include "vertex.h" |
|
33 #include "get.h" |
|
34 #include "half.h" |
|
35 |
|
36 #define DEBUG_VERTEX 0 |
|
37 |
|
38 GLboolean dglGetVertexAttrib(const DGLContext *ctx, GLuint index, GLenum pname, DGLType type, void* params) |
|
39 { |
|
40 GLint i; |
|
41 |
|
42 switch(pname) |
|
43 { |
|
44 case GL_VERTEX_ATTRIB_ARRAY_ENABLED: |
|
45 i = ctx->vertex_arrays[index].enabled; |
|
46 break; |
|
47 |
|
48 case GL_VERTEX_ATTRIB_ARRAY_SIZE: |
|
49 i = ctx->vertex_arrays[index].size; |
|
50 break; |
|
51 |
|
52 case GL_VERTEX_ATTRIB_ARRAY_STRIDE: |
|
53 i = ctx->vertex_arrays[index].stride; |
|
54 break; |
|
55 |
|
56 case GL_VERTEX_ATTRIB_ARRAY_TYPE: |
|
57 i = ctx->vertex_arrays[index].type; |
|
58 break; |
|
59 |
|
60 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED: |
|
61 i = ctx->vertex_arrays[index].normalized; |
|
62 break; |
|
63 |
|
64 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: |
|
65 i = ctx->vertex_arrays[index].buffer != NULL ? ctx->vertex_arrays[index].buffer->obj.name : 0; |
|
66 break; |
|
67 |
|
68 case GL_CURRENT_VERTEX_ATTRIB: |
|
69 if(index == 0) |
|
70 { |
|
71 // Attribute zero can't be set in desktop GL. |
|
72 if(type == DGLES2_TYPE_INT) |
|
73 { |
|
74 ((GLint*)params)[0] = (GLint)ctx->attrib_zero[0]; |
|
75 ((GLint*)params)[1] = (GLint)ctx->attrib_zero[1]; |
|
76 ((GLint*)params)[2] = (GLint)ctx->attrib_zero[2]; |
|
77 ((GLint*)params)[3] = (GLint)ctx->attrib_zero[3]; |
|
78 } |
|
79 else |
|
80 { |
|
81 DGLES2_ASSERT(type == DGLES2_TYPE_FLOAT); |
|
82 ((GLfloat*)params)[0] = ctx->attrib_zero[0]; |
|
83 ((GLfloat*)params)[1] = ctx->attrib_zero[1]; |
|
84 ((GLfloat*)params)[2] = ctx->attrib_zero[2]; |
|
85 ((GLfloat*)params)[3] = ctx->attrib_zero[3]; |
|
86 } |
|
87 } |
|
88 else |
|
89 { |
|
90 if(type == DGLES2_TYPE_INT) |
|
91 { |
|
92 ctx->hgl.GetVertexAttribiv(index, GL_CURRENT_VERTEX_ATTRIB, params); |
|
93 } |
|
94 else |
|
95 { |
|
96 DGLES2_ASSERT(type == DGLES2_TYPE_FLOAT); |
|
97 ctx->hgl.GetVertexAttribfv(index, GL_CURRENT_VERTEX_ATTRIB, params); |
|
98 } |
|
99 } |
|
100 return GL_TRUE; |
|
101 |
|
102 default: |
|
103 return GL_FALSE; |
|
104 } |
|
105 |
|
106 if(type == DGLES2_TYPE_INT) |
|
107 { |
|
108 *(GLint*)params = i; |
|
109 } |
|
110 else |
|
111 { |
|
112 DGLES2_ASSERT(type == DGLES2_TYPE_FLOAT); |
|
113 *(GLfloat*)params = (GLfloat)i; |
|
114 } |
|
115 |
|
116 return GL_TRUE; |
|
117 } |
|
118 |
|
119 GL_APICALL_BUILD void GL_APIENTRY glDisableVertexAttribArray(GLuint index) |
|
120 { |
|
121 DGLES2_ENTER(); |
|
122 DGLES2_ERROR_IF(index >= ctx->max_vertex_attribs, GL_INVALID_VALUE); |
|
123 # if(DEBUG_VERTEX == 1) |
|
124 Dprintf("Disabling array %d\n", index); |
|
125 # endif |
|
126 ctx->vertex_arrays[index].enabled = GL_FALSE; |
|
127 ctx->hgl.DisableVertexAttribArray(index); |
|
128 DGLES2_LEAVE(); |
|
129 } |
|
130 |
|
131 // Function to convert fixed and half float arrays to float arrays. |
|
132 static void dglConvertArrays(DGLContext* ctx, GLint first, GLsizei count) |
|
133 { |
|
134 unsigned int i; |
|
135 for(i = 0; i < ctx->max_vertex_attribs; ++i) |
|
136 { |
|
137 DGLVertexArray* va = ctx->vertex_arrays + i; |
|
138 if(!va->enabled) |
|
139 { |
|
140 continue; |
|
141 } |
|
142 { |
|
143 if(va->type == GL_FIXED || va->type == GL_HALF_FLOAT_OES) |
|
144 { |
|
145 const void* ptr = va->buffer != NULL ? va->buffer->data : va->ptr; |
|
146 |
|
147 GLsizei stride; |
|
148 if(va->stride) |
|
149 { |
|
150 stride = va->stride; |
|
151 } |
|
152 else if(va->type == GL_FIXED) |
|
153 { |
|
154 stride = va->size * sizeof(GLfixed); |
|
155 } |
|
156 else |
|
157 { |
|
158 DGLES2_ASSERT(va->type == GL_HALF_FLOAT_OES); |
|
159 stride = va->size * sizeof(khronos_int16_t); |
|
160 } |
|
161 |
|
162 # if(DEBUG_VERTEX == 1) |
|
163 Dprintf("Converting %d fixed/half float indices to float.\n", count); |
|
164 # endif |
|
165 |
|
166 if(va->floatptr) free(va->floatptr); |
|
167 |
|
168 va->floatptr = malloc(sizeof(GLfloat)*count*va->size); |
|
169 { |
|
170 GLsizei j; |
|
171 for(j = 0; j < count; ++j) |
|
172 { |
|
173 signed k; |
|
174 for(k = 0; k < va->size; ++k) |
|
175 { |
|
176 if(va->type == GL_FIXED) |
|
177 { |
|
178 va->floatptr[j*va->size + k] = ((GLfixed*)(((char*)ptr) + stride*(first + j)))[k] / 65536.0f; |
|
179 } |
|
180 else |
|
181 { |
|
182 khronos_int16_t half; |
|
183 DGLES2_ASSERT(va->type == GL_HALF_FLOAT_OES); |
|
184 half = ((khronos_int16_t*)(((char*)ptr) + stride*(first + j)))[k]; |
|
185 va->floatptr[j*va->size + k] = dglConvertHalfToFloat(half); |
|
186 } |
|
187 } |
|
188 } |
|
189 } |
|
190 ctx->hgl.VertexAttribPointer(i, va->size, GL_FLOAT, va->normalized, 0, va->floatptr - first); |
|
191 } |
|
192 } |
|
193 } |
|
194 } |
|
195 |
|
196 GL_APICALL_BUILD void GL_APIENTRY glDrawArrays(GLenum mode, GLint first, GLsizei count) |
|
197 { |
|
198 DGLES2_ENTER(); |
|
199 DGLES2_ERROR_IF(first < 0, GL_INVALID_VALUE); |
|
200 DGLES2_ERROR_IF(count < 0, GL_INVALID_VALUE); |
|
201 dglConvertArrays(ctx, first, count); |
|
202 DGLES2_BEGIN_DRAWING(); |
|
203 ctx->hgl.DrawArrays(mode, first, count); |
|
204 DGLES2_END_DRAWING(); |
|
205 DGLES2_LEAVE(); |
|
206 } |
|
207 |
|
208 GL_APICALL_BUILD void GL_APIENTRY glDrawElements(GLenum mode, GLsizei count, GLenum type, const void* indices) |
|
209 { |
|
210 DGLES2_ENTER(); |
|
211 DGLES2_ERROR_IF(count < 0, GL_INVALID_VALUE); |
|
212 { |
|
213 GLsizei indice_size; |
|
214 switch(type) |
|
215 { |
|
216 case GL_UNSIGNED_BYTE: indice_size = sizeof(GLubyte); break; |
|
217 case GL_UNSIGNED_SHORT: indice_size = sizeof(GLushort); break; |
|
218 default: |
|
219 { |
|
220 DGLES2_ERROR(GL_INVALID_ENUM); |
|
221 } |
|
222 } |
|
223 dglConvertArrays(ctx, (GLint)((size_t)indices/indice_size), count); |
|
224 DGLES2_BEGIN_DRAWING(); |
|
225 ctx->hgl.DrawElements(mode, count, type, indices); |
|
226 DGLES2_END_DRAWING(); |
|
227 } |
|
228 DGLES2_LEAVE(); |
|
229 } |
|
230 |
|
231 GL_APICALL_BUILD void GL_APIENTRY glEnableVertexAttribArray(GLuint index) |
|
232 { |
|
233 DGLES2_ENTER(); |
|
234 DGLES2_ERROR_IF(index >= ctx->max_vertex_attribs, GL_INVALID_VALUE); |
|
235 # if(DEBUG_VERTEX == 1) |
|
236 Dprintf("Enabling array %d\n", index); |
|
237 # endif |
|
238 ctx->vertex_arrays[index].enabled = GL_TRUE; |
|
239 ctx->hgl.EnableVertexAttribArray(index); |
|
240 DGLES2_LEAVE(); |
|
241 } |
|
242 |
|
243 GL_APICALL_BUILD void GL_APIENTRY glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params) |
|
244 { |
|
245 DGLES2_ENTER(); |
|
246 DGLES2_ERROR_IF(index >= ctx->max_vertex_attribs, GL_INVALID_VALUE); |
|
247 if(!dglGetVertexAttrib(ctx, index, pname, DGLES2_TYPE_FLOAT, params)) |
|
248 { |
|
249 DGLES2_ERROR(GL_INVALID_ENUM); |
|
250 } |
|
251 DGLES2_LEAVE(); |
|
252 } |
|
253 |
|
254 GL_APICALL_BUILD void GL_APIENTRY glGetVertexAttribiv(GLuint index, GLenum pname, GLint* params) |
|
255 { |
|
256 DGLES2_ENTER(); |
|
257 DGLES2_ERROR_IF(index >= ctx->max_vertex_attribs, GL_INVALID_VALUE); |
|
258 if(!dglGetVertexAttrib(ctx, index, pname, DGLES2_TYPE_INT, params)) |
|
259 { |
|
260 DGLES2_ERROR(GL_INVALID_ENUM); |
|
261 } |
|
262 DGLES2_LEAVE(); |
|
263 } |
|
264 |
|
265 GL_APICALL_BUILD void GL_APIENTRY glGetVertexAttribPointerv(GLuint index, GLenum pname, void** pointer) |
|
266 { |
|
267 DGLES2_ENTER(); |
|
268 DGLES2_ERROR_IF(index >= ctx->max_vertex_attribs, GL_INVALID_VALUE); |
|
269 DGLES2_ERROR_IF(pname != GL_VERTEX_ATTRIB_ARRAY_POINTER, GL_INVALID_ENUM); |
|
270 *pointer = (void*)ctx->vertex_arrays[index].ptr; |
|
271 DGLES2_LEAVE(); |
|
272 } |
|
273 |
|
274 GL_APICALL_BUILD void GL_APIENTRY glVertexAttrib1f(GLuint indx, GLfloat x) |
|
275 { |
|
276 DGLES2_ENTER(); |
|
277 DGLES2_ERROR_IF(indx >= ctx->max_vertex_attribs, GL_INVALID_VALUE); |
|
278 if(indx == 0) |
|
279 { |
|
280 // Attribute zero can't be set in desktop GL. |
|
281 ctx->attrib_zero[0] = x; |
|
282 } |
|
283 else |
|
284 { |
|
285 ctx->hgl.VertexAttrib1f(indx, x); |
|
286 } |
|
287 DGLES2_LEAVE(); |
|
288 } |
|
289 |
|
290 GL_APICALL_BUILD void GL_APIENTRY glVertexAttrib1fv(GLuint indx, const GLfloat* values) |
|
291 { |
|
292 DGLES2_ENTER(); |
|
293 DGLES2_ERROR_IF(indx >= ctx->max_vertex_attribs, GL_INVALID_VALUE); |
|
294 if(indx == 0) |
|
295 { |
|
296 // Attribute zero can't be set in desktop GL. |
|
297 ctx->attrib_zero[0] = values[0]; |
|
298 } |
|
299 else |
|
300 { |
|
301 ctx->hgl.VertexAttrib1fv(indx, values); |
|
302 } |
|
303 DGLES2_LEAVE(); |
|
304 } |
|
305 |
|
306 GL_APICALL_BUILD void GL_APIENTRY glVertexAttrib2f(GLuint indx, GLfloat x, GLfloat y) |
|
307 { |
|
308 DGLES2_ENTER(); |
|
309 DGLES2_ERROR_IF(indx >= ctx->max_vertex_attribs, GL_INVALID_VALUE); |
|
310 if(indx == 0) |
|
311 { |
|
312 // Attribute zero can't be set in desktop GL. |
|
313 ctx->attrib_zero[0] = x; |
|
314 ctx->attrib_zero[1] = y; |
|
315 } |
|
316 else |
|
317 { |
|
318 ctx->hgl.VertexAttrib2f(indx, x, y); |
|
319 } |
|
320 DGLES2_LEAVE(); |
|
321 } |
|
322 |
|
323 GL_APICALL_BUILD void GL_APIENTRY glVertexAttrib2fv(GLuint indx, const GLfloat* values) |
|
324 { |
|
325 DGLES2_ENTER(); |
|
326 DGLES2_ERROR_IF(indx >= ctx->max_vertex_attribs, GL_INVALID_VALUE); |
|
327 if(indx == 0) |
|
328 { |
|
329 // Attribute zero can't be set in desktop GL. |
|
330 ctx->attrib_zero[0] = values[0]; |
|
331 } |
|
332 else |
|
333 { |
|
334 ctx->hgl.VertexAttrib2fv(indx, values); |
|
335 } |
|
336 DGLES2_LEAVE(); |
|
337 } |
|
338 |
|
339 GL_APICALL_BUILD void GL_APIENTRY glVertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z) |
|
340 { |
|
341 DGLES2_ENTER(); |
|
342 DGLES2_ERROR_IF(indx >= ctx->max_vertex_attribs, GL_INVALID_VALUE); |
|
343 if(indx == 0) |
|
344 { |
|
345 // Attribute zero can't be set in desktop GL. |
|
346 ctx->attrib_zero[0] = x; |
|
347 ctx->attrib_zero[1] = y; |
|
348 ctx->attrib_zero[2] = z; |
|
349 } |
|
350 else |
|
351 { |
|
352 ctx->hgl.VertexAttrib3f(indx, x, y, z); |
|
353 } |
|
354 DGLES2_LEAVE(); |
|
355 } |
|
356 |
|
357 GL_APICALL_BUILD void GL_APIENTRY glVertexAttrib3fv(GLuint indx, const GLfloat* values) |
|
358 { |
|
359 DGLES2_ENTER(); |
|
360 DGLES2_ERROR_IF(indx >= ctx->max_vertex_attribs, GL_INVALID_VALUE); |
|
361 if(indx == 0) |
|
362 { |
|
363 // Attribute zero can't be set in desktop GL. |
|
364 ctx->attrib_zero[0] = values[0]; |
|
365 ctx->attrib_zero[1] = values[1]; |
|
366 ctx->attrib_zero[2] = values[2]; |
|
367 } |
|
368 else |
|
369 { |
|
370 ctx->hgl.VertexAttrib3fv(indx, values); |
|
371 } |
|
372 DGLES2_LEAVE(); |
|
373 } |
|
374 |
|
375 GL_APICALL_BUILD void GL_APIENTRY glVertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w) |
|
376 { |
|
377 DGLES2_ENTER(); |
|
378 DGLES2_ERROR_IF(indx >= ctx->max_vertex_attribs, GL_INVALID_VALUE); |
|
379 if(indx == 0) |
|
380 { |
|
381 // Attribute zero can't be set in desktop GL. |
|
382 ctx->attrib_zero[0] = x; |
|
383 ctx->attrib_zero[1] = y; |
|
384 ctx->attrib_zero[2] = z; |
|
385 ctx->attrib_zero[3] = w; |
|
386 } |
|
387 else |
|
388 { |
|
389 ctx->hgl.VertexAttrib4f(indx, x, y, z, w); |
|
390 } |
|
391 DGLES2_LEAVE(); |
|
392 } |
|
393 |
|
394 GL_APICALL_BUILD void GL_APIENTRY glVertexAttrib4fv(GLuint indx, const GLfloat* values) |
|
395 { |
|
396 DGLES2_ENTER(); |
|
397 DGLES2_ERROR_IF(indx >= ctx->max_vertex_attribs, GL_INVALID_VALUE); |
|
398 if(indx == 0) |
|
399 { |
|
400 // Attribute zero can't be set in desktop GL. |
|
401 ctx->attrib_zero[0] = values[0]; |
|
402 ctx->attrib_zero[1] = values[1]; |
|
403 ctx->attrib_zero[2] = values[2]; |
|
404 ctx->attrib_zero[3] = values[3]; |
|
405 } |
|
406 else |
|
407 { |
|
408 ctx->hgl.VertexAttrib4fv(indx, values); |
|
409 } |
|
410 DGLES2_LEAVE(); |
|
411 } |
|
412 |
|
413 GL_APICALL_BUILD void GL_APIENTRY glVertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr) |
|
414 { |
|
415 DGLES2_ENTER(); |
|
416 DGLES2_ERROR_IF(indx >= ctx->max_vertex_attribs, GL_INVALID_VALUE); |
|
417 DGLES2_ERROR_IF(size < 1 || size > 4, GL_INVALID_VALUE); |
|
418 DGLES2_ERROR_IF(type != GL_BYTE && |
|
419 type != GL_UNSIGNED_BYTE && |
|
420 type != GL_SHORT && |
|
421 type != GL_UNSIGNED_SHORT && |
|
422 type != GL_FIXED && |
|
423 type != GL_FLOAT && |
|
424 type != GL_HALF_FLOAT_OES, |
|
425 GL_INVALID_ENUM); |
|
426 DGLES2_ERROR_IF(stride < 0, GL_INVALID_VALUE); |
|
427 # if(DEBUG_VERTEX == 1) |
|
428 Dprintf("Array %d at %p (%d elements every %d bytes)\n", indx, ptr, size, stride); |
|
429 # endif |
|
430 |
|
431 { |
|
432 DGLVertexArray* va = ctx->vertex_arrays + indx; |
|
433 |
|
434 if(type != GL_FIXED && type != GL_HALF_FLOAT_OES) |
|
435 { |
|
436 ctx->hgl.VertexAttribPointer(indx, size, type, normalized, stride, ptr); |
|
437 } |
|
438 |
|
439 if(DGLContext_getHostError(ctx) == GL_NO_ERROR) |
|
440 { |
|
441 va->size = size; |
|
442 va->type = type; |
|
443 va->normalized = normalized; |
|
444 va->stride = stride; |
|
445 va->ptr = ptr; |
|
446 |
|
447 va->buffer = DGLContext_findBuffer(ctx, ctx->buffer_binding); |
|
448 } |
|
449 } |
|
450 DGLES2_LEAVE(); |
|
451 } |
|
452 |