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 "header.h"
18
19namespace android
20{
21bool capture; // capture after each glDraw*
22}
23
24void Debug_glDrawArrays(GLenum mode, GLint first, GLsizei count)
25{
26    DbgContext * const dbg = getDbgContextThreadSpecific();
27    glesv2debugger::Message msg, cmd;
28    msg.set_context_id(reinterpret_cast<int>(dbg));
29    msg.set_type(glesv2debugger::Message_Type_BeforeCall);
30    bool expectResponse = dbg->expectResponse.Bit(glesv2debugger::Message_Function_glDrawArrays);
31    msg.set_expect_response(expectResponse);
32    msg.set_function(glesv2debugger::Message_Function_glDrawArrays);
33    msg.set_arg0(mode);
34    msg.set_arg1(first);
35    msg.set_arg2(count);
36
37    msg.set_arg7(dbg->maxAttrib); // indicate capturing vertex data
38    if (dbg->hasNonVBOAttribs) {
39        std::string * const data = msg.mutable_data();
40        for (unsigned i = 0; i < count; i++)
41            dbg->Fetch(i + first, data);
42    }
43
44    void * pixels = NULL;
45    int viewport[4] = {};
46    cmd.set_function(glesv2debugger::Message_Function_CONTINUE);
47    cmd.set_expect_response(expectResponse);
48    glesv2debugger::Message_Function oldCmd = cmd.function();
49    Send(msg, cmd);
50    expectResponse = cmd.expect_response();
51    while (true) {
52        msg.Clear();
53        nsecs_t c0 = systemTime(timeMode);
54        switch (cmd.function()) {
55        case glesv2debugger::Message_Function_CONTINUE:
56            dbg->hooks->gl.glDrawArrays(mode, first, count);
57            msg.set_time((systemTime(timeMode) - c0) * 1e-6f);
58            msg.set_context_id(reinterpret_cast<int>(dbg));
59            msg.set_function(glesv2debugger::Message_Function_glDrawArrays);
60            msg.set_type(glesv2debugger::Message_Type_AfterCall);
61            msg.set_expect_response(expectResponse);
62            if (!expectResponse) {
63                cmd.set_function(glesv2debugger::Message_Function_SKIP);
64                cmd.set_expect_response(false);
65            }
66            oldCmd = cmd.function();
67            Send(msg, cmd);
68            expectResponse = cmd.expect_response();
69            // TODO: pack glReadPixels data with vertex data instead of
70            //  relying on sperate call for transport, this would allow
71            //  auto generated message loop using EXTEND_Debug macro
72            if (dbg->captureDraw > 0) {
73                dbg->captureDraw--;
74                dbg->hooks->gl.glGetIntegerv(GL_VIEWPORT, viewport);
75//                LOGD("glDrawArrays CAPTURE: x=%d y=%d width=%d height=%d format=0x%.4X type=0x%.4X",
76//                     viewport[0], viewport[1], viewport[2], viewport[3], readFormat, readType);
77                pixels = dbg->GetReadPixelsBuffer(viewport[2] * viewport[3] *
78                                                  dbg->readBytesPerPixel);
79                Debug_glReadPixels(viewport[0], viewport[1], viewport[2], viewport[3],
80                        GL_RGBA, GL_UNSIGNED_BYTE, pixels);
81            }
82            break;
83        case glesv2debugger::Message_Function_SKIP:
84            return;
85        case glesv2debugger::Message_Function_SETPROP:
86            SetProp(dbg, cmd);
87            expectResponse = cmd.expect_response();
88            if (!expectResponse) // SETPROP is "out of band"
89                cmd.set_function(oldCmd);
90            else
91                Receive(cmd);
92            break;
93        default:
94            GenerateCall(dbg, cmd, msg, NULL);
95            msg.set_expect_response(expectResponse);
96            if (!expectResponse) {
97                cmd.set_function(cmd.SKIP);
98                cmd.set_expect_response(expectResponse);
99            }
100            oldCmd = cmd.function();
101            Send(msg, cmd);
102            expectResponse = cmd.expect_response();
103            break;
104        }
105    }
106}
107
108template<typename T>
109static inline void FetchIndexed(const unsigned count, const T * indices,
110                                std::string * const data, const DbgContext * const ctx)
111{
112    for (unsigned i = 0; i < count; i++) {
113        if (!ctx->indexBuffer)
114            data->append((const char *)(indices + i), sizeof(*indices));
115        if (ctx->hasNonVBOAttribs)
116            ctx->Fetch(indices[i], data);
117    }
118}
119
120void Debug_glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices)
121{
122    DbgContext * const dbg = getDbgContextThreadSpecific();
123    glesv2debugger::Message msg, cmd;
124    msg.set_context_id(reinterpret_cast<int>(dbg));
125    msg.set_type(glesv2debugger::Message_Type_BeforeCall);
126    bool expectResponse = dbg->expectResponse.Bit(glesv2debugger::Message_Function_glDrawElements);
127    msg.set_expect_response(expectResponse);
128    msg.set_function(glesv2debugger::Message_Function_glDrawElements);
129    msg.set_arg0(mode);
130    msg.set_arg1(count);
131    msg.set_arg2(type);
132    msg.set_arg3(reinterpret_cast<int>(indices));
133
134    msg.set_arg7(dbg->maxAttrib); // indicate capturing vertex data
135    std::string * const data = msg.mutable_data();
136    if (GL_UNSIGNED_BYTE == type) {
137        if (dbg->indexBuffer) {
138            FetchIndexed(count, (unsigned char *)dbg->indexBuffer->data +
139                         (unsigned long)indices, data, dbg);
140        } else {
141            FetchIndexed(count, (unsigned char *)indices, data, dbg);
142        }
143    } else if (GL_UNSIGNED_SHORT == type) {
144        if (dbg->indexBuffer) {
145            FetchIndexed(count, (unsigned short *)((char *)dbg->indexBuffer->data +
146                                                   (unsigned long)indices), data, dbg);
147        } else {
148            FetchIndexed(count, (unsigned short *)indices, data, dbg);
149        }
150    } else {
151        assert(0);
152    }
153
154    void * pixels = NULL;
155    int viewport[4] = {};
156    cmd.set_function(glesv2debugger::Message_Function_CONTINUE);
157    cmd.set_expect_response(expectResponse);
158    glesv2debugger::Message_Function oldCmd = cmd.function();
159    Send(msg, cmd);
160    expectResponse = cmd.expect_response();
161    while (true) {
162        msg.Clear();
163        nsecs_t c0 = systemTime(timeMode);
164        switch (cmd.function()) {
165        case glesv2debugger::Message_Function_CONTINUE:
166            dbg->hooks->gl.glDrawElements(mode, count, type, indices);
167            msg.set_time((systemTime(timeMode) - c0) * 1e-6f);
168            msg.set_context_id(reinterpret_cast<int>(dbg));
169            msg.set_function(glesv2debugger::Message_Function_glDrawElements);
170            msg.set_type(glesv2debugger::Message_Type_AfterCall);
171            msg.set_expect_response(expectResponse);
172            if (!expectResponse) {
173                cmd.set_function(glesv2debugger::Message_Function_SKIP);
174                cmd.set_expect_response(false);
175            }
176            oldCmd = cmd.function();
177            Send(msg, cmd);
178            expectResponse = cmd.expect_response();
179            // TODO: pack glReadPixels data with vertex data instead of
180            //  relying on separate call for transport, this would allow
181            //  auto generated message loop using EXTEND_Debug macro
182            if (dbg->captureDraw > 0) {
183                dbg->captureDraw--;
184                dbg->hooks->gl.glGetIntegerv(GL_VIEWPORT, viewport);
185                pixels = dbg->GetReadPixelsBuffer(viewport[2] * viewport[3] *
186                                                  dbg->readBytesPerPixel);
187                Debug_glReadPixels(viewport[0], viewport[1], viewport[2], viewport[3],
188                        GL_RGBA, GL_UNSIGNED_BYTE, pixels);
189            }
190            break;
191        case glesv2debugger::Message_Function_SKIP:
192            return;
193        case glesv2debugger::Message_Function_SETPROP:
194            SetProp(dbg, cmd);
195            expectResponse = cmd.expect_response();
196            if (!expectResponse) // SETPROP is "out of band"
197                cmd.set_function(oldCmd);
198            else
199                Receive(cmd);
200            break;
201        default:
202            GenerateCall(dbg, cmd, msg, NULL);
203            msg.set_expect_response(expectResponse);
204            if (!expectResponse) {
205                cmd.set_function(cmd.SKIP);
206                cmd.set_expect_response(expectResponse);
207            }
208            oldCmd = cmd.function();
209            Send(msg, cmd);
210            expectResponse = cmd.expect_response();
211            break;
212        }
213    }
214}
215