gltrace_fixup.cpp revision 34c726efb54a941a97a6d7252e7c1442d2eded56
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 <GLES2/gl2.h>
19
20#include "gltrace.pb.h"
21#include "gltrace_context.h"
22#include "gltrace_fixup.h"
23
24namespace android {
25namespace gltrace {
26
27unsigned getBytesPerTexel(const GLenum format, const GLenum type) {
28    /*
29    Description from glTexImage2D spec:
30
31    Data is read from data as a sequence of unsigned bytes or shorts, depending on type.
32    When type is GL_UNSIGNED_BYTE, each of the bytes is interpreted as one color component.
33    When type is one of GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_4_4_4_4, or
34    GL_UNSIGNED_SHORT_5_5_5_1, each unsigned short value is interpreted as containing all
35    the components for a single texel, with the color components arranged according to
36    format. Color components are treated as groups of one, two, three, or four values,
37    again based on format. Groups of components are referred to as texels.
38
39    width × height texels are read from memory, starting at location data. By default,
40    these texels are taken from adjacent memory locations, except that after all width
41    texels are read, the read pointer is advanced to the next four-byte boundary.
42    The four-byte row alignment is specified by glPixelStorei with argument
43    GL_UNPACK_ALIGNMENT, and it can be set to one, two, four, or eight bytes.
44    */
45
46    switch (type) {
47    case GL_UNSIGNED_SHORT_5_6_5:
48    case GL_UNSIGNED_SHORT_4_4_4_4:
49    case GL_UNSIGNED_SHORT_5_5_5_1:
50        return 2;
51    case GL_UNSIGNED_BYTE:
52        break;
53    default:
54        ALOGE("GetBytesPerPixel: unknown type %x", type);
55    }
56
57    switch (format) {
58    case GL_ALPHA:
59    case GL_LUMINANCE:
60        return 1;
61    case GL_LUMINANCE_ALPHA:
62        return 2;
63    case GL_RGB:
64        return 3;
65    case GL_RGBA:
66    case 0x80E1: // GL_BGRA_EXT
67        return 4;
68    default:
69        ALOGE("GetBytesPerPixel: unknown format %x", format);
70    }
71
72    return 1;   // in doubt...
73}
74
75/** Generic helper function: extract pointer at argIndex and
76    replace it with the C style string at *pointer */
77void fixup_CStringPtr(int argIndex, GLMessage *glmsg) {
78    GLMessage_DataType *arg = glmsg->mutable_args(argIndex);
79    GLchar *ptr = (GLchar *)arg->intvalue(0);
80
81    arg->set_type(GLMessage::DataType::CHAR);
82    arg->set_isarray(true);
83    arg->add_charvalue(ptr);
84}
85
86void fixup_glGetString(GLMessage *glmsg) {
87    /* const GLubyte* GLTrace_glGetString(GLenum name) */
88    GLMessage_DataType *ret = glmsg->mutable_returnvalue();
89    GLchar *ptr = (GLchar *)ret->intvalue(0);
90
91    if (ptr != NULL) {
92        ret->set_type(GLMessage::DataType::CHAR);
93        ret->set_isarray(true);
94        ret->add_charvalue(ptr);
95    }
96}
97
98/* Add the contents of the framebuffer to the protobuf message */
99void fixup_addFBContents(GLTraceContext *context, GLMessage *glmsg, FBBinding fbToRead) {
100    void *fbcontents;
101    unsigned fbsize, fbwidth, fbheight;
102    context->getCompressedFB(&fbcontents, &fbsize, &fbwidth, &fbheight, fbToRead);
103
104    GLMessage_FrameBuffer *fb = glmsg->mutable_fb();
105    fb->set_width(fbwidth);
106    fb->set_height(fbheight);
107    fb->add_contents(fbcontents, fbsize);
108}
109
110/** Common fixup routing for glTexImage2D & glTexSubImage2D. */
111void fixup_glTexImage(int widthIndex, int heightIndex, GLMessage *glmsg) {
112    GLMessage_DataType arg_width  = glmsg->args(widthIndex);
113    GLMessage_DataType arg_height = glmsg->args(heightIndex);
114
115    GLMessage_DataType arg_format = glmsg->args(6);
116    GLMessage_DataType arg_type   = glmsg->args(7);
117    GLMessage_DataType *arg_data  = glmsg->mutable_args(8);
118
119    GLsizei width  = arg_width.intvalue(0);
120    GLsizei height = arg_height.intvalue(0);
121    GLenum format  = arg_format.intvalue(0);
122    GLenum type    = arg_type.intvalue(0);
123    void *data     = (void *)arg_data->intvalue(0);
124
125    int bytesPerTexel = getBytesPerTexel(format, type);
126
127    arg_data->set_type(GLMessage::DataType::BYTE);
128    arg_data->clear_rawbytes();
129
130    if (data != NULL) {
131        arg_data->set_isarray(true);
132        arg_data->add_rawbytes(data, bytesPerTexel * width * height);
133    } else {
134        arg_data->set_isarray(false);
135        arg_data->set_type(GLMessage::DataType::VOID);
136    }
137}
138
139
140void fixup_glTexImage2D(GLMessage *glmsg) {
141    /* void glTexImage2D(GLenum target,
142                        GLint level,
143                        GLint internalformat,
144                        GLsizei width,
145                        GLsizei height,
146                        GLint border,
147                        GLenum format,
148                        GLenum type,
149                        const GLvoid *data);
150    */
151    int widthIndex = 3;
152    int heightIndex = 4;
153    fixup_glTexImage(widthIndex, heightIndex, glmsg);
154}
155
156void fixup_glTexSubImage2D(GLMessage *glmsg) {
157    /*
158    void glTexSubImage2D(GLenum target,
159                        GLint level,
160                        GLint xoffset,
161                        GLint yoffset,
162                        GLsizei width,
163                        GLsizei height,
164                        GLenum format,
165                        GLenum type,
166                        const GLvoid * data);
167    */
168    int widthIndex = 4;
169    int heightIndex = 5;
170    fixup_glTexImage(widthIndex, heightIndex, glmsg);
171}
172
173void fixup_glShaderSource(GLMessage *glmsg) {
174    /* void glShaderSource(GLuint shader, GLsizei count, const GLchar** string,
175                                    const GLint* length) */
176    GLMessage_DataType arg_count  = glmsg->args(1);
177    GLMessage_DataType arg_lenp   = glmsg->args(3);
178    GLMessage_DataType *arg_strpp = glmsg->mutable_args(2);
179
180    GLsizei count = arg_count.intvalue(0);
181    GLchar **stringpp = (GLchar **)arg_strpp->intvalue(0);
182    GLint *lengthp = (GLint *)arg_lenp.intvalue(0);
183
184    arg_strpp->set_type(GLMessage::DataType::CHAR);
185    arg_strpp->set_isarray(true);
186    arg_strpp->clear_charvalue();
187
188    ::std::string src = "";
189    for (int i = 0; i < count; i++) {
190        if (lengthp != NULL)
191            src.append(*stringpp, *lengthp);
192        else
193            src.append(*stringpp);  // assume null terminated
194        stringpp++;
195        lengthp++;
196    }
197
198    arg_strpp->add_charvalue(src);
199}
200
201void fixup_glUniformGeneric(int argIndex, int nFloats, GLMessage *glmsg) {
202    GLMessage_DataType *arg_values = glmsg->mutable_args(argIndex);
203    GLfloat *src = (GLfloat*)arg_values->intvalue(0);
204
205    arg_values->set_type(GLMessage::DataType::FLOAT);
206    arg_values->set_isarray(true);
207    arg_values->clear_floatvalue();
208
209    for (int i = 0; i < nFloats; i++) {
210        arg_values->add_floatvalue(*src++);
211    }
212}
213
214void fixup_glUniformMatrixGeneric(int matrixSize, GLMessage *glmsg) {
215    /* void glUniformMatrix?fv(GLint location, GLsizei count, GLboolean transpose,
216                                                                const GLfloat* value) */
217    GLMessage_DataType arg_count  = glmsg->args(1);
218    int n_matrices = arg_count.intvalue(0);
219    fixup_glUniformGeneric(3, matrixSize * matrixSize * n_matrices, glmsg);
220}
221
222void fixup_GenericIntArray(int argIndex, int nInts, GLMessage *glmsg) {
223    GLMessage_DataType *arg_intarray = glmsg->mutable_args(argIndex);
224    GLint *intp = (GLint *)arg_intarray->intvalue(0);
225
226    arg_intarray->set_type(GLMessage::DataType::INT);
227    arg_intarray->set_isarray(true);
228    arg_intarray->clear_intvalue();
229
230    for (int i = 0; i < nInts; i++, intp++) {
231        arg_intarray->add_intvalue(*intp);
232    }
233}
234
235void fixup_glGenGeneric(GLMessage *glmsg) {
236    /* void glGen*(GLsizei n, GLuint * buffers); */
237    GLMessage_DataType arg_n  = glmsg->args(0);
238    GLsizei n = arg_n.intvalue(0);
239
240    fixup_GenericIntArray(1, n, glmsg);
241}
242
243void fixup_glDeleteGeneric(GLMessage *glmsg) {
244    /* void glDelete*(GLsizei n, GLuint *buffers); */
245    GLMessage_DataType arg_n  = glmsg->args(0);
246    GLsizei n = arg_n.intvalue(0);
247
248    fixup_GenericIntArray(1, n, glmsg);
249}
250
251void fixup_glGetBooleanv(GLMessage *glmsg) {
252    /* void glGetBooleanv(GLenum pname, GLboolean *params); */
253    GLMessage_DataType *arg_params = glmsg->mutable_args(1);
254    GLboolean *src = (GLboolean*)arg_params->intvalue(0);
255
256    arg_params->set_type(GLMessage::DataType::BOOL);
257    arg_params->set_isarray(true);
258    arg_params->clear_boolvalue();
259    arg_params->add_boolvalue(*src);
260}
261
262void fixup_glGetFloatv(GLMessage *glmsg) {
263    /* void glGetFloatv(GLenum pname, GLfloat *params); */
264    GLMessage_DataType *arg_params = glmsg->mutable_args(1);
265    GLfloat *src = (GLfloat*)arg_params->intvalue(0);
266
267    arg_params->set_type(GLMessage::DataType::FLOAT);
268    arg_params->set_isarray(true);
269    arg_params->clear_floatvalue();
270    arg_params->add_floatvalue(*src);
271}
272
273void fixupGLMessage(GLTraceContext *context, nsecs_t start, nsecs_t end, GLMessage *glmsg) {
274    // for all messages, set the current context id
275    glmsg->set_context_id(context->getId());
276
277    // set start time and duration
278    glmsg->set_start_time(start);
279    glmsg->set_duration((unsigned)(end - start));
280
281    // do any custom message dependent processing
282    switch (glmsg->function()) {
283    case GLMessage::glDeleteBuffers:      /* glDeleteBuffers(GLsizei n, GLuint *buffers); */
284    case GLMessage::glDeleteFramebuffers: /* glDeleteFramebuffers(GLsizei n, GLuint *buffers); */
285    case GLMessage::glDeleteRenderbuffers:/* glDeleteRenderbuffers(GLsizei n, GLuint *buffers); */
286    case GLMessage::glDeleteTextures:     /* glDeleteTextures(GLsizei n, GLuint *textures); */
287        fixup_glDeleteGeneric(glmsg);
288        break;
289    case GLMessage::glGenBuffers:        /* void glGenBuffers(GLsizei n, GLuint *buffers); */
290    case GLMessage::glGenFramebuffers:   /* void glGenFramebuffers(GLsizei n, GLuint *buffers); */
291    case GLMessage::glGenRenderbuffers:  /* void glGenFramebuffers(GLsizei n, GLuint *buffers); */
292    case GLMessage::glGenTextures:       /* void glGenTextures(GLsizei n, GLuint *textures); */
293        fixup_glGenGeneric(glmsg);
294        break;
295    case GLMessage::glGetAttribLocation:
296    case GLMessage::glGetUniformLocation:
297        /* int glGetAttribLocation(GLuint program, const GLchar* name) */
298        /* int glGetUniformLocation(GLuint program, const GLchar* name) */
299        fixup_CStringPtr(1, glmsg);
300        break;
301    case GLMessage::glGetBooleanv:
302        fixup_glGetBooleanv(glmsg);
303        break;
304    case GLMessage::glGetFloatv:
305        fixup_glGetFloatv(glmsg);
306        break;
307    case GLMessage::glGetIntegerv:        /* void glGetIntegerv(GLenum pname, GLint *params); */
308        fixup_GenericIntArray(1, 1, glmsg);
309        break;
310    case GLMessage::glGetProgramiv:
311    case GLMessage::glGetRenderbufferParameteriv:
312    case GLMessage::glGetShaderiv:
313        /* void glGetProgramiv(GLuint program, GLenum pname, GLint* params) */
314        /* void glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params) */
315        /* void glGetShaderiv(GLuint shader, GLenum pname, GLint* params) */
316        fixup_GenericIntArray(2, 1, glmsg);
317        break;
318    case GLMessage::glGetString:
319        fixup_glGetString(glmsg);
320        break;
321    case GLMessage::glTexImage2D:
322        if (context->getGlobalTraceState()->shouldCollectTextureDataOnGlTexImage()) {
323            fixup_glTexImage2D(glmsg);
324        }
325        break;
326    case GLMessage::glTexSubImage2D:
327        if (context->getGlobalTraceState()->shouldCollectTextureDataOnGlTexImage()) {
328            fixup_glTexSubImage2D(glmsg);
329        }
330        break;
331    case GLMessage::glShaderSource:
332        fixup_glShaderSource(glmsg);
333        break;
334    case GLMessage::glUniformMatrix2fv:
335        /* void glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose,
336                                                                    const GLfloat* value) */
337        fixup_glUniformMatrixGeneric(2, glmsg);
338        break;
339    case GLMessage::glUniformMatrix3fv:
340        /* void glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose,
341                                                                    const GLfloat* value) */
342        fixup_glUniformMatrixGeneric(3, glmsg);
343        break;
344    case GLMessage::glUniformMatrix4fv:
345        /* void glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose,
346                                                                    const GLfloat* value) */
347        fixup_glUniformMatrixGeneric(4, glmsg);
348        break;
349    case GLMessage::glDrawArrays:
350        /* void glDrawArrays(GLenum mode, GLint first, GLsizei count) */
351        if (context->getGlobalTraceState()->shouldCollectFbOnGlDraw()) {
352            fixup_addFBContents(context, glmsg, CURRENTLY_BOUND_FB);
353        }
354        break;
355    case GLMessage::glDrawElements:
356        /* void glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) */
357        if (context->getGlobalTraceState()->shouldCollectFbOnGlDraw()) {
358            fixup_addFBContents(context, glmsg, CURRENTLY_BOUND_FB);
359        }
360        break;
361    default:
362        break;
363    }
364}
365
366};
367};
368