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 package com.android.ide.eclipse.gldebugger; 18 19 import com.android.ide.eclipse.gldebugger.DebuggerMessage.Message; 20 import com.android.sdklib.util.SparseArray; 21 22 import java.nio.ByteBuffer; 23 24 class GLBuffer implements Cloneable { 25 public final int name; 26 public GLEnum usage; 27 public GLEnum target; 28 /** in SampleView.targetByteOrder */ 29 public ByteBuffer data; 30 31 public GLBuffer(final int name) { 32 this.name = name; 33 } 34 35 /** deep copy */ 36 @Override 37 public GLBuffer clone() { 38 try { 39 GLBuffer copy = (GLBuffer) super.clone(); 40 if (data != null) { 41 copy.data = ByteBuffer.allocate(data.capacity()); 42 copy.data.order(GLFramesView.TARGET_BYTE_ORDER); 43 data.position(0); 44 copy.data.put(data); 45 } 46 return copy; 47 } catch (CloneNotSupportedException e) { 48 e.printStackTrace(); 49 assert false; 50 return null; 51 } 52 } 53 } 54 55 class GLAttribPointer implements Cloneable { 56 public int size; // number of values per vertex 57 public GLEnum type; // data type 58 public int stride; // bytes 59 /** 60 * element stride in bytes, used when fetching from buffer; not for fetching 61 * from user pointer since server already packed elements 62 */ 63 int elemStride; // in bytes 64 /** element size in bytes */ 65 int elemSize; 66 public int ptr; // pointer in debugger server or byte offset into buffer 67 public GLBuffer buffer; 68 public boolean normalized; 69 public boolean enabled; 70 71 /** deep copy, re-maps buffer into copyBuffers */ 72 public GLAttribPointer clone(SparseArray<GLBuffer> copyBuffers) { 73 try { 74 GLAttribPointer copy = (GLAttribPointer) super.clone(); 75 if (buffer != null) 76 copy.buffer = copyBuffers.get(buffer.name); 77 return copy; 78 } catch (CloneNotSupportedException e) { 79 e.printStackTrace(); 80 assert false; 81 return null; 82 } 83 } 84 } 85 86 public class GLServerVertex implements Cloneable { 87 public SparseArray<GLBuffer> buffers = new SparseArray<GLBuffer>(); 88 public GLBuffer attribBuffer, indexBuffer; // current binding 89 public GLAttribPointer attribPointers[]; 90 public float defaultAttribs[][]; 91 92 public GLServerVertex(final int MAX_VERTEX_ATTRIBS) { 93 buffers.append(0, null); 94 attribPointers = new GLAttribPointer[MAX_VERTEX_ATTRIBS]; 95 for (int i = 0; i < attribPointers.length; i++) 96 attribPointers[i] = new GLAttribPointer(); 97 defaultAttribs = new float[MAX_VERTEX_ATTRIBS][4]; 98 for (int i = 0; i < defaultAttribs.length; i++) { 99 defaultAttribs[i][0] = 0; 100 defaultAttribs[i][1] = 0; 101 defaultAttribs[i][2] = 0; 102 defaultAttribs[i][3] = 1; 103 } 104 } 105 106 /** deep copy */ 107 @Override 108 public GLServerVertex clone() { 109 try { 110 GLServerVertex copy = (GLServerVertex) super.clone(); 111 112 copy.buffers = new SparseArray<GLBuffer>(buffers.size()); 113 for (int i = 0; i < buffers.size(); i++) 114 if (buffers.valueAt(i) != null) 115 copy.buffers.append(buffers.keyAt(i), buffers.valueAt(i).clone()); 116 else 117 copy.buffers.append(buffers.keyAt(i), null); 118 119 if (attribBuffer != null) 120 copy.attribBuffer = copy.buffers.get(attribBuffer.name); 121 if (indexBuffer != null) 122 copy.indexBuffer = copy.buffers.get(indexBuffer.name); 123 124 copy.attribPointers = new GLAttribPointer[attribPointers.length]; 125 for (int i = 0; i < attribPointers.length; i++) 126 copy.attribPointers[i] = attribPointers[i].clone(copy.buffers); 127 128 copy.defaultAttribs = defaultAttribs.clone(); 129 130 return copy; 131 } catch (CloneNotSupportedException e) { 132 e.printStackTrace(); 133 assert false; 134 return null; 135 } 136 } 137 138 /** returns true if processed */ 139 public boolean process(final Message msg) { 140 switch (msg.getFunction()) { 141 case glBindBuffer: 142 glBindBuffer(msg); 143 return true; 144 case glBufferData: 145 glBufferData(msg); 146 return true; 147 case glBufferSubData: 148 glBufferSubData(msg); 149 return true; 150 case glDeleteBuffers: 151 glDeleteBuffers(msg); 152 return true; 153 case glDrawArrays: 154 case glDrawElements: 155 return true; 156 case glDisableVertexAttribArray: 157 glDisableVertexAttribArray(msg); 158 return true; 159 case glEnableVertexAttribArray: 160 glEnableVertexAttribArray(msg); 161 return true; 162 case glGenBuffers: 163 glGenBuffers(msg); 164 return true; 165 case glVertexAttribPointer: 166 glVertexAttribPointer(msg); 167 return true; 168 case glVertexAttrib1f: 169 glVertexAttrib1f(msg); 170 return true; 171 case glVertexAttrib1fv: 172 glVertexAttrib1fv(msg); 173 return true; 174 case glVertexAttrib2f: 175 glVertexAttrib2f(msg); 176 return true; 177 case glVertexAttrib2fv: 178 glVertexAttrib2fv(msg); 179 return true; 180 case glVertexAttrib3f: 181 glVertexAttrib3f(msg); 182 return true; 183 case glVertexAttrib3fv: 184 glVertexAttrib3fv(msg); 185 return true; 186 case glVertexAttrib4f: 187 glVertexAttrib4f(msg); 188 return true; 189 case glVertexAttrib4fv: 190 glVertexAttrib4fv(msg); 191 return true; 192 default: 193 return false; 194 } 195 } 196 197 // void API_ENTRY(glBindBuffer)(GLenum target, GLuint buffer) 198 public void glBindBuffer(Message msg) { 199 if (GLEnum.valueOf(msg.getArg0()) == GLEnum.GL_ARRAY_BUFFER) { 200 attribBuffer = buffers.get(msg.getArg1()); 201 if (null != attribBuffer) 202 attribBuffer.target = GLEnum.GL_ARRAY_BUFFER; 203 } else if (GLEnum.valueOf(msg.getArg0()) == GLEnum.GL_ELEMENT_ARRAY_BUFFER) { 204 indexBuffer = buffers.get(msg.getArg1()); 205 if (null != indexBuffer) 206 indexBuffer.target = GLEnum.GL_ELEMENT_ARRAY_BUFFER; 207 } else 208 assert false; 209 } 210 211 // void API_ENTRY(glBufferData)(GLenum target, GLsizeiptr size, const 212 // GLvoid:size:in data, GLenum usage) 213 public void glBufferData(Message msg) { 214 if (GLEnum.valueOf(msg.getArg0()) == GLEnum.GL_ARRAY_BUFFER) { 215 attribBuffer.usage = GLEnum.valueOf(msg.getArg3()); 216 attribBuffer.data = msg.getData().asReadOnlyByteBuffer(); 217 attribBuffer.data.order(GLFramesView.TARGET_BYTE_ORDER); 218 } else if (GLEnum.valueOf(msg.getArg0()) == GLEnum.GL_ELEMENT_ARRAY_BUFFER) { 219 indexBuffer.usage = GLEnum.valueOf(msg.getArg3()); 220 indexBuffer.data = msg.getData().asReadOnlyByteBuffer(); 221 indexBuffer.data.order(GLFramesView.TARGET_BYTE_ORDER); 222 } else 223 assert false; 224 } 225 226 // void API_ENTRY(glBufferSubData)(GLenum target, GLintptr offset, 227 // GLsizeiptr size, const GLvoid:size:in data) 228 public void glBufferSubData(Message msg) { 229 if (GLEnum.valueOf(msg.getArg0()) == GLEnum.GL_ARRAY_BUFFER) { 230 if (attribBuffer.data.isReadOnly()) { 231 ByteBuffer buffer = ByteBuffer.allocate(attribBuffer.data.capacity()); 232 buffer.order(GLFramesView.TARGET_BYTE_ORDER); 233 buffer.put(attribBuffer.data); 234 attribBuffer.data = buffer; 235 } 236 attribBuffer.data.position(msg.getArg1()); 237 attribBuffer.data.put(msg.getData().asReadOnlyByteBuffer()); 238 } else if (GLEnum.valueOf(msg.getArg0()) == GLEnum.GL_ELEMENT_ARRAY_BUFFER) { 239 if (indexBuffer.data.isReadOnly()) { 240 ByteBuffer buffer = ByteBuffer.allocate(indexBuffer.data.capacity()); 241 buffer.order(GLFramesView.TARGET_BYTE_ORDER); 242 buffer.put(indexBuffer.data); 243 indexBuffer.data = buffer; 244 } 245 indexBuffer.data.position(msg.getArg1()); 246 indexBuffer.data.put(msg.getData().asReadOnlyByteBuffer()); 247 } else 248 assert false; 249 } 250 251 // void glDeleteBuffers(GLsizei n, const GLuint* buffers) 252 public void glDeleteBuffers(Message msg) { 253 final int n = msg.getArg0(); 254 final ByteBuffer names = msg.getData().asReadOnlyByteBuffer(); 255 names.order(GLFramesView.TARGET_BYTE_ORDER); 256 for (int i = 0; i < n; i++) { 257 final int name = names.getInt(); 258 final GLBuffer buffer = buffers.get(name); 259 for (int j = 0; j < attribPointers.length; j++) 260 if (attribPointers[j].buffer == buffer) { 261 attribPointers[j].buffer = null; 262 attribPointers[j].enabled = false; 263 } 264 if (attribBuffer == buffer) 265 attribBuffer = null; 266 if (indexBuffer == buffer) 267 indexBuffer = null; 268 buffers.remove(name); 269 } 270 } 271 272 // void glDisableVertexAttribArray(GLuint index) 273 public void glDisableVertexAttribArray(Message msg) { 274 if (msg.getArg0() >= 0 && msg.getArg0() < attribPointers.length) 275 attribPointers[msg.getArg0()].enabled = false; 276 } 277 278 float fetchConvert(final ByteBuffer src, final GLEnum type, final boolean normalized) { 279 if (GLEnum.GL_FLOAT == type) 280 return Float.intBitsToFloat(src.getInt()); 281 else if (GLEnum.GL_UNSIGNED_INT == type) 282 if (normalized) 283 return (src.getInt() & 0xffffffffL) / (2e32f - 1); 284 else 285 return src.getInt() & 0xffffffffL; 286 else if (GLEnum.GL_INT == type) 287 if (normalized) 288 return (src.getInt() * 2 + 1) / (2e32f - 1); 289 else 290 return src.getInt(); 291 else if (GLEnum.GL_UNSIGNED_SHORT == type) 292 if (normalized) 293 return (src.getShort() & 0xffff) / (2e16f - 1); 294 else 295 return src.getShort() & 0xffff; 296 else if (GLEnum.GL_SHORT == type) 297 if (normalized) 298 return (src.getShort() * 2 + 1) / (2e16f - 1); 299 else 300 return src.getShort(); 301 else if (GLEnum.GL_UNSIGNED_BYTE == type) 302 if (normalized) 303 return (src.get() & 0xff) / (2e8f - 1); 304 else 305 return src.get() & 0xff; 306 else if (GLEnum.GL_BYTE == type) 307 if (normalized) 308 return (src.get() * 2 + 1) / (2e8f - 1); 309 else 310 return src.get(); 311 else if (GLEnum.GL_FIXED == type) 312 if (normalized) 313 return (src.getInt() * 2 + 1) / (2e32f - 1); 314 else 315 return src.getInt() / (2e16f); 316 else 317 assert false; 318 return 0; 319 } 320 321 static int typeSize(final GLEnum type) { 322 switch (type) { 323 case GL_FLOAT: 324 case GL_UNSIGNED_INT: 325 case GL_INT: 326 case GL_FIXED: 327 return 4; 328 case GL_UNSIGNED_SHORT: 329 case GL_SHORT: 330 return 2; 331 case GL_UNSIGNED_BYTE: 332 case GL_BYTE: 333 return 1; 334 default: 335 assert false; 336 return 0; 337 } 338 } 339 340 void fetch(final int maxAttrib, final int index, final int dstIdx, final ByteBuffer nonVBO, 341 final float[][] fetchedAttribs) { 342 for (int i = 0; i < maxAttrib; i++) { 343 final GLAttribPointer attrib = attribPointers[i]; 344 int size = 0; 345 if (attrib.enabled) { 346 size = attrib.size; 347 if (null != attrib.buffer) { 348 final ByteBuffer src = attrib.buffer.data; 349 src.position(attrib.ptr + index * attrib.elemStride); 350 for (int j = 0; j < size; j++) 351 fetchedAttribs[i][dstIdx * 4 + j] = fetchConvert(src, attrib.type, 352 attrib.normalized); 353 } else 354 for (int j = 0; j < size; j++) 355 fetchedAttribs[i][dstIdx * 4 + j] = fetchConvert(nonVBO, attrib.type, 356 attrib.normalized); 357 } 358 if (size < 1) 359 fetchedAttribs[i][dstIdx * 4 + 0] = defaultAttribs[i][0]; 360 if (size < 2) 361 fetchedAttribs[i][dstIdx * 4 + 1] = defaultAttribs[i][1]; 362 if (size < 3) 363 fetchedAttribs[i][dstIdx * 4 + 2] = defaultAttribs[i][2]; 364 if (size < 4) 365 fetchedAttribs[i][dstIdx * 4 + 3] = defaultAttribs[i][3]; 366 } 367 } 368 369 /** 370 * fetches and converts vertex data from buffers, defaults and user pointers 371 * into MessageData; mainly for display use 372 */ 373 public void glDrawArrays(MessageData msgData) { 374 final Message msg = msgData.msg; 375 if (!msg.hasArg7()) 376 return; 377 final int maxAttrib = msg.getArg7(); 378 final int first = msg.getArg1(), count = msg.getArg2(); 379 msgData.attribs = new float[maxAttrib][count * 4]; 380 ByteBuffer arrays = null; 381 if (msg.hasData()) // server sends user pointer attribs 382 { 383 arrays = msg.getData().asReadOnlyByteBuffer(); 384 arrays.order(GLFramesView.TARGET_BYTE_ORDER); 385 } 386 for (int i = 0; i < count; i++) 387 fetch(maxAttrib, first + i, i, arrays, msgData.attribs); 388 assert null == arrays || arrays.remaining() == 0; 389 } 390 391 // void glDrawElements(GLenum mode, GLsizei count, GLenum type, const 392 // GLvoid* indices) 393 /** 394 * fetches and converts vertex data from buffers, defaults and user pointers 395 * and indices from buffer/pointer into MessageData; mainly for display use 396 */ 397 public void glDrawElements(MessageData msgData) { 398 final Message msg = msgData.msg; 399 if (!msg.hasArg7()) 400 return; 401 final int maxAttrib = msg.getArg7(); 402 final int count = msg.getArg1(); 403 final GLEnum type = GLEnum.valueOf(msg.getArg2()); 404 msgData.attribs = new float[maxAttrib][count * 4]; 405 msgData.indices = new short[count]; 406 ByteBuffer arrays = null, index = null; 407 if (msg.hasData()) // server sends user pointer attribs 408 { 409 arrays = msg.getData().asReadOnlyByteBuffer(); 410 arrays.order(GLFramesView.TARGET_BYTE_ORDER); 411 } 412 if (null == indexBuffer) 413 index = arrays; // server also interleaves user pointer indices 414 else { 415 index = indexBuffer.data; 416 index.position(msg.getArg3()); 417 } 418 if (GLEnum.GL_UNSIGNED_SHORT == type) { 419 for (int i = 0; i < count; i++) { 420 msgData.indices[i] = index.getShort(); 421 fetch(maxAttrib, msgData.indices[i] & 0xffff, i, arrays, msgData.attribs); 422 } 423 } else if (GLEnum.GL_UNSIGNED_BYTE == type) { 424 for (int i = 0; i < count; i++) { 425 msgData.indices[i] = (short) (index.get() & 0xff); 426 fetch(maxAttrib, msgData.indices[i], i, arrays, msgData.attribs); 427 } 428 } else 429 assert false; 430 assert null == arrays || arrays.remaining() == 0; 431 } 432 433 // void glEnableVertexAttribArray(GLuint index) 434 public void glEnableVertexAttribArray(Message msg) { 435 if (msg.getArg0() >= 0 && msg.getArg0() < attribPointers.length) 436 attribPointers[msg.getArg0()].enabled = true; 437 } 438 439 // void API_ENTRY(glGenBuffers)(GLsizei n, GLuint:n:out buffers) 440 public void glGenBuffers(Message msg) { 441 final int n = msg.getArg0(); 442 final ByteBuffer buffer = msg.getData().asReadOnlyByteBuffer(); 443 buffer.order(GLFramesView.TARGET_BYTE_ORDER); 444 for (int i = 0; i < n; i++) { 445 final int name = buffer.getInt(); 446 final int index = buffers.indexOfKey(name); 447 if (index < 0) 448 buffers.append(name, new GLBuffer(name)); 449 } 450 } 451 452 // void glVertexAttribPointer(GLuint index, GLint size, GLenum type, 453 // GLboolean normalized, GLsizei stride, const GLvoid* ptr) 454 public void glVertexAttribPointer(Message msg) { 455 GLAttribPointer attrib = attribPointers[msg.getArg0()]; 456 attrib.size = msg.getArg1(); 457 attrib.type = GLEnum.valueOf(msg.getArg2()); 458 attrib.normalized = msg.getArg3() != 0; 459 attrib.stride = msg.getArg4(); 460 attrib.elemSize = attrib.size * typeSize(attrib.type); 461 if (attrib.stride == 0) 462 attrib.elemStride = attrib.elemSize; 463 else 464 attrib.elemStride = attrib.stride; 465 attrib.ptr = msg.getArg5(); 466 attrib.buffer = attribBuffer; 467 } 468 469 // void glVertexAttrib1f(GLuint indx, GLfloat x) 470 public void glVertexAttrib1f(Message msg) { 471 glVertexAttrib4f(msg.getArg0(), Float.intBitsToFloat(msg.getArg1()), 472 0, 0, 1); 473 } 474 475 // void glVertexAttrib1fv(GLuint indx, const GLfloat* values) 476 public void glVertexAttrib1fv(Message msg) { 477 final ByteBuffer values = msg.getData().asReadOnlyByteBuffer(); 478 values.order(GLFramesView.TARGET_BYTE_ORDER); 479 glVertexAttrib4f(msg.getArg0(), 480 Float.intBitsToFloat(values.getInt()), 481 0, 0, 1); 482 } 483 484 // void glVertexAttrib2f(GLuint indx, GLfloat x, GLfloat y) 485 public void glVertexAttrib2f(Message msg) { 486 glVertexAttrib4f(msg.getArg0(), Float.intBitsToFloat(msg.getArg1()), 487 Float.intBitsToFloat(msg.getArg2()), 0, 1); 488 } 489 490 // void glVertexAttrib2fv(GLuint indx, const GLfloat* values) 491 public void glVertexAttrib2fv(Message msg) { 492 final ByteBuffer values = msg.getData().asReadOnlyByteBuffer(); 493 values.order(GLFramesView.TARGET_BYTE_ORDER); 494 glVertexAttrib4f(msg.getArg0(), 495 Float.intBitsToFloat(values.getInt()), 496 Float.intBitsToFloat(values.getInt()), 0, 1); 497 } 498 499 // void glVertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z) 500 public void glVertexAttrib3f(Message msg) { 501 glVertexAttrib4f(msg.getArg0(), Float.intBitsToFloat(msg.getArg1()), 502 Float.intBitsToFloat(msg.getArg2()), 503 Float.intBitsToFloat(msg.getArg3()), 1); 504 } 505 506 // void glVertexAttrib3fv(GLuint indx, const GLfloat* values) 507 public void glVertexAttrib3fv(Message msg) { 508 final ByteBuffer values = msg.getData().asReadOnlyByteBuffer(); 509 values.order(GLFramesView.TARGET_BYTE_ORDER); 510 glVertexAttrib4f(msg.getArg0(), 511 Float.intBitsToFloat(values.getInt()), 512 Float.intBitsToFloat(values.getInt()), 513 Float.intBitsToFloat(values.getInt()), 1); 514 } 515 516 public void glVertexAttrib4f(Message msg) { 517 glVertexAttrib4f(msg.getArg0(), Float.intBitsToFloat(msg.getArg1()), 518 Float.intBitsToFloat(msg.getArg2()), 519 Float.intBitsToFloat(msg.getArg3()), 520 Float.intBitsToFloat(msg.getArg4())); 521 } 522 523 void glVertexAttrib4f(int indx, float x, float y, float z, float w) { 524 if (indx < 0 || indx >= defaultAttribs.length) 525 return; 526 defaultAttribs[indx][0] = x; 527 defaultAttribs[indx][1] = y; 528 defaultAttribs[indx][2] = z; 529 defaultAttribs[indx][3] = w; 530 } 531 532 // void glVertexAttrib4fv(GLuint indx, const GLfloat* values) 533 public void glVertexAttrib4fv(Message msg) { 534 final ByteBuffer values = msg.getData().asReadOnlyByteBuffer(); 535 values.order(GLFramesView.TARGET_BYTE_ORDER); 536 glVertexAttrib4f(msg.getArg0(), 537 Float.intBitsToFloat(values.getInt()), 538 Float.intBitsToFloat(values.getInt()), 539 Float.intBitsToFloat(values.getInt()), 540 Float.intBitsToFloat(values.getInt())); 541 } 542 } 543