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
19 namespace android
20 {
21 bool capture; // capture after each glDraw*
22 }
23
Debug_glDrawArrays(GLenum mode,GLint first,GLsizei count)24 void 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
108 template<typename T>
FetchIndexed(const unsigned count,const T * indices,std::string * const data,const DbgContext * const ctx)109 static 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
Debug_glDrawElements(GLenum mode,GLsizei count,GLenum type,const GLvoid * indices)120 void 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