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