gltrace_fixup.cpp revision 0469dd6d55fa331bfd7de9431da98b6340d82271
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        LOGE("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        LOGE("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 as an argument */
99void fixup_addFBContents(GLMessage *glmsg) {
100    GLMessage_DataType *arg_fb = glmsg->add_args();    /* Add the FB as the last argument */
101    GLTraceContext *glContext = getGLTraceContext();
102
103    void *fb;
104    unsigned fbsize, fbwidth, fbheight;
105    glContext->getCompressedFB(&fb, &fbsize, &fbwidth, &fbheight);
106
107    arg_fb->set_isarray(true);
108    arg_fb->set_type(GLMessage::DataType::BYTE);
109    arg_fb->add_rawbytes(fb, fbsize);
110    arg_fb->add_intvalue(fbwidth);
111    arg_fb->add_intvalue(fbheight);
112}
113
114void fixup_glTexImage2D(GLMessage *glmsg) {
115    /* void glTexImage2D(GLenum target,
116                        GLint level,
117                        GLint internalformat,
118                        GLsizei width,
119                        GLsizei height,
120                        GLint border,
121                        GLenum format,
122                        GLenum type,
123                        const GLvoid *data);
124     */
125    GLMessage_DataType arg_width  = glmsg->args(3);
126    GLMessage_DataType arg_height = glmsg->args(4);
127    GLMessage_DataType arg_format = glmsg->args(6);
128    GLMessage_DataType arg_type   = glmsg->args(7);
129    GLMessage_DataType *arg_data  = glmsg->mutable_args(8);
130
131    GLsizei width  = arg_width.intvalue(0);
132    GLsizei height = arg_height.intvalue(0);
133    GLenum format  = arg_format.intvalue(0);
134    GLenum type    = arg_type.intvalue(0);
135    void *data     = (void *)arg_data->intvalue(0);
136
137    int bytesPerTexel = getBytesPerTexel(format, type);
138
139    arg_data->set_type(GLMessage::DataType::BYTE);
140    arg_data->set_isarray(true);
141    arg_data->clear_rawbytes();
142
143    if (data != NULL) {
144        arg_data->add_rawbytes(data, bytesPerTexel * width * height);
145    } else {
146        LOGE("fixup_glTexImage2D: image data is NULL.\n");
147        arg_data->set_type(GLMessage::DataType::VOID);
148        // FIXME:
149        // This will create the texture, but it will be uninitialized.
150        // It can later be initialized with glTexSubImage2D or by
151        // attaching an FBO to it and rendering into the FBO.
152    }
153}
154
155void fixup_glShaderSource(GLMessage *glmsg) {
156    /* void glShaderSource(GLuint shader, GLsizei count, const GLchar** string,
157                                    const GLint* length) */
158    GLMessage_DataType arg_count  = glmsg->args(1);
159    GLMessage_DataType arg_lenp   = glmsg->args(3);
160    GLMessage_DataType *arg_strpp = glmsg->mutable_args(2);
161
162    GLsizei count = arg_count.intvalue(0);
163    GLchar **stringpp = (GLchar **)arg_strpp->intvalue(0);
164    GLint *lengthp = (GLint *)arg_lenp.intvalue(0);
165
166    arg_strpp->set_type(GLMessage::DataType::CHAR);
167    arg_strpp->set_isarray(true);
168    arg_strpp->clear_charvalue();
169
170    ::std::string src = "";
171    for (int i = 0; i < count; i++) {
172        if (lengthp != NULL)
173            src.append(*stringpp, *lengthp);
174        else
175            src.append(*stringpp);  // assume null terminated
176        stringpp++;
177        lengthp++;
178    }
179
180    arg_strpp->add_charvalue(src);
181}
182
183void fixup_glUniformGeneric(int argIndex, int nFloats, GLMessage *glmsg) {
184    GLMessage_DataType *arg_values = glmsg->mutable_args(argIndex);
185    GLfloat *src = (GLfloat*)arg_values->intvalue(0);
186
187    arg_values->set_type(GLMessage::DataType::FLOAT);
188    arg_values->set_isarray(true);
189    arg_values->clear_floatvalue();
190
191    for (int i = 0; i < nFloats; i++) {
192        arg_values->add_floatvalue(*src++);
193    }
194}
195
196void fixup_glUniformMatrixGeneric(int matrixSize, GLMessage *glmsg) {
197    /* void glUniformMatrix?fv(GLint location, GLsizei count, GLboolean transpose,
198                                                                const GLfloat* value) */
199    GLMessage_DataType arg_count  = glmsg->args(1);
200    int n_matrices = arg_count.intvalue(0);
201    fixup_glUniformGeneric(3, matrixSize * matrixSize * n_matrices, glmsg);
202}
203
204void fixup_GenericIntArray(int argIndex, int nInts, GLMessage *glmsg) {
205    GLMessage_DataType *arg_intarray = glmsg->mutable_args(argIndex);
206    GLint *intp = (GLint *)arg_intarray->intvalue(0);
207
208    arg_intarray->set_type(GLMessage::DataType::INT);
209    arg_intarray->set_isarray(true);
210    arg_intarray->clear_intvalue();
211
212    for (int i = 0; i < nInts; i++, intp++) {
213        arg_intarray->add_intvalue(*intp);
214    }
215}
216
217void fixup_glGenGeneric(GLMessage *glmsg) {
218    /* void glGen*(GLsizei n, GLuint * buffers); */
219    GLMessage_DataType arg_n  = glmsg->args(0);
220    GLsizei n = arg_n.intvalue(0);
221
222    fixup_GenericIntArray(1, n, glmsg);
223}
224
225void fixup_glGetBooleanv(GLMessage *glmsg) {
226    /* void glGetBooleanv(GLenum pname, GLboolean *params); */
227    GLMessage_DataType *arg_params = glmsg->mutable_args(1);
228    GLboolean *src = (GLboolean*)arg_params->intvalue(0);
229
230    arg_params->set_type(GLMessage::DataType::BOOL);
231    arg_params->set_isarray(true);
232    arg_params->clear_boolvalue();
233    arg_params->add_boolvalue(*src);
234}
235
236void fixup_glGetFloatv(GLMessage *glmsg) {
237    /* void glGetFloatv(GLenum pname, GLfloat *params); */
238    GLMessage_DataType *arg_params = glmsg->mutable_args(1);
239    GLfloat *src = (GLfloat*)arg_params->intvalue(0);
240
241    arg_params->set_type(GLMessage::DataType::FLOAT);
242    arg_params->set_isarray(true);
243    arg_params->clear_floatvalue();
244    arg_params->add_floatvalue(*src);
245}
246
247void fixupGLMessage(GLMessage *glmsg) {
248    switch (glmsg->function()) {
249    case GLMessage::glGenBuffers:        /* void glGenBuffers(GLsizei n, GLuint * buffers); */
250    case GLMessage::glGenFramebuffers:   /* void glGenFramebuffers(GLsizei n, GLuint * buffers); */
251    case GLMessage::glGenRenderbuffers:  /* void glGenFramebuffers(GLsizei n, GLuint * buffers); */
252    case GLMessage::glGenTextures:       /* void glGenTextures(GLsizei n, GLuint * buffers); */
253        fixup_glGenGeneric(glmsg);
254        break;
255    case GLMessage::glGetAttribLocation:
256    case GLMessage::glGetUniformLocation:
257        /* int glGetAttribLocation(GLuint program, const GLchar* name) */
258        /* int glGetUniformLocation(GLuint program, const GLchar* name) */
259        fixup_CStringPtr(1, glmsg);
260        break;
261    case GLMessage::glGetBooleanv:
262        fixup_glGetBooleanv(glmsg);
263        break;
264    case GLMessage::glGetFloatv:
265        fixup_glGetFloatv(glmsg);
266        break;
267    case GLMessage::glGetIntegerv:        /* void glGetIntegerv(GLenum pname, GLint *params); */
268        fixup_GenericIntArray(1, 1, glmsg);
269        break;
270    case GLMessage::glGetProgramiv:
271    case GLMessage::glGetRenderbufferParameteriv:
272    case GLMessage::glGetShaderiv:
273        /* void glGetProgramiv(GLuint program, GLenum pname, GLint* params) */
274        /* void glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params) */
275        /* void glGetShaderiv(GLuint shader, GLenum pname, GLint* params) */
276        fixup_GenericIntArray(2, 1, glmsg);
277        break;
278    case GLMessage::glGetString:
279        fixup_glGetString(glmsg);
280        break;
281    case GLMessage::glTexImage2D:
282        fixup_glTexImage2D(glmsg);
283        break;
284    case GLMessage::glShaderSource:
285        fixup_glShaderSource(glmsg);
286        break;
287    case GLMessage::glUniformMatrix2fv:
288        /* void glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose,
289                                                                    const GLfloat* value) */
290        fixup_glUniformMatrixGeneric(2, glmsg);
291        break;
292    case GLMessage::glUniformMatrix3fv:
293        /* void glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose,
294                                                                    const GLfloat* value) */
295        fixup_glUniformMatrixGeneric(3, glmsg);
296        break;
297    case GLMessage::glUniformMatrix4fv:
298        /* void glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose,
299                                                                    const GLfloat* value) */
300        fixup_glUniformMatrixGeneric(4, glmsg);
301        break;
302    case GLMessage::glDrawArrays:
303    case GLMessage::glDrawElements:
304        /* void glDrawArrays(GLenum mode, GLint first, GLsizei count) */
305        /* void glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) */
306        fixup_addFBContents(glmsg);
307        break;
308    default:
309        break;
310    }
311}
312
313};
314};
315