1 /*
2 * Copyright 2011, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <cutils/log.h>
18 #include <GLES/gl.h>
19 #include <GLES/glext.h>
20 #include <GLES2/gl2.h>
21 #include <GLES2/gl2ext.h>
22
23 #include "gltrace.pb.h"
24 #include "gltrace_api.h"
25 #include "gltrace_context.h"
26 #include "gltrace_fixup.h"
27
28 namespace android {
29 namespace gltrace {
30
getBytesPerTexel(const GLenum format,const GLenum type)31 unsigned getBytesPerTexel(const GLenum format, const GLenum type) {
32 /*
33 Description from glTexImage2D spec:
34
35 Data is read from data as a sequence of unsigned bytes or shorts, depending on type.
36 When type is GL_UNSIGNED_BYTE, each of the bytes is interpreted as one color component.
37 When type is one of GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_4_4_4_4, or
38 GL_UNSIGNED_SHORT_5_5_5_1, each unsigned short value is interpreted as containing all
39 the components for a single texel, with the color components arranged according to
40 format. Color components are treated as groups of one, two, three, or four values,
41 again based on format. Groups of components are referred to as texels.
42
43 width × height texels are read from memory, starting at location data. By default,
44 these texels are taken from adjacent memory locations, except that after all width
45 texels are read, the read pointer is advanced to the next four-byte boundary.
46 The four-byte row alignment is specified by glPixelStorei with argument
47 GL_UNPACK_ALIGNMENT, and it can be set to one, two, four, or eight bytes.
48 */
49
50 switch (type) {
51 case GL_UNSIGNED_SHORT_5_6_5:
52 case GL_UNSIGNED_SHORT_4_4_4_4:
53 case GL_UNSIGNED_SHORT_5_5_5_1:
54 return 2;
55 case GL_UNSIGNED_BYTE:
56 break;
57 default:
58 ALOGE("GetBytesPerPixel: unknown type %x", type);
59 }
60
61 switch (format) {
62 case GL_ALPHA:
63 case GL_LUMINANCE:
64 return 1;
65 case GL_LUMINANCE_ALPHA:
66 return 2;
67 case GL_RGB:
68 return 3;
69 case GL_RGBA:
70 case 0x80E1: // GL_BGRA_EXT
71 return 4;
72 default:
73 ALOGE("GetBytesPerPixel: unknown format %x", format);
74 }
75
76 return 1; // in doubt...
77 }
78
fixup_GenericFloatArray(int argIndex,int nFloats,GLMessage * glmsg,void * src)79 void fixup_GenericFloatArray(int argIndex, int nFloats, GLMessage *glmsg, void *src) {
80 GLMessage_DataType *arg_floatarray = glmsg->mutable_args(argIndex);
81 GLfloat *floatp = (GLfloat *)src;
82
83 if (floatp == NULL) {
84 return;
85 }
86
87 arg_floatarray->set_type(GLMessage::DataType::FLOAT);
88 arg_floatarray->set_isarray(true);
89 arg_floatarray->clear_floatvalue();
90
91 for (int i = 0; i < nFloats; i++, floatp++) {
92 arg_floatarray->add_floatvalue(*floatp);
93 }
94 }
95
fixup_GenericIntArray(int argIndex,int nInts,GLMessage * glmsg,void * src)96 void fixup_GenericIntArray(int argIndex, int nInts, GLMessage *glmsg, void *src) {
97 GLMessage_DataType *arg_intarray = glmsg->mutable_args(argIndex);
98 GLint *intp = (GLint *)src;
99
100 if (intp == NULL) {
101 return;
102 }
103
104 arg_intarray->set_type(GLMessage::DataType::INT);
105 arg_intarray->set_isarray(true);
106 arg_intarray->clear_intvalue();
107
108 for (int i = 0; i < nInts; i++, intp++) {
109 arg_intarray->add_intvalue(*intp);
110 }
111 }
112
fixup_GenericEnumArray(int argIndex,int nEnums,GLMessage * glmsg,void * src)113 void fixup_GenericEnumArray(int argIndex, int nEnums, GLMessage *glmsg, void *src) {
114 // fixup as if they were ints
115 fixup_GenericIntArray(argIndex, nEnums, glmsg, src);
116
117 // and then set the data type to be enum
118 GLMessage_DataType *arg_enumarray = glmsg->mutable_args(argIndex);
119 arg_enumarray->set_type(GLMessage::DataType::ENUM);
120 }
121
122 /** Generic helper function: extract pointer at argIndex and
123 replace it with the C style string at *pointer */
fixup_CStringPtr(int argIndex,GLMessage * glmsg,void * src)124 void fixup_CStringPtr(int argIndex, GLMessage *glmsg, void *src) {
125 GLMessage_DataType *arg = glmsg->mutable_args(argIndex);
126 GLchar *ptr = (GLchar *) src;
127
128 arg->set_type(GLMessage::DataType::CHAR);
129 arg->set_isarray(true);
130 arg->add_charvalue(ptr);
131 }
132
fixup_glGetString(GLMessage * glmsg,void * pointersToFixup[])133 void fixup_glGetString(GLMessage *glmsg, void *pointersToFixup[]) {
134 /* const GLubyte* GLTrace_glGetString(GLenum name) */
135 GLMessage_DataType *ret = glmsg->mutable_returnvalue();
136 GLchar *ptr = (GLchar *) pointersToFixup[0];
137
138 if (ptr != NULL) {
139 ret->set_type(GLMessage::DataType::CHAR);
140 ret->set_isarray(true);
141 ret->add_charvalue(ptr);
142 }
143 }
144
145 /* Add the contents of the framebuffer to the protobuf message */
fixup_addFBContents(GLTraceContext * context,GLMessage * glmsg,FBBinding fbToRead)146 void fixup_addFBContents(GLTraceContext *context, GLMessage *glmsg, FBBinding fbToRead) {
147 void *fbcontents;
148 unsigned fbsize, fbwidth, fbheight;
149 context->getCompressedFB(&fbcontents, &fbsize, &fbwidth, &fbheight, fbToRead);
150
151 GLMessage_FrameBuffer *fb = glmsg->mutable_fb();
152 fb->set_width(fbwidth);
153 fb->set_height(fbheight);
154 fb->add_contents(fbcontents, fbsize);
155 }
156
157 /** Common fixup routing for glTexImage2D & glTexSubImage2D. */
fixup_glTexImage(int widthIndex,int heightIndex,GLMessage * glmsg,void * dataSrc)158 void fixup_glTexImage(int widthIndex, int heightIndex, GLMessage *glmsg, void *dataSrc) {
159 GLMessage_DataType arg_width = glmsg->args(widthIndex);
160 GLMessage_DataType arg_height = glmsg->args(heightIndex);
161
162 GLMessage_DataType arg_format = glmsg->args(6);
163 GLMessage_DataType arg_type = glmsg->args(7);
164 GLMessage_DataType *arg_data = glmsg->mutable_args(8);
165
166 GLsizei width = arg_width.intvalue(0);
167 GLsizei height = arg_height.intvalue(0);
168 GLenum format = arg_format.intvalue(0);
169 GLenum type = arg_type.intvalue(0);
170 void *data = (void *) dataSrc;
171
172 int bytesPerTexel = getBytesPerTexel(format, type);
173
174 arg_data->set_type(GLMessage::DataType::BYTE);
175 arg_data->clear_rawbytes();
176
177 if (data != NULL) {
178 arg_data->set_isarray(true);
179 arg_data->add_rawbytes(data, bytesPerTexel * width * height);
180 } else {
181 arg_data->set_isarray(false);
182 arg_data->set_type(GLMessage::DataType::VOID);
183 }
184 }
185
186
fixup_glTexImage2D(GLMessage * glmsg,void * pointersToFixup[])187 void fixup_glTexImage2D(GLMessage *glmsg, void *pointersToFixup[]) {
188 /* void glTexImage2D(GLenum target,
189 GLint level,
190 GLint internalformat,
191 GLsizei width,
192 GLsizei height,
193 GLint border,
194 GLenum format,
195 GLenum type,
196 const GLvoid *data);
197 */
198 int widthIndex = 3;
199 int heightIndex = 4;
200 fixup_glTexImage(widthIndex, heightIndex, glmsg, pointersToFixup[0]);
201 }
202
fixup_glTexSubImage2D(GLMessage * glmsg,void * pointersToFixup[])203 void fixup_glTexSubImage2D(GLMessage *glmsg, void *pointersToFixup[]) {
204 /*
205 void glTexSubImage2D(GLenum target,
206 GLint level,
207 GLint xoffset,
208 GLint yoffset,
209 GLsizei width,
210 GLsizei height,
211 GLenum format,
212 GLenum type,
213 const GLvoid * data);
214 */
215 int widthIndex = 4;
216 int heightIndex = 5;
217 fixup_glTexImage(widthIndex, heightIndex, glmsg, pointersToFixup[0]);
218 }
219
fixup_glShaderSource(GLMessage * glmsg,void * pointersToFixup[])220 void fixup_glShaderSource(GLMessage *glmsg, void *pointersToFixup[]) {
221 /* void glShaderSource(GLuint shader, GLsizei count, const GLchar** string,
222 const GLint* length) */
223 GLMessage_DataType arg_count = glmsg->args(1);
224 GLMessage_DataType arg_lenp = glmsg->args(3);
225 GLMessage_DataType *arg_strpp = glmsg->mutable_args(2);
226
227 GLsizei count = arg_count.intvalue(0);
228 GLchar **stringpp = (GLchar **) pointersToFixup[0];
229 GLint *lengthp = (GLint *) pointersToFixup[1];
230
231 arg_strpp->set_type(GLMessage::DataType::CHAR);
232 arg_strpp->set_isarray(true);
233 arg_strpp->clear_charvalue();
234
235 ::std::string src = "";
236 for (int i = 0; i < count; i++) {
237 if (lengthp != NULL)
238 src.append(*stringpp, *lengthp);
239 else
240 src.append(*stringpp); // assume null terminated
241 stringpp++;
242 lengthp++;
243 }
244
245 arg_strpp->add_charvalue(src);
246 }
247
fixup_glUniformGenericInteger(int argIndex,int nIntegers,GLMessage * glmsg,void * pointersToFixup[])248 void fixup_glUniformGenericInteger(int argIndex, int nIntegers, GLMessage *glmsg,
249 void *pointersToFixup[]) {
250 /* void glUniform?iv(GLint location, GLsizei count, const GLint *value); */
251 fixup_GenericIntArray(argIndex, nIntegers, glmsg, pointersToFixup[0]);
252 }
253
fixup_glUniformGeneric(int argIndex,int nFloats,GLMessage * glmsg,void * src)254 void fixup_glUniformGeneric(int argIndex, int nFloats, GLMessage *glmsg, void *src) {
255 fixup_GenericFloatArray(argIndex, nFloats, glmsg, src);
256 }
257
fixup_glUniformMatrixGeneric(int matrixSize,GLMessage * glmsg,void * pointersToFixup[])258 void fixup_glUniformMatrixGeneric(int matrixSize, GLMessage *glmsg, void *pointersToFixup[]) {
259 /* void glUniformMatrix?fv(GLint location, GLsizei count, GLboolean transpose,
260 const GLfloat* value) */
261 GLMessage_DataType arg_count = glmsg->args(1);
262 int n_matrices = arg_count.intvalue(0);
263 fixup_glUniformGeneric(3, matrixSize * matrixSize * n_matrices, glmsg, pointersToFixup[0]);
264 }
265
fixup_glGenGeneric(GLMessage * glmsg,void * pointersToFixup[])266 void fixup_glGenGeneric(GLMessage *glmsg, void *pointersToFixup[]) {
267 /* void glGen*(GLsizei n, GLuint * buffers); */
268 GLMessage_DataType arg_n = glmsg->args(0);
269 GLsizei n = arg_n.intvalue(0);
270
271 fixup_GenericIntArray(1, n, glmsg, pointersToFixup[0]);
272 }
273
fixup_glDeleteGeneric(GLMessage * glmsg,void * pointersToFixup[])274 void fixup_glDeleteGeneric(GLMessage *glmsg, void *pointersToFixup[]) {
275 /* void glDelete*(GLsizei n, GLuint *buffers); */
276 GLMessage_DataType arg_n = glmsg->args(0);
277 GLsizei n = arg_n.intvalue(0);
278
279 fixup_GenericIntArray(1, n, glmsg, pointersToFixup[0]);
280 }
281
fixup_glGetBooleanv(GLMessage * glmsg,void * pointersToFixup[])282 void fixup_glGetBooleanv(GLMessage *glmsg, void *pointersToFixup[]) {
283 /* void glGetBooleanv(GLenum pname, GLboolean *params); */
284 GLMessage_DataType *arg_params = glmsg->mutable_args(1);
285 GLboolean *src = (GLboolean*) pointersToFixup[0];
286
287 arg_params->set_type(GLMessage::DataType::BOOL);
288 arg_params->set_isarray(true);
289 arg_params->clear_boolvalue();
290 arg_params->add_boolvalue(*src);
291 }
292
fixup_glGetFloatv(GLMessage * glmsg,void * pointersToFixup[])293 void fixup_glGetFloatv(GLMessage *glmsg, void *pointersToFixup[]) {
294 /* void glGetFloatv(GLenum pname, GLfloat *params); */
295 GLMessage_DataType *arg_params = glmsg->mutable_args(1);
296 GLfloat *src = (GLfloat*) pointersToFixup[0];
297
298 arg_params->set_type(GLMessage::DataType::FLOAT);
299 arg_params->set_isarray(true);
300 arg_params->clear_floatvalue();
301 arg_params->add_floatvalue(*src);
302 }
303
fixup_glLinkProgram(GLMessage * glmsg)304 void fixup_glLinkProgram(GLMessage *glmsg) {
305 /* void glLinkProgram(GLuint program); */
306 GLuint program = glmsg->args(0).intvalue(0);
307
308 /* We don't have to fixup this call, but as soon as a program is linked,
309 we obtain information about all active attributes and uniforms to
310 pass on to the debugger. Note that in order to pass this info to
311 the debugger, all we need to do is call the trace versions of the
312 necessary calls. */
313
314 GLint n, maxNameLength;
315 GLchar *name;
316 GLint size;
317 GLenum type;
318
319 // obtain info regarding active attributes
320 GLTrace_glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &n);
321 GLTrace_glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxNameLength);
322
323 name = (GLchar *) malloc(maxNameLength);
324 for (int i = 0; i < n; i++) {
325 GLTrace_glGetActiveAttrib(program, i, maxNameLength, NULL, &size, &type, name);
326 }
327 free(name);
328
329 // obtain info regarding active uniforms
330 GLTrace_glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &n);
331 GLTrace_glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxNameLength);
332
333 name = (GLchar *) malloc(maxNameLength);
334 for (int i = 0; i < n; i++) {
335 GLTrace_glGetActiveUniform(program, i, maxNameLength, NULL, &size, &type, name);
336 }
337 free(name);
338 }
339
340 /** Given a glGetActive[Uniform|Attrib] call, obtain the location
341 * of the variable of given name in the call.
342 */
getShaderVariableLocation(GLTraceContext * context,GLMessage * glmsg,GLchar * name)343 int getShaderVariableLocation(GLTraceContext *context, GLMessage *glmsg, GLchar *name) {
344 GLMessage_Function func = glmsg->function();
345 if (func != GLMessage::glGetActiveAttrib && func != GLMessage::glGetActiveUniform) {
346 return -1;
347 }
348
349 int program = glmsg->args(0).intvalue(0);
350
351 if (func == GLMessage::glGetActiveAttrib) {
352 return context->hooks->gl.glGetAttribLocation(program, name);
353 } else {
354 return context->hooks->gl.glGetUniformLocation(program, name);
355 }
356 }
357
fixup_glGetActiveAttribOrUniform(GLTraceContext * context,GLMessage * glmsg,void * pointersToFixup[])358 void fixup_glGetActiveAttribOrUniform(GLTraceContext *context, GLMessage *glmsg,
359 void *pointersToFixup[]) {
360 /* void glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize,
361 GLsizei* length, GLint* size, GLenum* type, GLchar* name); */
362 /* void glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize,
363 GLsizei* length, GLint* size, GLenum* type, GLchar* name) */
364
365 fixup_GenericIntArray(3, 1, glmsg, pointersToFixup[0]); // length
366 fixup_GenericIntArray(4, 1, glmsg, pointersToFixup[1]); // size
367 fixup_GenericEnumArray(5, 1, glmsg, pointersToFixup[2]); // type
368 fixup_CStringPtr(6, glmsg, pointersToFixup[3]); // name
369
370 // The index argument in the glGetActive[Attrib|Uniform] functions
371 // does not correspond to the actual location index as used in
372 // glUniform*() or glVertexAttrib*() to actually upload the data.
373 // In order to make things simpler for the debugger, we also pass
374 // a hidden location argument that stores the actual location.
375 // append the location value to the end of the argument list
376 int location = getShaderVariableLocation(context, glmsg, (GLchar*)pointersToFixup[3]);
377 GLMessage_DataType *arg_location = glmsg->add_args();
378 arg_location->set_isarray(false);
379 arg_location->set_type(GLMessage::DataType::INT);
380 arg_location->add_intvalue(location);
381 }
382
glGetInteger(GLTraceContext * context,GLenum param)383 GLint glGetInteger(GLTraceContext *context, GLenum param) {
384 GLint x;
385 context->hooks->gl.glGetIntegerv(param, &x);
386 return x;
387 }
388
glGetVertexAttrib(GLTraceContext * context,GLuint index,GLenum pname)389 GLint glGetVertexAttrib(GLTraceContext *context, GLuint index, GLenum pname) {
390 GLint x;
391 context->hooks->gl.glGetVertexAttribiv(index, pname, &x);
392 return x;
393 }
394
isUsingArrayBuffers(GLTraceContext * context)395 bool isUsingArrayBuffers(GLTraceContext *context) {
396 return glGetInteger(context, GL_ARRAY_BUFFER_BINDING) != 0;
397 }
398
isUsingElementArrayBuffers(GLTraceContext * context)399 bool isUsingElementArrayBuffers(GLTraceContext *context) {
400 return glGetInteger(context, GL_ELEMENT_ARRAY_BUFFER_BINDING) != 0;
401 }
402
403 /** Copy @len bytes of data from @src into the @dataIndex'th argument of the message. */
addGlBufferData(GLMessage * glmsg,int dataIndex,GLvoid * src,GLsizeiptr len)404 void addGlBufferData(GLMessage *glmsg, int dataIndex, GLvoid *src, GLsizeiptr len) {
405 GLMessage_DataType *arg_datap = glmsg->mutable_args(dataIndex);
406 arg_datap->set_type(GLMessage::DataType::VOID);
407 arg_datap->set_isarray(true);
408 arg_datap->clear_intvalue();
409 arg_datap->add_rawbytes(src, len);
410 }
411
fixup_glBufferData(GLTraceContext * context,GLMessage * glmsg,void * pointersToFixup[])412 void fixup_glBufferData(GLTraceContext *context, GLMessage *glmsg, void *pointersToFixup[]) {
413 /* void glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) */
414 GLsizeiptr size = glmsg->args(1).intvalue(0);
415 GLvoid *datap = (GLvoid *) pointersToFixup[0];
416
417 // Save element array buffers for future use to fixup glVertexAttribPointers
418 // when a glDrawElements() call is performed.
419 GLenum target = glmsg->args(0).intvalue(0);
420 if (target == GL_ELEMENT_ARRAY_BUFFER) {
421 GLint bufferId = glGetInteger(context, GL_ELEMENT_ARRAY_BUFFER_BINDING);
422 context->bindBuffer(bufferId, datap, size);
423 }
424
425 // add buffer data to the protobuf message
426 if (datap != NULL) {
427 addGlBufferData(glmsg, 2, datap, size);
428 }
429 }
430
fixup_glBufferSubData(GLTraceContext * context,GLMessage * glmsg,void * pointersToFixup[])431 void fixup_glBufferSubData(GLTraceContext *context, GLMessage *glmsg, void *pointersToFixup[]) {
432 /* void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data) */
433 GLenum target = glmsg->args(0).intvalue(0);
434 GLintptr offset = glmsg->args(1).intvalue(0);
435 GLsizeiptr size = glmsg->args(2).intvalue(0);
436 GLvoid *datap = (GLvoid *) pointersToFixup[0];
437 if (target == GL_ELEMENT_ARRAY_BUFFER) {
438 GLint bufferId = glGetInteger(context, GL_ELEMENT_ARRAY_BUFFER_BINDING);
439 context->updateBufferSubData(bufferId, offset, datap, size);
440 }
441
442 // add buffer data to the protobuf message
443 addGlBufferData(glmsg, 3, datap, size);
444 }
445
446 /** Obtain the size of each vertex attribute. */
vertexAttribSize(GLenum type,GLsizei numComponents)447 int vertexAttribSize(GLenum type, GLsizei numComponents) {
448 int sizePerComponent;
449
450 switch(type) {
451 case GL_BYTE:
452 case GL_UNSIGNED_BYTE:
453 sizePerComponent = 1;
454 break;
455 case GL_SHORT:
456 case GL_UNSIGNED_SHORT:
457 sizePerComponent = 2;
458 break;
459 case GL_FIXED:
460 case GL_FLOAT:
461 default:
462 sizePerComponent = 4;
463 break;
464 }
465
466 return sizePerComponent * numComponents;
467 }
468
469 /** Create and send a glVertexAttribPointerData trace message to the host. */
trace_glVertexAttribPointerData(GLTraceContext * context,GLuint indx,GLint size,GLenum type,GLboolean normalized,GLsizei stride,const GLvoid * ptr,GLuint minIndex,GLuint maxIndex,nsecs_t startTime)470 void trace_glVertexAttribPointerData(GLTraceContext *context,
471 GLuint indx, GLint size, GLenum type,
472 GLboolean normalized, GLsizei stride, const GLvoid* ptr,
473 GLuint minIndex, GLuint maxIndex, nsecs_t startTime) {
474 /* void glVertexAttribPointerData(GLuint indx, GLint size, GLenum type,
475 GLboolean normalized, GLsizei stride, const GLvoid* ptr,
476 int minIndex, int maxIndex) */
477 GLMessage glmsg;
478 GLTraceContext *glContext = context;
479
480 glmsg.set_function(GLMessage::glVertexAttribPointerData);
481
482 // copy argument indx
483 GLMessage_DataType *arg_indx = glmsg.add_args();
484 arg_indx->set_isarray(false);
485 arg_indx->set_type(GLMessage::DataType::INT);
486 arg_indx->add_intvalue(indx);
487
488 // copy argument size
489 GLMessage_DataType *arg_size = glmsg.add_args();
490 arg_size->set_isarray(false);
491 arg_size->set_type(GLMessage::DataType::INT);
492 arg_size->add_intvalue(size);
493
494 // copy argument type
495 GLMessage_DataType *arg_type = glmsg.add_args();
496 arg_type->set_isarray(false);
497 arg_type->set_type(GLMessage::DataType::ENUM);
498 arg_type->add_intvalue((int)type);
499
500 // copy argument normalized
501 GLMessage_DataType *arg_normalized = glmsg.add_args();
502 arg_normalized->set_isarray(false);
503 arg_normalized->set_type(GLMessage::DataType::BOOL);
504 arg_normalized->add_boolvalue(normalized);
505
506 // copy argument stride
507 GLMessage_DataType *arg_stride = glmsg.add_args();
508 arg_stride->set_isarray(false);
509 arg_stride->set_type(GLMessage::DataType::INT);
510 arg_stride->add_intvalue(stride);
511
512 // copy argument ptr
513 GLMessage_DataType *arg_ptr = glmsg.add_args();
514 arg_ptr->set_isarray(true);
515 arg_ptr->set_type(GLMessage::DataType::BYTE);
516 int perVertexSize = vertexAttribSize(type, size);
517 GLchar *p = (GLchar*) ptr;
518 std::string data;
519 for (GLuint i = minIndex; i < maxIndex; i++) {
520 data.append(p, perVertexSize);
521 p += stride == 0 ? perVertexSize : stride;
522 }
523 arg_ptr->add_rawbytes(data);
524
525 // copy argument min index
526 GLMessage_DataType *arg_min = glmsg.add_args();
527 arg_min->set_isarray(false);
528 arg_min->set_type(GLMessage::DataType::INT);
529 arg_min->add_intvalue(minIndex);
530
531 // copy argument max index
532 GLMessage_DataType *arg_max = glmsg.add_args();
533 arg_max->set_isarray(false);
534 arg_max->set_type(GLMessage::DataType::INT);
535 arg_max->add_intvalue(maxIndex);
536
537 glmsg.set_context_id(context->getId());
538 glmsg.set_start_time(startTime);
539 glmsg.set_threadtime(0);
540 glmsg.set_duration(0);
541
542 context->traceGLMessage(&glmsg);
543 }
544
findMinAndMaxIndices(GLvoid * indices,GLsizei count,GLenum type,GLuint * minIndex,GLuint * maxIndex)545 void findMinAndMaxIndices(GLvoid *indices, GLsizei count, GLenum type,
546 GLuint *minIndex, GLuint *maxIndex) {
547 GLuint index;
548 *minIndex = UINT_MAX;
549 *maxIndex = 0;
550
551 if (indices == NULL) {
552 return;
553 }
554
555 for (GLsizei i = 0; i < count; i++) {
556 if (type == GL_UNSIGNED_BYTE) {
557 index = *((GLubyte*) indices + i);
558 } else {
559 index = *((GLushort*) indices + i);
560 }
561
562 if (index < *minIndex) *minIndex = index;
563 if (index > *maxIndex) *maxIndex = index;
564 }
565 }
566
trace_VertexAttribPointerData(GLTraceContext * context,GLuint minIndex,GLuint maxIndex,nsecs_t time)567 void trace_VertexAttribPointerData(GLTraceContext *context,
568 GLuint minIndex, GLuint maxIndex, nsecs_t time) {
569 GLuint maxAttribs = glGetInteger(context, GL_MAX_VERTEX_ATTRIBS);
570 for (GLuint index = 0; index < maxAttribs; index++) {
571 if (!glGetVertexAttrib(context, index, GL_VERTEX_ATTRIB_ARRAY_ENABLED)) {
572 // vertex array disabled
573 continue;
574 }
575
576 if (glGetVertexAttrib(context, index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING)) {
577 // vbo
578 continue;
579 }
580
581 GLint size = glGetVertexAttrib(context, index, GL_VERTEX_ATTRIB_ARRAY_SIZE);
582 GLenum type = glGetVertexAttrib(context, index, GL_VERTEX_ATTRIB_ARRAY_TYPE);
583 GLboolean norm = glGetVertexAttrib(context, index, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED);
584 GLsizei stride = glGetVertexAttrib(context, index, GL_VERTEX_ATTRIB_ARRAY_STRIDE);
585 GLvoid* ptr;
586 context->hooks->gl.glGetVertexAttribPointerv(index, GL_VERTEX_ATTRIB_ARRAY_POINTER, &ptr);
587
588 trace_glVertexAttribPointerData(context,
589 index, size, type, norm, stride, ptr,
590 minIndex, maxIndex, time);
591 }
592 }
593
trace_VertexAttribPointerDataForGlDrawArrays(GLTraceContext * context,GLMessage * glmsg)594 void trace_VertexAttribPointerDataForGlDrawArrays(GLTraceContext *context, GLMessage *glmsg) {
595 /* void glDrawArrays(GLenum mode, GLint first, GLsizei count) */
596 GLsizei count = glmsg->args(2).intvalue(0);
597
598 // Vertex attrib pointer data patchup calls should appear as if
599 // they occurred right before the draw call.
600 nsecs_t time = glmsg->start_time() - 1;
601
602 trace_VertexAttribPointerData(context, 0, count, time);
603 }
604
trace_VertexAttribPointerDataForGlDrawElements(GLTraceContext * context,GLMessage * glmsg,GLvoid * indices)605 void trace_VertexAttribPointerDataForGlDrawElements(GLTraceContext *context, GLMessage *glmsg,
606 GLvoid *indices) {
607 /* void glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) */
608 GLsizei count = glmsg->args(1).intvalue(0);
609 GLenum type = glmsg->args(2).intvalue(0);
610 GLuint index;
611
612 GLuint minIndex, maxIndex;
613
614 // The index buffer is either passed in as an argument to the glDrawElements() call,
615 // or it is stored in the current GL_ELEMENT_ARRAY_BUFFER.
616 GLvoid *indexBuffer;
617 if (isUsingElementArrayBuffers(context)) {
618 GLsizeiptr eaBufferSize;
619 GLuint bufferId = glGetInteger(context, GL_ELEMENT_ARRAY_BUFFER_BINDING);
620 context->getBuffer(bufferId, &indexBuffer, &eaBufferSize);
621 } else {
622 indexBuffer = indices;
623 }
624
625 // Rather than sending vertex attribute data that corresponds to the indices
626 // being drawn, we send the vertex attribute data for the entire range of
627 // indices being drawn, including the ones not drawn. The min & max indices
628 // provide the range of indices being drawn.
629 findMinAndMaxIndices(indexBuffer, count, type, &minIndex, &maxIndex);
630
631 // Vertex attrib pointer data patchup calls should appear as if
632 // they occurred right before the draw call.
633 nsecs_t time = glmsg->start_time() - 1;
634
635 trace_VertexAttribPointerData(context, minIndex, maxIndex + 1, time);
636 }
637
fixup_glDrawArrays(GLTraceContext * context,GLMessage * glmsg)638 void fixup_glDrawArrays(GLTraceContext *context, GLMessage *glmsg) {
639 // Trace all vertex attribute data stored in client space.
640 trace_VertexAttribPointerDataForGlDrawArrays(context, glmsg);
641
642 // Attach the FB if requested
643 if (context->getGlobalTraceState()->shouldCollectFbOnGlDraw()) {
644 fixup_addFBContents(context, glmsg, CURRENTLY_BOUND_FB);
645 }
646 }
647
fixup_glDrawElements(GLTraceContext * context,GLMessage * glmsg,void * pointersToFixup[])648 void fixup_glDrawElements(GLTraceContext *context, GLMessage *glmsg, void *pointersToFixup[]) {
649 /* void glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) */
650 GLvoid *indices = pointersToFixup[0];
651 GLenum type = glmsg->args(2).intvalue(0);
652 GLsizei count = glmsg->args(1).intvalue(0);
653 GLuint index;
654
655 // Trace all vertex attribute data stored in client space.
656 trace_VertexAttribPointerDataForGlDrawElements(context, glmsg, indices);
657
658 // Fixup indices argument
659 if (!isUsingElementArrayBuffers(context)) {
660 GLMessage_DataType *arg_indices = glmsg->mutable_args(3);
661 arg_indices->set_isarray(true);
662 arg_indices->clear_intvalue();
663 arg_indices->set_type(GLMessage::DataType::INT);
664 for (GLsizei i = 0; i < count; i++) {
665 if (type == GL_UNSIGNED_BYTE) {
666 index = *((GLubyte*) indices + i);
667 } else {
668 index = *((GLushort*) indices + i);
669 }
670 arg_indices->add_intvalue(index);
671 }
672 }
673
674 // Attach the FB if requested
675 if (context->getGlobalTraceState()->shouldCollectFbOnGlDraw()) {
676 fixup_addFBContents(context, glmsg, CURRENTLY_BOUND_FB);
677 }
678 }
679
fixupGLMessage(GLTraceContext * context,nsecs_t wallStart,nsecs_t wallEnd,nsecs_t threadStart,nsecs_t threadEnd,GLMessage * glmsg,void * pointersToFixup[])680 void fixupGLMessage(GLTraceContext *context, nsecs_t wallStart, nsecs_t wallEnd,
681 nsecs_t threadStart, nsecs_t threadEnd,
682 GLMessage *glmsg, void *pointersToFixup[]) {
683 // for all messages, set the current context id
684 glmsg->set_context_id(context->getId());
685
686 // set start time and duration
687 glmsg->set_start_time(wallStart);
688 glmsg->set_duration((unsigned)(wallEnd - wallStart));
689 glmsg->set_threadtime((unsigned)(threadEnd - threadStart));
690
691 // do any custom message dependent processing
692 switch (glmsg->function()) {
693 case GLMessage::glDeleteBuffers: /* glDeleteBuffers(GLsizei n, GLuint *buffers); */
694 case GLMessage::glDeleteFramebuffers: /* glDeleteFramebuffers(GLsizei n, GLuint *buffers); */
695 case GLMessage::glDeleteRenderbuffers:/* glDeleteRenderbuffers(GLsizei n, GLuint *buffers); */
696 case GLMessage::glDeleteTextures: /* glDeleteTextures(GLsizei n, GLuint *textures); */
697 fixup_glDeleteGeneric(glmsg, pointersToFixup);
698 break;
699 case GLMessage::glGenBuffers: /* void glGenBuffers(GLsizei n, GLuint *buffers); */
700 case GLMessage::glGenFramebuffers: /* void glGenFramebuffers(GLsizei n, GLuint *buffers); */
701 case GLMessage::glGenRenderbuffers: /* void glGenFramebuffers(GLsizei n, GLuint *buffers); */
702 case GLMessage::glGenTextures: /* void glGenTextures(GLsizei n, GLuint *textures); */
703 fixup_glGenGeneric(glmsg, pointersToFixup);
704 break;
705 case GLMessage::glLinkProgram: /* void glLinkProgram(GLuint program); */
706 fixup_glLinkProgram(glmsg);
707 break;
708 case GLMessage::glGetActiveAttrib:
709 fixup_glGetActiveAttribOrUniform(context, glmsg, pointersToFixup);
710 break;
711 case GLMessage::glGetActiveUniform:
712 fixup_glGetActiveAttribOrUniform(context, glmsg, pointersToFixup);
713 break;
714 case GLMessage::glBindAttribLocation:
715 /* void glBindAttribLocation(GLuint program, GLuint index, const GLchar* name); */
716 fixup_CStringPtr(2, glmsg, pointersToFixup[0]);
717 break;
718 case GLMessage::glGetAttribLocation:
719 case GLMessage::glGetUniformLocation:
720 /* int glGetAttribLocation(GLuint program, const GLchar* name) */
721 /* int glGetUniformLocation(GLuint program, const GLchar* name) */
722 fixup_CStringPtr(1, glmsg, pointersToFixup[0]);
723 break;
724 case GLMessage::glGetBooleanv:
725 fixup_glGetBooleanv(glmsg, pointersToFixup);
726 break;
727 case GLMessage::glGetFloatv:
728 fixup_glGetFloatv(glmsg, pointersToFixup);
729 break;
730 case GLMessage::glGetIntegerv: /* void glGetIntegerv(GLenum pname, GLint *params); */
731 fixup_GenericIntArray(1, 1, glmsg, pointersToFixup[0]);
732 break;
733 case GLMessage::glGetProgramiv:
734 case GLMessage::glGetRenderbufferParameteriv:
735 case GLMessage::glGetShaderiv:
736 /* void glGetProgramiv(GLuint program, GLenum pname, GLint* params) */
737 /* void glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params) */
738 /* void glGetShaderiv(GLuint shader, GLenum pname, GLint* params) */
739 fixup_GenericIntArray(2, 1, glmsg, pointersToFixup[0]);
740 break;
741 case GLMessage::glGetString:
742 fixup_glGetString(glmsg, pointersToFixup);
743 break;
744 case GLMessage::glTexImage2D:
745 if (context->getGlobalTraceState()->shouldCollectTextureDataOnGlTexImage()) {
746 fixup_glTexImage2D(glmsg, pointersToFixup);
747 }
748 break;
749 case GLMessage::glTexSubImage2D:
750 if (context->getGlobalTraceState()->shouldCollectTextureDataOnGlTexImage()) {
751 fixup_glTexSubImage2D(glmsg, pointersToFixup);
752 }
753 break;
754 case GLMessage::glShaderSource:
755 fixup_glShaderSource(glmsg, pointersToFixup);
756 break;
757 case GLMessage::glUniform1iv:
758 /* void glUniform1iv(GLint location, GLsizei count, const GLint *value); */
759 fixup_glUniformGenericInteger(2, 1, glmsg, pointersToFixup);
760 break;
761 case GLMessage::glUniform2iv:
762 /* void glUniform2iv(GLint location, GLsizei count, const GLint *value); */
763 fixup_glUniformGenericInteger(2, 2, glmsg, pointersToFixup);
764 break;
765 case GLMessage::glUniform3iv:
766 /* void glUniform3iv(GLint location, GLsizei count, const GLint *value); */
767 fixup_glUniformGenericInteger(2, 3, glmsg, pointersToFixup);
768 break;
769 case GLMessage::glUniform4iv:
770 /* void glUniform4iv(GLint location, GLsizei count, const GLint *value); */
771 fixup_glUniformGenericInteger(2, 4, glmsg, pointersToFixup);
772 break;
773 case GLMessage::glUniform1fv:
774 /* void glUniform1fv(GLint location, GLsizei count, const GLfloat *value); */
775 fixup_glUniformGeneric(2, 1, glmsg, pointersToFixup[0]);
776 break;
777 case GLMessage::glUniform2fv:
778 /* void glUniform2fv(GLint location, GLsizei count, const GLfloat *value); */
779 fixup_glUniformGeneric(2, 2, glmsg, pointersToFixup[0]);
780 break;
781 case GLMessage::glUniform3fv:
782 /* void glUniform3fv(GLint location, GLsizei count, const GLfloat *value); */
783 fixup_glUniformGeneric(2, 3, glmsg, pointersToFixup[0]);
784 break;
785 case GLMessage::glUniform4fv:
786 /* void glUniform4fv(GLint location, GLsizei count, const GLfloat *value); */
787 fixup_glUniformGeneric(2, 4, glmsg, pointersToFixup[0]);
788 break;
789 case GLMessage::glUniformMatrix2fv:
790 /* void glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose,
791 const GLfloat* value) */
792 fixup_glUniformMatrixGeneric(2, glmsg, pointersToFixup);
793 break;
794 case GLMessage::glUniformMatrix3fv:
795 /* void glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose,
796 const GLfloat* value) */
797 fixup_glUniformMatrixGeneric(3, glmsg, pointersToFixup);
798 break;
799 case GLMessage::glUniformMatrix4fv:
800 /* void glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose,
801 const GLfloat* value) */
802 fixup_glUniformMatrixGeneric(4, glmsg, pointersToFixup);
803 break;
804 case GLMessage::glBufferData:
805 /* void glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) */
806 fixup_glBufferData(context, glmsg, pointersToFixup);
807 break;
808 case GLMessage::glBufferSubData:
809 /* void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data) */
810 fixup_glBufferSubData(context, glmsg, pointersToFixup);
811 break;
812 case GLMessage::glDrawArrays:
813 /* void glDrawArrays(GLenum mode, GLint first, GLsizei count) */
814 fixup_glDrawArrays(context, glmsg);
815 break;
816 case GLMessage::glDrawElements:
817 /* void glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) */
818 fixup_glDrawElements(context, glmsg, pointersToFixup);
819 break;
820 case GLMessage::glPushGroupMarkerEXT:
821 /* void PushGroupMarkerEXT(sizei length, const char *marker); */
822 fixup_CStringPtr(1, glmsg, pointersToFixup[0]);
823 break;
824 case GLMessage::glInsertEventMarkerEXT:
825 /* void InsertEventMarkerEXT(sizei length, const char *marker); */
826 fixup_CStringPtr(1, glmsg, pointersToFixup[0]);
827 break;
828 default:
829 break;
830 }
831 }
832
833 };
834 };
835