1 /* 2 * Copyright (C) 2012 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.gltrace.state.transforms; 18 19 import com.android.ide.eclipse.gltrace.FileUtils; 20 import com.android.ide.eclipse.gltrace.GLEnum; 21 import com.android.ide.eclipse.gltrace.GLProtoBuf.GLMessage; 22 import com.android.ide.eclipse.gltrace.state.GLState; 23 import com.android.ide.eclipse.gltrace.state.GLStateType; 24 import com.android.ide.eclipse.gltrace.state.IGLProperty; 25 import com.google.common.io.Files; 26 import com.google.protobuf.ByteString; 27 28 import java.io.File; 29 import java.io.IOException; 30 import java.util.ArrayList; 31 import java.util.Arrays; 32 import java.util.Collections; 33 import java.util.EnumSet; 34 import java.util.List; 35 36 public class StateTransformFactory { 37 private static final String TEXTURE_DATA_FILE_PREFIX = "tex"; //$NON-NLS-1$ 38 private static final String TEXTURE_DATA_FILE_SUFFIX = ".dat"; //$NON-NLS-1$ 39 private static EnumSet<GLEnum> sTexParameterPnameValues; 40 41 /** Construct a list of transformations to be applied for the provided OpenGL call. */ 42 public static List<IStateTransform> getTransformsFor(GLMessage msg) { 43 switch (msg.getFunction()) { 44 case eglCreateContext: 45 return transformsForEglCreateContext(msg); 46 case glBindFramebuffer: 47 return transformsForGlBindFramebuffer(msg); 48 49 // vertex data 50 case glVertexAttribPointer: 51 return transformsForGlVertexAttribPointer(msg); 52 case glVertexAttrib1f: 53 case glVertexAttrib2f: 54 case glVertexAttrib3f: 55 case glVertexAttrib4f: 56 return transformsForGlVertexAttribxf(msg); 57 case glVertexAttrib1fv: 58 case glVertexAttrib2fv: 59 case glVertexAttrib3fv: 60 case glVertexAttrib4fv: 61 return transformsForGlVertexAttribxfv(msg); 62 case glEnableVertexAttribArray: 63 return transformsForGlEnableVertexAttribArray(msg); 64 case glDisableVertexAttribArray: 65 return transformsForGlDisableVertexAttribArray(msg); 66 67 // VBO's 68 case glBindBuffer: 69 return transformsForGlBindBuffer(msg); 70 case glGenBuffers: 71 return transformsForGlGenBuffers(msg); 72 case glDeleteBuffers: 73 return transformsForGlDeleteBuffers(msg); 74 case glBufferData: 75 return transformsForGlBufferData(msg); 76 case glBufferSubData: 77 return transformsForGlBufferSubData(msg); 78 79 // transformation state 80 case glViewport: 81 return transformsForGlViewport(msg); 82 case glDepthRangef: 83 return transformsForGlDepthRangef(msg); 84 85 // rasterization 86 case glLineWidth: 87 return transformsForGlLineWidth(msg); 88 case glCullFace: 89 return transformsForGlCullFace(msg); 90 case glFrontFace: 91 return transformsForGlFrontFace(msg); 92 case glPolygonOffset: 93 return transformsForGlPolygonOffset(msg); 94 95 // pixel operations 96 case glScissor: 97 return transformsForGlScissor(msg); 98 case glStencilFunc: 99 return transformsForGlStencilFunc(msg); 100 case glStencilFuncSeparate: 101 return transformsForGlStencilFuncSeparate(msg); 102 case glStencilOp: 103 return transformsForGlStencilOp(msg); 104 case glStencilOpSeparate: 105 return transformsForGlStencilOpSeparate(msg); 106 case glDepthFunc: 107 return transformsForGlDepthFunc(msg); 108 case glBlendEquation: 109 return transformsForGlBlendEquation(msg); 110 case glBlendEquationSeparate: 111 return transformsForGlBlendEquationSeparate(msg); 112 case glBlendFunc: 113 return transformsForGlBlendFunc(msg); 114 case glBlendFuncSeparate: 115 return transformsForGlBlendFuncSeparate(msg); 116 case glPixelStorei: 117 return transformsForGlPixelStorei(msg); 118 119 // Texture State Transformations 120 case glGenTextures: 121 return transformsForGlGenTextures(msg); 122 case glDeleteTextures: 123 return transformsForGlDeleteTextures(msg); 124 case glActiveTexture: 125 return transformsForGlActiveTexture(msg); 126 case glBindTexture: 127 return transformsForGlBindTexture(msg); 128 case glTexImage2D: 129 return transformsForGlTexImage2D(msg); 130 case glTexSubImage2D: 131 return transformsForGlTexSubImage2D(msg); 132 case glTexParameteri: 133 return transformsForGlTexParameter(msg); 134 135 // Program State Transformations 136 case glCreateProgram: 137 return transformsForGlCreateProgram(msg); 138 case glUseProgram: 139 return transformsForGlUseProgram(msg); 140 case glAttachShader: 141 return transformsForGlAttachShader(msg); 142 case glDetachShader: 143 return transformsForGlDetachShader(msg); 144 case glGetActiveAttrib: 145 return transformsForGlGetActiveAttrib(msg); 146 case glGetActiveUniform: 147 return transformsForGlGetActiveUniform(msg); 148 case glUniform1i: 149 case glUniform2i: 150 case glUniform3i: 151 case glUniform4i: 152 return transformsForGlUniform(msg, false); 153 case glUniform1f: 154 case glUniform2f: 155 case glUniform3f: 156 case glUniform4f: 157 return transformsForGlUniform(msg, true); 158 case glUniform1iv: 159 case glUniform2iv: 160 case glUniform3iv: 161 case glUniform4iv: 162 return transformsForGlUniformv(msg, false); 163 case glUniform1fv: 164 case glUniform2fv: 165 case glUniform3fv: 166 case glUniform4fv: 167 return transformsForGlUniformv(msg, true); 168 case glUniformMatrix2fv: 169 case glUniformMatrix3fv: 170 case glUniformMatrix4fv: 171 return transformsForGlUniformMatrix(msg); 172 173 // Shader State Transformations 174 case glCreateShader: 175 return transformsForGlCreateShader(msg); 176 case glDeleteShader: 177 return transformsForGlDeleteShader(msg); 178 case glShaderSource: 179 return transformsForGlShaderSource(msg); 180 default: 181 return Collections.emptyList(); 182 } 183 } 184 185 private static List<IStateTransform> transformsForGlVertexAttribPointer(GLMessage msg) { 186 int index = msg.getArgs(0).getIntValue(0); 187 188 int size = msg.getArgs(1).getIntValue(0); 189 int type = msg.getArgs(2).getIntValue(0); 190 boolean normalized = msg.getArgs(3).getBoolValue(0); 191 int stride = msg.getArgs(4).getIntValue(0); 192 193 long pointer; 194 if (msg.getArgs(5).getIntValueCount() > 0) { 195 pointer = msg.getArgs(5).getIntValue(0); 196 } else { 197 pointer = msg.getArgs(5).getInt64Value(0); 198 } 199 200 List<IStateTransform> transforms = new ArrayList<IStateTransform>(); 201 transforms.add(new PropertyChangeTransform( 202 GLPropertyAccessor.makeAccessor(msg.getContextId(), 203 GLStateType.VERTEX_ARRAY_DATA, 204 GLStateType.VERTEX_ATTRIB_ARRAY, 205 Integer.valueOf(index), 206 GLStateType.VERTEX_ATTRIB_ARRAY_SIZE), 207 Integer.valueOf(size))); 208 transforms.add(new PropertyChangeTransform( 209 GLPropertyAccessor.makeAccessor(msg.getContextId(), 210 GLStateType.VERTEX_ARRAY_DATA, 211 GLStateType.VERTEX_ATTRIB_ARRAY, 212 Integer.valueOf(index), 213 GLStateType.VERTEX_ATTRIB_ARRAY_TYPE), 214 GLEnum.valueOf(type))); 215 transforms.add(new PropertyChangeTransform( 216 GLPropertyAccessor.makeAccessor(msg.getContextId(), 217 GLStateType.VERTEX_ARRAY_DATA, 218 GLStateType.VERTEX_ATTRIB_ARRAY, 219 Integer.valueOf(index), 220 GLStateType.VERTEX_ATTRIB_ARRAY_NORMALIZED), 221 Boolean.valueOf(normalized))); 222 transforms.add(new PropertyChangeTransform( 223 GLPropertyAccessor.makeAccessor(msg.getContextId(), 224 GLStateType.VERTEX_ARRAY_DATA, 225 GLStateType.VERTEX_ATTRIB_ARRAY, 226 Integer.valueOf(index), 227 GLStateType.VERTEX_ATTRIB_ARRAY_STRIDE), 228 Integer.valueOf(stride))); 229 transforms.add(new PropertyChangeTransform( 230 GLPropertyAccessor.makeAccessor(msg.getContextId(), 231 GLStateType.VERTEX_ARRAY_DATA, 232 GLStateType.VERTEX_ATTRIB_ARRAY, 233 Integer.valueOf(index), 234 GLStateType.VERTEX_ATTRIB_ARRAY_POINTER), 235 Long.valueOf(pointer))); 236 return transforms; 237 } 238 239 private static List<IStateTransform> transformsForGlVertexAttrib(int context, 240 int index, float v0, float v1, float v2, float v3) { 241 List<IStateTransform> transforms = new ArrayList<IStateTransform>(4); 242 transforms.add(new PropertyChangeTransform( 243 GLPropertyAccessor.makeAccessor(context, 244 GLStateType.VERTEX_ARRAY_DATA, 245 GLStateType.GENERIC_VERTEX_ATTRIBUTES, 246 Integer.valueOf(index), 247 GLStateType.GENERIC_VERTEX_ATTRIB_V0), 248 Float.valueOf(v0))); 249 transforms.add(new PropertyChangeTransform( 250 GLPropertyAccessor.makeAccessor(context, 251 GLStateType.VERTEX_ARRAY_DATA, 252 GLStateType.GENERIC_VERTEX_ATTRIBUTES, 253 Integer.valueOf(index), 254 GLStateType.GENERIC_VERTEX_ATTRIB_V1), 255 Float.valueOf(v1))); 256 transforms.add(new PropertyChangeTransform( 257 GLPropertyAccessor.makeAccessor(context, 258 GLStateType.VERTEX_ARRAY_DATA, 259 GLStateType.GENERIC_VERTEX_ATTRIBUTES, 260 Integer.valueOf(index), 261 GLStateType.GENERIC_VERTEX_ATTRIB_V2), 262 Float.valueOf(v2))); 263 transforms.add(new PropertyChangeTransform( 264 GLPropertyAccessor.makeAccessor(context, 265 GLStateType.VERTEX_ARRAY_DATA, 266 GLStateType.GENERIC_VERTEX_ATTRIBUTES, 267 Integer.valueOf(index), 268 GLStateType.GENERIC_VERTEX_ATTRIB_V3), 269 Float.valueOf(v3))); 270 return transforms; 271 } 272 273 private static List<IStateTransform> transformsForGlVertexAttribxf(GLMessage msg) { 274 // void glVertexAttrib1f(GLuint index, GLfloat v0); 275 // void glVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1); 276 // void glVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2); 277 // void glVertexAttrib4f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); 278 279 int index = msg.getArgs(0).getIntValue(0); 280 float v0 = msg.getArgs(1).getFloatValue(0); 281 float v1 = msg.getArgsCount() > 2 ? msg.getArgs(2).getFloatValue(0) : 0; 282 float v2 = msg.getArgsCount() > 3 ? msg.getArgs(3).getFloatValue(0) : 0; 283 float v3 = msg.getArgsCount() > 4 ? msg.getArgs(4).getFloatValue(0) : 0; 284 285 return transformsForGlVertexAttrib(msg.getContextId(), index, v0, v1, v2, v3); 286 } 287 288 private static List<IStateTransform> transformsForGlVertexAttribxfv(GLMessage msg) { 289 // void glVertexAttrib1fv(GLuint index, const GLfloat *v); 290 // void glVertexAttrib2fv(GLuint index, const GLfloat *v); 291 // void glVertexAttrib3fv(GLuint index, const GLfloat *v); 292 // void glVertexAttrib4fv(GLuint index, const GLfloat *v); 293 294 int index = msg.getArgs(0).getIntValue(0); 295 float v[] = new float[4]; 296 297 for (int i = 0; i < msg.getArgs(1).getFloatValueList().size(); i++) { 298 v[i] = msg.getArgs(1).getFloatValue(i); 299 } 300 301 return transformsForGlVertexAttrib(msg.getContextId(), index, v[0], v[1], v[2], v[3]); 302 } 303 304 private static List<IStateTransform> transformsForGlEnableVertexAttribArray(GLMessage msg) { 305 // void glEnableVertexAttribArray(GLuint index); 306 // void glDisableVertexAttribArray(GLuint index); 307 308 int index = msg.getArgs(0).getIntValue(0); 309 IStateTransform transform = new PropertyChangeTransform( 310 GLPropertyAccessor.makeAccessor(msg.getContextId(), 311 GLStateType.VERTEX_ARRAY_DATA, 312 GLStateType.VERTEX_ATTRIB_ARRAY, 313 Integer.valueOf(index), 314 GLStateType.VERTEX_ATTRIB_ARRAY_ENABLED), 315 Boolean.TRUE); 316 return Collections.singletonList(transform); 317 } 318 319 private static List<IStateTransform> transformsForGlDisableVertexAttribArray(GLMessage msg) { 320 // void glEnableVertexAttribArray(GLuint index); 321 // void glDisableVertexAttribArray(GLuint index); 322 323 int index = msg.getArgs(0).getIntValue(0); 324 IStateTransform transform = new PropertyChangeTransform( 325 GLPropertyAccessor.makeAccessor(msg.getContextId(), 326 GLStateType.VERTEX_ARRAY_DATA, 327 GLStateType.VERTEX_ATTRIB_ARRAY, 328 Integer.valueOf(index), 329 GLStateType.VERTEX_ATTRIB_ARRAY_ENABLED), 330 Boolean.FALSE); 331 return Collections.singletonList(transform); 332 } 333 334 private static List<IStateTransform> transformsForGlBindBuffer(GLMessage msg) { 335 // void glBindBuffer(GLenum target, GLuint buffer); 336 // target is one of GL_ARRAY_BUFFER or GL_ELEMENT_ARRAY_BUFFER. 337 338 GLEnum target = GLEnum.valueOf(msg.getArgs(0).getIntValue(0)); 339 int buffer = msg.getArgs(1).getIntValue(0); 340 GLStateType bufferType; 341 342 if (target == GLEnum.GL_ARRAY_BUFFER) { 343 bufferType = GLStateType.ARRAY_BUFFER_BINDING; 344 } else { 345 bufferType = GLStateType.ELEMENT_ARRAY_BUFFER_BINDING; 346 } 347 348 IStateTransform transform = new PropertyChangeTransform( 349 GLPropertyAccessor.makeAccessor(msg.getContextId(), 350 GLStateType.VERTEX_ARRAY_DATA, 351 GLStateType.BUFFER_BINDINGS, 352 bufferType), 353 Integer.valueOf(buffer)); 354 return Collections.singletonList(transform); 355 } 356 357 private static List<IStateTransform> transformsForGlGenBuffers(GLMessage msg) { 358 // void glGenBuffers(GLsizei n, GLuint * buffers); 359 int n = msg.getArgs(0).getIntValue(0); 360 List<IStateTransform> transforms = new ArrayList<IStateTransform>(); 361 362 for (int i = 0; i < n; i++) { 363 transforms.add(new SparseArrayElementAddTransform( 364 GLPropertyAccessor.makeAccessor(msg.getContextId(), 365 GLStateType.VERTEX_ARRAY_DATA, 366 GLStateType.VBO), 367 msg.getArgs(1).getIntValue(i))); 368 } 369 370 return transforms; 371 } 372 373 private static List<IStateTransform> transformsForGlDeleteBuffers(GLMessage msg) { 374 // void glDeleteBuffers(GLsizei n, const GLuint * buffers); 375 int n = msg.getArgs(0).getIntValue(0); 376 List<IStateTransform> transforms = new ArrayList<IStateTransform>(); 377 378 for (int i = 0; i < n; i++) { 379 transforms.add(new SparseArrayElementRemoveTransform( 380 GLPropertyAccessor.makeAccessor(msg.getContextId(), 381 GLStateType.VERTEX_ARRAY_DATA, 382 GLStateType.VBO), 383 msg.getArgs(1).getIntValue(i))); 384 } 385 386 return transforms; 387 } 388 389 private static List<IStateTransform> transformsForGlBufferData(GLMessage msg) { 390 // void glBufferData(GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage); 391 GLEnum target = GLEnum.valueOf(msg.getArgs(0).getIntValue(0)); 392 int size = msg.getArgs(1).getIntValue(0); 393 byte[] data = null; 394 GLEnum usage = GLEnum.valueOf(msg.getArgs(3).getIntValue(0)); 395 396 if (msg.getArgs(2).getRawBytesList().size() > 0) { 397 data = msg.getArgs(2).getRawBytesList().get(0).toByteArray(); 398 } else { 399 data = new byte[size]; 400 } 401 402 List<IStateTransform> transforms = new ArrayList<IStateTransform>(); 403 404 transforms.add(new PropertyChangeTransform( 405 new CurrentVboPropertyAccessor(msg.getContextId(), 406 target, 407 GLStateType.BUFFER_SIZE), 408 Integer.valueOf(size))); 409 transforms.add(new PropertyChangeTransform( 410 new CurrentVboPropertyAccessor(msg.getContextId(), 411 target, 412 GLStateType.BUFFER_DATA), 413 data)); 414 transforms.add(new PropertyChangeTransform( 415 new CurrentVboPropertyAccessor(msg.getContextId(), 416 target, 417 GLStateType.BUFFER_USAGE), 418 usage)); 419 transforms.add(new PropertyChangeTransform( 420 new CurrentVboPropertyAccessor(msg.getContextId(), 421 target, 422 GLStateType.BUFFER_TYPE), 423 target)); 424 return transforms; 425 } 426 427 private static List<IStateTransform> transformsForGlBufferSubData(GLMessage msg) { 428 // void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data); 429 GLEnum target = GLEnum.valueOf(msg.getArgs(0).getIntValue(0)); 430 int offset = msg.getArgs(1).getIntValue(0); 431 byte[] data = msg.getArgs(3).getRawBytesList().get(0).toByteArray(); 432 433 IStateTransform transform = new BufferSubDataTransform( 434 new CurrentVboPropertyAccessor(msg.getContextId(), 435 target, 436 GLStateType.BUFFER_DATA), 437 offset, data); 438 439 return Collections.singletonList(transform); 440 } 441 442 private static List<IStateTransform> transformsForGlBindFramebuffer(GLMessage msg) { 443 // void glBindFramebuffer(GLenum target, GLuint framebuffer); 444 int fb = msg.getArgs(1).getIntValue(0); 445 IStateTransform transform = new PropertyChangeTransform( 446 GLPropertyAccessor.makeAccessor(msg.getContextId(), 447 GLStateType.FRAMEBUFFER_STATE, 448 GLStateType.FRAMEBUFFER_BINDING), 449 fb); 450 return Collections.singletonList(transform); 451 } 452 453 private static List<IStateTransform> transformsForGlLineWidth(GLMessage msg) { 454 // void glLineWidth(GLfloat width); 455 float width = msg.getArgs(0).getFloatValue(0); 456 IStateTransform transform = new PropertyChangeTransform( 457 GLPropertyAccessor.makeAccessor(msg.getContextId(), 458 GLStateType.RASTERIZATION_STATE, 459 GLStateType.LINE_WIDTH), 460 width); 461 return Collections.singletonList(transform); 462 } 463 464 private static List<IStateTransform> transformsForGlCullFace(GLMessage msg) { 465 // void glCullFace(GLenum mode); 466 int mode = msg.getArgs(0).getIntValue(0); 467 IStateTransform transform = new PropertyChangeTransform( 468 GLPropertyAccessor.makeAccessor(msg.getContextId(), 469 GLStateType.RASTERIZATION_STATE, 470 GLStateType.CULL_FACE_MODE), 471 GLEnum.valueOf(mode)); 472 return Collections.singletonList(transform); 473 } 474 475 private static List<IStateTransform> transformsForGlFrontFace(GLMessage msg) { 476 // void glFrontFace(GLenum mode); 477 int mode = msg.getArgs(0).getIntValue(0); 478 IStateTransform transform = new PropertyChangeTransform( 479 GLPropertyAccessor.makeAccessor(msg.getContextId(), 480 GLStateType.RASTERIZATION_STATE, 481 GLStateType.FRONT_FACE), 482 GLEnum.valueOf(mode)); 483 return Collections.singletonList(transform); 484 } 485 486 private static List<IStateTransform> transformsForGlPolygonOffset(GLMessage msg) { 487 // void glPolygonOffset(GLfloat factor, GLfloat units) 488 float factor = msg.getArgs(0).getFloatValue(0); 489 float units = msg.getArgs(1).getFloatValue(0); 490 491 List<IStateTransform> transforms = new ArrayList<IStateTransform>(); 492 transforms.add(new PropertyChangeTransform( 493 GLPropertyAccessor.makeAccessor(msg.getContextId(), 494 GLStateType.RASTERIZATION_STATE, 495 GLStateType.POLYGON_OFFSET_FACTOR), 496 Float.valueOf(factor))); 497 transforms.add(new PropertyChangeTransform( 498 GLPropertyAccessor.makeAccessor(msg.getContextId(), 499 GLStateType.RASTERIZATION_STATE, 500 GLStateType.POLYGON_OFFSET_UNITS), 501 Float.valueOf(units))); 502 return transforms; 503 } 504 505 private static List<IStateTransform> transformsForGlScissor(GLMessage msg) { 506 // void glScissor(GLint x, GLint y, GLsizei width, GLsizei height); 507 int x = msg.getArgs(0).getIntValue(0); 508 int y = msg.getArgs(1).getIntValue(0); 509 int w = msg.getArgs(2).getIntValue(0); 510 int h = msg.getArgs(3).getIntValue(0); 511 512 List<IStateTransform> transforms = new ArrayList<IStateTransform>(); 513 transforms.add(new PropertyChangeTransform( 514 GLPropertyAccessor.makeAccessor(msg.getContextId(), 515 GLStateType.PIXEL_OPERATIONS, 516 GLStateType.SCISSOR_BOX, 517 GLStateType.SCISSOR_BOX_X), 518 Integer.valueOf(x))); 519 transforms.add(new PropertyChangeTransform( 520 GLPropertyAccessor.makeAccessor(msg.getContextId(), 521 GLStateType.PIXEL_OPERATIONS, 522 GLStateType.SCISSOR_BOX, 523 GLStateType.SCISSOR_BOX_Y), 524 Integer.valueOf(y))); 525 transforms.add(new PropertyChangeTransform( 526 GLPropertyAccessor.makeAccessor(msg.getContextId(), 527 GLStateType.PIXEL_OPERATIONS, 528 GLStateType.SCISSOR_BOX, 529 GLStateType.SCISSOR_BOX_WIDTH), 530 Integer.valueOf(w))); 531 transforms.add(new PropertyChangeTransform( 532 GLPropertyAccessor.makeAccessor(msg.getContextId(), 533 GLStateType.PIXEL_OPERATIONS, 534 GLStateType.SCISSOR_BOX, 535 GLStateType.SCISSOR_BOX_HEIGHT), 536 Integer.valueOf(h))); 537 return transforms; 538 } 539 540 private static List<IStateTransform> transformsForGlStencilFuncFront(int contextId, 541 GLEnum func, int ref, int mask) { 542 List<IStateTransform> transforms = new ArrayList<IStateTransform>(); 543 transforms.add(new PropertyChangeTransform( 544 GLPropertyAccessor.makeAccessor(contextId, 545 GLStateType.PIXEL_OPERATIONS, 546 GLStateType.STENCIL, 547 GLStateType.STENCIL_FUNC), 548 func)); 549 transforms.add(new PropertyChangeTransform( 550 GLPropertyAccessor.makeAccessor(contextId, 551 GLStateType.PIXEL_OPERATIONS, 552 GLStateType.STENCIL, 553 GLStateType.STENCIL_REF), 554 Integer.valueOf(ref))); 555 transforms.add(new PropertyChangeTransform( 556 GLPropertyAccessor.makeAccessor(contextId, 557 GLStateType.PIXEL_OPERATIONS, 558 GLStateType.STENCIL, 559 GLStateType.STENCIL_VALUE_MASK), 560 Integer.valueOf(mask))); 561 return transforms; 562 } 563 564 private static List<IStateTransform> transformsForGlStencilFuncBack(int contextId, 565 GLEnum func, int ref, int mask) { 566 List<IStateTransform> transforms = new ArrayList<IStateTransform>(); 567 transforms.add(new PropertyChangeTransform( 568 GLPropertyAccessor.makeAccessor(contextId, 569 GLStateType.PIXEL_OPERATIONS, 570 GLStateType.STENCIL, 571 GLStateType.STENCIL_BACK_FUNC), 572 func)); 573 transforms.add(new PropertyChangeTransform( 574 GLPropertyAccessor.makeAccessor(contextId, 575 GLStateType.PIXEL_OPERATIONS, 576 GLStateType.STENCIL, 577 GLStateType.STENCIL_BACK_REF), 578 Integer.valueOf(ref))); 579 transforms.add(new PropertyChangeTransform( 580 GLPropertyAccessor.makeAccessor(contextId, 581 GLStateType.PIXEL_OPERATIONS, 582 GLStateType.STENCIL, 583 GLStateType.STENCIL_BACK_VALUE_MASK), 584 Integer.valueOf(mask))); 585 return transforms; 586 } 587 588 private static List<IStateTransform> transformsForGlStencilFunc(GLMessage msg) { 589 // void glStencilFunc(GLenum func, GLint ref, GLuint mask); 590 GLEnum func = GLEnum.valueOf(msg.getArgs(0).getIntValue(0)); 591 int ref = msg.getArgs(1).getIntValue(0); 592 int mask = msg.getArgs(2).getIntValue(0); 593 594 List<IStateTransform> transforms = new ArrayList<IStateTransform>(); 595 transforms.addAll(transformsForGlStencilFuncFront(msg.getContextId(), func, ref, mask)); 596 transforms.addAll(transformsForGlStencilFuncBack(msg.getContextId(), func, ref, mask)); 597 return transforms; 598 } 599 600 private static List<IStateTransform> transformsForGlStencilFuncSeparate(GLMessage msg) { 601 // void glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask); 602 GLEnum face = GLEnum.valueOf(msg.getArgs(0).getIntValue(0)); 603 GLEnum func = GLEnum.valueOf(msg.getArgs(1).getIntValue(0)); 604 int ref = msg.getArgs(2).getIntValue(0); 605 int mask = msg.getArgs(3).getIntValue(0); 606 607 List<IStateTransform> transforms = new ArrayList<IStateTransform>(); 608 if (face == GLEnum.GL_FRONT || face == GLEnum.GL_FRONT_AND_BACK) { 609 transforms.addAll( 610 transformsForGlStencilFuncFront(msg.getContextId(), func, ref, mask)); 611 } 612 if (face == GLEnum.GL_BACK || face == GLEnum.GL_FRONT_AND_BACK) { 613 transforms.addAll( 614 transformsForGlStencilFuncBack(msg.getContextId(), func, ref, mask)); 615 } 616 617 return transforms; 618 } 619 620 private static List<IStateTransform> transformsForGlStencilOpFront(int contextId, 621 GLEnum sfail, GLEnum dpfail, GLEnum dppass) { 622 List<IStateTransform> transforms = new ArrayList<IStateTransform>(); 623 transforms.add(new PropertyChangeTransform( 624 GLPropertyAccessor.makeAccessor(contextId, 625 GLStateType.PIXEL_OPERATIONS, 626 GLStateType.STENCIL, 627 GLStateType.STENCIL_FAIL), 628 sfail)); 629 transforms.add(new PropertyChangeTransform( 630 GLPropertyAccessor.makeAccessor(contextId, 631 GLStateType.PIXEL_OPERATIONS, 632 GLStateType.STENCIL, 633 GLStateType.STENCIL_PASS_DEPTH_FAIL), 634 dpfail)); 635 transforms.add(new PropertyChangeTransform( 636 GLPropertyAccessor.makeAccessor(contextId, 637 GLStateType.PIXEL_OPERATIONS, 638 GLStateType.STENCIL, 639 GLStateType.STENCIL_PASS_DEPTH_PASS), 640 dppass)); 641 return transforms; 642 } 643 644 private static List<IStateTransform> transformsForGlStencilOpBack(int contextId, 645 GLEnum sfail, GLEnum dpfail, GLEnum dppass) { 646 List<IStateTransform> transforms = new ArrayList<IStateTransform>(); 647 transforms.add(new PropertyChangeTransform( 648 GLPropertyAccessor.makeAccessor(contextId, 649 GLStateType.PIXEL_OPERATIONS, 650 GLStateType.STENCIL, 651 GLStateType.STENCIL_BACK_FAIL), 652 sfail)); 653 transforms.add(new PropertyChangeTransform( 654 GLPropertyAccessor.makeAccessor(contextId, 655 GLStateType.PIXEL_OPERATIONS, 656 GLStateType.STENCIL, 657 GLStateType.STENCIL_BACK_PASS_DEPTH_FAIL), 658 dpfail)); 659 transforms.add(new PropertyChangeTransform( 660 GLPropertyAccessor.makeAccessor(contextId, 661 GLStateType.PIXEL_OPERATIONS, 662 GLStateType.STENCIL, 663 GLStateType.STENCIL_BACK_PASS_DEPTH_PASS), 664 dppass)); 665 return transforms; 666 } 667 668 private static List<IStateTransform> transformsForGlStencilOp(GLMessage msg) { 669 // void glStencilOp(GLenum sfail, GLenum dpfail, GLenum dppass); 670 GLEnum sfail = GLEnum.valueOf(msg.getArgs(0).getIntValue(0)); 671 GLEnum dpfail = GLEnum.valueOf(msg.getArgs(1).getIntValue(0)); 672 GLEnum dppass = GLEnum.valueOf(msg.getArgs(2).getIntValue(0)); 673 List<IStateTransform> transforms = new ArrayList<IStateTransform>(); 674 transforms.addAll( 675 transformsForGlStencilOpFront(msg.getContextId(), sfail, dpfail, dppass)); 676 transforms.addAll( 677 transformsForGlStencilOpBack(msg.getContextId(), sfail, dpfail, dppass)); 678 return transforms; 679 } 680 681 private static List<IStateTransform> transformsForGlStencilOpSeparate(GLMessage msg) { 682 // void glStencilOp(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); 683 GLEnum face = GLEnum.valueOf(msg.getArgs(0).getIntValue(0)); 684 GLEnum sfail = GLEnum.valueOf(msg.getArgs(1).getIntValue(0)); 685 GLEnum dpfail = GLEnum.valueOf(msg.getArgs(2).getIntValue(0)); 686 GLEnum dppass = GLEnum.valueOf(msg.getArgs(3).getIntValue(0)); 687 List<IStateTransform> transforms = new ArrayList<IStateTransform>(); 688 689 if (face == GLEnum.GL_FRONT || face == GLEnum.GL_FRONT_AND_BACK) { 690 transforms.addAll( 691 transformsForGlStencilOpFront(msg.getContextId(), sfail, dpfail, dppass)); 692 } 693 694 if (face == GLEnum.GL_BACK || face == GLEnum.GL_FRONT_AND_BACK) { 695 transforms.addAll( 696 transformsForGlStencilOpBack(msg.getContextId(), sfail, dpfail, dppass)); 697 } 698 699 return transforms; 700 } 701 702 private static List<IStateTransform> transformsForGlDepthFunc(GLMessage msg) { 703 // void glDepthFunc(GLenum func); 704 GLEnum func = GLEnum.valueOf(msg.getArgs(0).getIntValue(0)); 705 706 IStateTransform transform = new PropertyChangeTransform( 707 GLPropertyAccessor.makeAccessor(msg.getContextId(), 708 GLStateType.PIXEL_OPERATIONS, 709 GLStateType.DEPTH_FUNC), 710 func); 711 return Collections.singletonList(transform); 712 } 713 714 private static IStateTransform transformForGlEquationRGB(int contextId, GLEnum mode) { 715 return new PropertyChangeTransform( 716 GLPropertyAccessor.makeAccessor(contextId, 717 GLStateType.PIXEL_OPERATIONS, 718 GLStateType.BLEND, 719 GLStateType.BLEND_EQUATION_RGB), 720 mode); 721 } 722 723 private static IStateTransform transformForGlEquationAlpha(int contextId, GLEnum mode) { 724 return new PropertyChangeTransform( 725 GLPropertyAccessor.makeAccessor(contextId, 726 GLStateType.PIXEL_OPERATIONS, 727 GLStateType.BLEND, 728 GLStateType.BLEND_EQUATION_ALPHA), 729 mode); 730 } 731 732 private static List<IStateTransform> transformsForGlBlendEquationSeparate(GLMessage msg) { 733 // void glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha); 734 GLEnum rgb = GLEnum.valueOf(msg.getArgs(0).getIntValue(0)); 735 GLEnum alpha = GLEnum.valueOf(msg.getArgs(1).getIntValue(0)); 736 737 List<IStateTransform> transforms = new ArrayList<IStateTransform>(); 738 transforms.add(transformForGlEquationRGB(msg.getContextId(), rgb)); 739 transforms.add(transformForGlEquationAlpha(msg.getContextId(), alpha)); 740 return transforms; 741 } 742 743 private static List<IStateTransform> transformsForGlBlendEquation(GLMessage msg) { 744 // void glBlendEquation(GLenum mode); 745 GLEnum mode = GLEnum.valueOf(msg.getArgs(0).getIntValue(0)); 746 747 List<IStateTransform> transforms = new ArrayList<IStateTransform>(); 748 transforms.add(transformForGlEquationRGB(msg.getContextId(), mode)); 749 transforms.add(transformForGlEquationAlpha(msg.getContextId(), mode)); 750 return transforms; 751 } 752 753 private static List<IStateTransform> transformsForGlBlendFuncSrcDst(boolean src, 754 int contextId, GLEnum rgb, GLEnum alpha) { 755 List<IStateTransform> transforms = new ArrayList<IStateTransform>(); 756 757 GLStateType rgbAccessor = GLStateType.BLEND_DST_RGB; 758 GLStateType alphaAccessor = GLStateType.BLEND_DST_ALPHA; 759 if (src) { 760 rgbAccessor = GLStateType.BLEND_SRC_RGB; 761 alphaAccessor = GLStateType.BLEND_SRC_ALPHA; 762 } 763 764 transforms.add(new PropertyChangeTransform( 765 GLPropertyAccessor.makeAccessor(contextId, 766 GLStateType.PIXEL_OPERATIONS, 767 GLStateType.BLEND, 768 rgbAccessor), 769 rgb)); 770 transforms.add(new PropertyChangeTransform( 771 GLPropertyAccessor.makeAccessor(contextId, 772 GLStateType.PIXEL_OPERATIONS, 773 GLStateType.BLEND, 774 alphaAccessor), 775 alpha)); 776 return transforms; 777 } 778 779 private static List<IStateTransform> transformsForGlBlendFuncSeparate(GLMessage msg) { 780 // void glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) 781 GLEnum srcRgb = GLEnum.valueOf(msg.getArgs(0).getIntValue(0)); 782 GLEnum dstRgb = GLEnum.valueOf(msg.getArgs(1).getIntValue(0)); 783 GLEnum srcAlpha = GLEnum.valueOf(msg.getArgs(2).getIntValue(0)); 784 GLEnum dstAlpha = GLEnum.valueOf(msg.getArgs(3).getIntValue(0)); 785 786 List<IStateTransform> transforms = new ArrayList<IStateTransform>(); 787 transforms.addAll(transformsForGlBlendFuncSrcDst(true, 788 msg.getContextId(), srcRgb, srcAlpha)); 789 transforms.addAll(transformsForGlBlendFuncSrcDst(false, 790 msg.getContextId(), dstRgb, dstAlpha)); 791 return transforms; 792 } 793 794 private static List<IStateTransform> transformsForGlBlendFunc(GLMessage msg) { 795 // void glBlendFunc(GLenum sfactor, GLenum dfactor); 796 GLEnum sfactor = GLEnum.valueOf(msg.getArgs(0).getIntValue(0)); 797 GLEnum dfactor = GLEnum.valueOf(msg.getArgs(1).getIntValue(0)); 798 799 List<IStateTransform> transforms = new ArrayList<IStateTransform>(); 800 transforms.addAll(transformsForGlBlendFuncSrcDst(true, 801 msg.getContextId(), sfactor, sfactor)); 802 transforms.addAll(transformsForGlBlendFuncSrcDst(false, 803 msg.getContextId(), dfactor, dfactor)); 804 return transforms; 805 } 806 807 private static List<IStateTransform> transformsForGlPixelStorei(GLMessage msg) { 808 // void glPixelStorei(GLenum pname, GLint param); 809 GLEnum pname = GLEnum.valueOf(msg.getArgs(0).getIntValue(0)); 810 Integer param = Integer.valueOf(msg.getArgs(1).getIntValue(0)); 811 812 IStateTransform transform; 813 if (pname == GLEnum.GL_PACK_ALIGNMENT) { 814 transform = new PropertyChangeTransform( 815 GLPropertyAccessor.makeAccessor(msg.getContextId(), 816 GLStateType.PIXEL_PACKING, 817 GLStateType.PACK_ALIGNMENT), 818 param); 819 } else { 820 transform = new PropertyChangeTransform( 821 GLPropertyAccessor.makeAccessor(msg.getContextId(), 822 GLStateType.PIXEL_PACKING, 823 GLStateType.UNPACK_ALIGNMENT), 824 param); 825 } 826 827 return Collections.singletonList(transform); 828 } 829 830 private static List<IStateTransform> transformsForGlViewport(GLMessage msg) { 831 // void glViewport( GLint x, GLint y, GLsizei width, GLsizei height); 832 int x = msg.getArgs(0).getIntValue(0); 833 int y = msg.getArgs(1).getIntValue(0); 834 int w = msg.getArgs(2).getIntValue(0); 835 int h = msg.getArgs(3).getIntValue(0); 836 837 List<IStateTransform> transforms = new ArrayList<IStateTransform>(); 838 transforms.add(new PropertyChangeTransform( 839 GLPropertyAccessor.makeAccessor(msg.getContextId(), 840 GLStateType.TRANSFORMATION_STATE, 841 GLStateType.VIEWPORT, 842 GLStateType.VIEWPORT_X), 843 Integer.valueOf(x))); 844 transforms.add(new PropertyChangeTransform( 845 GLPropertyAccessor.makeAccessor(msg.getContextId(), 846 GLStateType.TRANSFORMATION_STATE, 847 GLStateType.VIEWPORT, 848 GLStateType.VIEWPORT_Y), 849 Integer.valueOf(y))); 850 transforms.add(new PropertyChangeTransform( 851 GLPropertyAccessor.makeAccessor(msg.getContextId(), 852 GLStateType.TRANSFORMATION_STATE, 853 GLStateType.VIEWPORT, 854 GLStateType.VIEWPORT_WIDTH), 855 Integer.valueOf(w))); 856 transforms.add(new PropertyChangeTransform( 857 GLPropertyAccessor.makeAccessor(msg.getContextId(), 858 GLStateType.TRANSFORMATION_STATE, 859 GLStateType.VIEWPORT, 860 GLStateType.VIEWPORT_HEIGHT), 861 Integer.valueOf(h))); 862 return transforms; 863 } 864 865 private static List<IStateTransform> transformsForGlDepthRangef(GLMessage msg) { 866 // void glDepthRangef(GLclampf nearVal, GLclampf farVal); 867 float near = msg.getArgs(0).getFloatValue(0); 868 float far = msg.getArgs(1).getFloatValue(0); 869 870 List<IStateTransform> transforms = new ArrayList<IStateTransform>(); 871 transforms.add(new PropertyChangeTransform( 872 GLPropertyAccessor.makeAccessor(msg.getContextId(), 873 GLStateType.TRANSFORMATION_STATE, 874 GLStateType.DEPTH_RANGE, 875 GLStateType.DEPTH_RANGE_NEAR), 876 Float.valueOf(near))); 877 transforms.add(new PropertyChangeTransform( 878 GLPropertyAccessor.makeAccessor(msg.getContextId(), 879 GLStateType.TRANSFORMATION_STATE, 880 GLStateType.DEPTH_RANGE, 881 GLStateType.DEPTH_RANGE_FAR), 882 Float.valueOf(far))); 883 return transforms; 884 } 885 886 private static List<IStateTransform> transformsForGlGenTextures(GLMessage msg) { 887 // void glGenTextures(GLsizei n, GLuint *textures); 888 int n = msg.getArgs(0).getIntValue(0); 889 890 List<IStateTransform> transforms = new ArrayList<IStateTransform>(); 891 for (int i = 0; i < n; i++) { 892 int texture = msg.getArgs(1).getIntValue(i); 893 transforms.add(new SparseArrayElementAddTransform( 894 GLPropertyAccessor.makeAccessor(msg.getContextId(), 895 GLStateType.TEXTURE_STATE, 896 GLStateType.TEXTURES), 897 texture)); 898 } 899 900 return transforms; 901 } 902 903 /** 904 * Obtain a list of transforms that will reset any existing texture units 905 * that are bound to provided texture. 906 * @param contextId context to operate on 907 * @param texture texture that should be unbound 908 */ 909 private static List<IStateTransform> transformsToResetBoundTextureUnits(int contextId, 910 int texture) { 911 List<IStateTransform> transforms = new ArrayList<IStateTransform>( 912 GLState.TEXTURE_UNIT_COUNT); 913 914 for (int i = 0; i < GLState.TEXTURE_UNIT_COUNT; i++) { 915 transforms.add(new PropertyChangeTransform( 916 GLPropertyAccessor.makeAccessor(contextId, 917 GLStateType.TEXTURE_STATE, 918 GLStateType.TEXTURE_UNITS, 919 Integer.valueOf(i), 920 GLStateType.TEXTURE_BINDING_2D), 921 Integer.valueOf(0), /* reset binding to texture 0 */ 922 Predicates.matchesInteger(texture) /* only if currently bound to @texture */ )); 923 } 924 return transforms; 925 } 926 927 private static List<IStateTransform> transformsForGlDeleteTextures(GLMessage msg) { 928 // void glDeleteTextures(GLsizei n, const GLuint * textures); 929 int n = msg.getArgs(0).getIntValue(0); 930 931 List<IStateTransform> transforms = new ArrayList<IStateTransform>(n); 932 for (int i = 0; i < n; i++) { 933 int texture = msg.getArgs(1).getIntValue(i); 934 transforms.add(new SparseArrayElementRemoveTransform( 935 GLPropertyAccessor.makeAccessor(msg.getContextId(), 936 GLStateType.TEXTURE_STATE, 937 GLStateType.TEXTURES), 938 texture)); 939 transforms.addAll(transformsToResetBoundTextureUnits(msg.getContextId(), texture)); 940 } 941 942 return transforms; 943 } 944 945 private static List<IStateTransform> transformsForGlActiveTexture(GLMessage msg) { 946 // void glActiveTexture(GLenum texture); 947 GLEnum texture = GLEnum.valueOf(msg.getArgs(0).getIntValue(0)); 948 Integer textureIndex = Integer.valueOf((int)(texture.value - GLEnum.GL_TEXTURE0.value)); 949 IStateTransform transform = new PropertyChangeTransform( 950 GLPropertyAccessor.makeAccessor(msg.getContextId(), 951 GLStateType.TEXTURE_STATE, 952 GLStateType.ACTIVE_TEXTURE_UNIT), 953 textureIndex); 954 return Collections.singletonList(transform); 955 } 956 957 private static GLStateType getTextureUnitTargetName(GLEnum target) { 958 if (target == GLEnum.GL_TEXTURE_CUBE_MAP) { 959 return GLStateType.TEXTURE_BINDING_CUBE_MAP; 960 } else if (target == GLEnum.GL_TEXTURE_EXTERNAL) { 961 // added by OES_EGL_image_external 962 return GLStateType.TEXTURE_BINDING_EXTERNAL; 963 } else { 964 return GLStateType.TEXTURE_BINDING_2D; 965 } 966 } 967 968 private static GLStateType getTextureTargetName(GLEnum pname) { 969 switch (pname) { 970 case GL_TEXTURE_MIN_FILTER: 971 return GLStateType.TEXTURE_MIN_FILTER; 972 case GL_TEXTURE_MAG_FILTER: 973 return GLStateType.TEXTURE_MAG_FILTER; 974 case GL_TEXTURE_WRAP_S: 975 return GLStateType.TEXTURE_WRAP_S; 976 case GL_TEXTURE_WRAP_T: 977 return GLStateType.TEXTURE_WRAP_T; 978 } 979 980 assert false : "glTexParameter's pname argument does not support provided value."; 981 return GLStateType.TEXTURE_MIN_FILTER; 982 } 983 984 private static List<IStateTransform> transformsForGlBindTexture(GLMessage msg) { 985 // void glBindTexture(GLenum target, GLuint texture); 986 GLEnum target = GLEnum.valueOf(msg.getArgs(0).getIntValue(0)); 987 Integer texture = Integer.valueOf(msg.getArgs(1).getIntValue(0)); 988 989 IStateTransform transform = new PropertyChangeTransform( 990 new TextureUnitPropertyAccessor(msg.getContextId(), 991 getTextureUnitTargetName(target)), 992 texture); 993 return Collections.singletonList(transform); 994 } 995 996 /** 997 * Utility function used by both {@link #transformsForGlTexImage2D(GLMessage) and 998 * {@link #transformsForGlTexSubImage2D(GLMessage)}. 999 */ 1000 private static List<IStateTransform> transformsForGlTexImage(GLMessage msg, int widthArgIndex, 1001 int heightArgIndex, int xOffsetIndex, int yOffsetIndex) { 1002 GLEnum target = GLEnum.valueOf(msg.getArgs(0).getIntValue(0)); 1003 int level = msg.getArgs(1).getIntValue(0); 1004 Integer width = Integer.valueOf(msg.getArgs(widthArgIndex).getIntValue(0)); 1005 Integer height = Integer.valueOf(msg.getArgs(heightArgIndex).getIntValue(0)); 1006 GLEnum format = GLEnum.valueOf(msg.getArgs(6).getIntValue(0)); 1007 GLEnum type = GLEnum.valueOf(msg.getArgs(7).getIntValue(0)); 1008 1009 List<IStateTransform> transforms = new ArrayList<IStateTransform>(); 1010 transforms.add(new PropertyChangeTransform( 1011 new TexturePropertyAccessor(msg.getContextId(), 1012 getTextureUnitTargetName(target), 1013 level, 1014 GLStateType.TEXTURE_WIDTH), 1015 width)); 1016 transforms.add(new PropertyChangeTransform( 1017 new TexturePropertyAccessor(msg.getContextId(), 1018 getTextureUnitTargetName(target), 1019 level, 1020 GLStateType.TEXTURE_HEIGHT), 1021 height)); 1022 transforms.add(new PropertyChangeTransform( 1023 new TexturePropertyAccessor(msg.getContextId(), 1024 getTextureUnitTargetName(target), 1025 level, 1026 GLStateType.TEXTURE_FORMAT), 1027 format)); 1028 transforms.add(new PropertyChangeTransform( 1029 new TexturePropertyAccessor(msg.getContextId(), 1030 getTextureUnitTargetName(target), 1031 level, 1032 GLStateType.TEXTURE_IMAGE_TYPE), 1033 type)); 1034 1035 // if texture data is available, extract and store it in the cache folder 1036 File f = null; 1037 if (msg.getArgs(8).getIsArray()) { 1038 ByteString data = msg.getArgs(8).getRawBytes(0); 1039 f = FileUtils.createTempFile(TEXTURE_DATA_FILE_PREFIX, TEXTURE_DATA_FILE_SUFFIX); 1040 try { 1041 Files.write(data.toByteArray(), f); 1042 } catch (IOException e) { 1043 throw new RuntimeException(e); 1044 } 1045 } 1046 1047 int xOffset = 0; 1048 int yOffset = 0; 1049 1050 if (xOffsetIndex >= 0) { 1051 xOffset = msg.getArgs(xOffsetIndex).getIntValue(0); 1052 } 1053 1054 if (yOffsetIndex >= 0) { 1055 yOffset = msg.getArgs(yOffsetIndex).getIntValue(0); 1056 } 1057 1058 transforms.add(new TexImageTransform( 1059 new TexturePropertyAccessor(msg.getContextId(), 1060 getTextureUnitTargetName(target), 1061 level, 1062 GLStateType.TEXTURE_IMAGE), 1063 f, format, type, xOffset, yOffset, width, height)); 1064 1065 return transforms; 1066 } 1067 1068 private static List<IStateTransform> transformsForGlTexImage2D(GLMessage msg) { 1069 // void glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, 1070 // GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *data); 1071 return transformsForGlTexImage(msg, 3, 4, -1, -1); 1072 } 1073 1074 private static List<IStateTransform> transformsForGlTexSubImage2D(GLMessage msg) { 1075 // void glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, 1076 // GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *data); 1077 return transformsForGlTexImage(msg, 4, 5, 2, 3); 1078 } 1079 1080 private static List<IStateTransform> transformsForGlTexParameter(GLMessage msg) { 1081 // void glTexParameteri(GLenum target, GLenum pname, GLint param); 1082 GLEnum target = GLEnum.valueOf(msg.getArgs(0).getIntValue(0)); 1083 GLEnum pname = GLEnum.valueOf(msg.getArgs(1).getIntValue(0)); 1084 GLEnum pvalue = GLEnum.valueOf(msg.getArgs(2).getIntValue(0)); 1085 1086 if (sTexParameterPnameValues == null) { 1087 GLEnum[] pnameValues = new GLEnum[] { 1088 GLEnum.GL_TEXTURE_BASE_LEVEL, 1089 GLEnum.GL_TEXTURE_COMPARE_FUNC, 1090 GLEnum.GL_TEXTURE_COMPARE_MODE, 1091 GLEnum.GL_TEXTURE_MIN_FILTER, 1092 GLEnum.GL_TEXTURE_MAG_FILTER, 1093 GLEnum.GL_TEXTURE_MIN_LOD, 1094 GLEnum.GL_TEXTURE_MAX_LOD, 1095 GLEnum.GL_TEXTURE_MAX_LEVEL, 1096 GLEnum.GL_TEXTURE_SWIZZLE_R, 1097 GLEnum.GL_TEXTURE_SWIZZLE_G, 1098 GLEnum.GL_TEXTURE_SWIZZLE_B, 1099 GLEnum.GL_TEXTURE_SWIZZLE_A, 1100 GLEnum.GL_TEXTURE_WRAP_S, 1101 GLEnum.GL_TEXTURE_WRAP_T, 1102 GLEnum.GL_TEXTURE_WRAP_R 1103 }; 1104 sTexParameterPnameValues = EnumSet.copyOf(Arrays.asList(pnameValues)); 1105 } 1106 1107 if (!sTexParameterPnameValues.contains(pname)) { 1108 throw new IllegalArgumentException( 1109 String.format("Unsupported parameter (%s) for glTexParameter()", pname)); 1110 } 1111 1112 IStateTransform transform = new PropertyChangeTransform( 1113 new TexturePropertyAccessor(msg.getContextId(), 1114 getTextureUnitTargetName(target), 1115 getTextureTargetName(pname)), 1116 pvalue); 1117 return Collections.singletonList(transform); 1118 } 1119 1120 private static List<IStateTransform> transformsForGlCreateProgram(GLMessage msg) { 1121 // GLuint glCreateProgram(void); 1122 int program = msg.getReturnValue().getIntValue(0); 1123 1124 IStateTransform transform = new SparseArrayElementAddTransform( 1125 GLPropertyAccessor.makeAccessor(msg.getContextId(), 1126 GLStateType.PROGRAM_STATE, 1127 GLStateType.PROGRAMS), 1128 program); 1129 return Collections.singletonList(transform); 1130 } 1131 1132 private static List<IStateTransform> transformsForGlUseProgram(GLMessage msg) { 1133 // void glUseProgram(GLuint program); 1134 Integer program = Integer.valueOf(msg.getArgs(0).getIntValue(0)); 1135 1136 IStateTransform transform = new PropertyChangeTransform( 1137 GLPropertyAccessor.makeAccessor(msg.getContextId(), 1138 GLStateType.PROGRAM_STATE, 1139 GLStateType.CURRENT_PROGRAM), 1140 program); 1141 return Collections.singletonList(transform); 1142 } 1143 1144 private static List<IStateTransform> transformsForGlAttachShader(GLMessage msg) { 1145 // void glAttachShader(GLuint program, GLuint shader); 1146 int program = msg.getArgs(0).getIntValue(0); 1147 int shader = msg.getArgs(1).getIntValue(0); 1148 1149 IStateTransform transform = new SparseArrayElementAddTransform( 1150 GLPropertyAccessor.makeAccessor(msg.getContextId(), 1151 GLStateType.PROGRAM_STATE, 1152 GLStateType.PROGRAMS, 1153 Integer.valueOf(program), 1154 GLStateType.ATTACHED_SHADERS), 1155 Integer.valueOf(shader)); 1156 return Collections.singletonList(transform); 1157 } 1158 1159 private static List<IStateTransform> transformsForGlDetachShader(GLMessage msg) { 1160 // void glDetachShader(GLuint program, GLuint shader); 1161 int program = msg.getArgs(0).getIntValue(0); 1162 int shader = msg.getArgs(1).getIntValue(0); 1163 1164 IStateTransform transform = new SparseArrayElementRemoveTransform( 1165 GLPropertyAccessor.makeAccessor(msg.getContextId(), 1166 GLStateType.PROGRAM_STATE, 1167 GLStateType.PROGRAMS, 1168 Integer.valueOf(program), 1169 GLStateType.ATTACHED_SHADERS), 1170 Integer.valueOf(shader)); 1171 return Collections.singletonList(transform); 1172 } 1173 1174 private static List<IStateTransform> transformsForGlGetActiveAttribOrUniform( 1175 GLMessage msg, boolean isAttrib) { 1176 // void glGetActive[Attrib|Uniform](GLuint program, GLuint index, GLsizei bufsize, 1177 // GLsizei* length, GLint* size, GLenum* type, GLchar* name); 1178 int program = msg.getArgs(0).getIntValue(0); 1179 int size = msg.getArgs(4).getIntValue(0); 1180 GLEnum type = GLEnum.valueOf(msg.getArgs(5).getIntValue(0)); 1181 String name = msg.getArgs(6).getCharValue(0).toStringUtf8(); 1182 1183 // The 2nd argument (index) does not give the correct location of the 1184 // attribute/uniform in device. The actual location is obtained from 1185 // the getAttribLocation or getUniformLocation calls. The trace library 1186 // appends this value as an additional last argument to this call. 1187 int location = msg.getArgs(7).getIntValue(0); 1188 1189 GLStateType activeInput; 1190 GLStateType inputName; 1191 GLStateType inputType; 1192 GLStateType inputSize; 1193 1194 if (isAttrib) { 1195 activeInput = GLStateType.ACTIVE_ATTRIBUTES; 1196 inputName = GLStateType.ATTRIBUTE_NAME; 1197 inputType = GLStateType.ATTRIBUTE_TYPE; 1198 inputSize = GLStateType.ATTRIBUTE_SIZE; 1199 } else { 1200 activeInput = GLStateType.ACTIVE_UNIFORMS; 1201 inputName = GLStateType.UNIFORM_NAME; 1202 inputType = GLStateType.UNIFORM_TYPE; 1203 inputSize = GLStateType.UNIFORM_SIZE; 1204 } 1205 1206 IStateTransform addAttribute = new SparseArrayElementAddTransform( 1207 GLPropertyAccessor.makeAccessor(msg.getContextId(), 1208 GLStateType.PROGRAM_STATE, 1209 GLStateType.PROGRAMS, 1210 Integer.valueOf(program), 1211 activeInput), 1212 Integer.valueOf(location)); 1213 IStateTransform setAttributeName = new PropertyChangeTransform( 1214 GLPropertyAccessor.makeAccessor(msg.getContextId(), 1215 GLStateType.PROGRAM_STATE, 1216 GLStateType.PROGRAMS, 1217 Integer.valueOf(program), 1218 activeInput, 1219 Integer.valueOf(location), 1220 inputName), 1221 name); 1222 IStateTransform setAttributeType = new PropertyChangeTransform( 1223 GLPropertyAccessor.makeAccessor(msg.getContextId(), 1224 GLStateType.PROGRAM_STATE, 1225 GLStateType.PROGRAMS, 1226 Integer.valueOf(program), 1227 activeInput, 1228 Integer.valueOf(location), 1229 inputType), 1230 type); 1231 IStateTransform setAttributeSize = new PropertyChangeTransform( 1232 GLPropertyAccessor.makeAccessor(msg.getContextId(), 1233 GLStateType.PROGRAM_STATE, 1234 GLStateType.PROGRAMS, 1235 Integer.valueOf(program), 1236 activeInput, 1237 Integer.valueOf(location), 1238 inputSize), 1239 Integer.valueOf(size)); 1240 return Arrays.asList(addAttribute, setAttributeName, setAttributeType, setAttributeSize); 1241 } 1242 1243 private static List<IStateTransform> transformsForGlGetActiveAttrib(GLMessage msg) { 1244 return transformsForGlGetActiveAttribOrUniform(msg, true); 1245 } 1246 1247 private static List<IStateTransform> transformsForGlGetActiveUniform(GLMessage msg) { 1248 return transformsForGlGetActiveAttribOrUniform(msg, false); 1249 } 1250 1251 private static List<IStateTransform> transformsForGlUniformMatrix(GLMessage msg) { 1252 // void glUniformMatrix[2|3|4]fv(GLint location, GLsizei count, GLboolean transpose, 1253 // const GLfloat *value); 1254 int location = msg.getArgs(0).getIntValue(0); 1255 List<Float> uniforms = msg.getArgs(3).getFloatValueList(); 1256 1257 IStateTransform setValues = new PropertyChangeTransform( 1258 new CurrentProgramPropertyAccessor(msg.getContextId(), 1259 GLStateType.ACTIVE_UNIFORMS, 1260 location, 1261 GLStateType.UNIFORM_VALUE), 1262 uniforms); 1263 1264 return Collections.singletonList(setValues); 1265 } 1266 1267 private static List<IStateTransform> transformsForGlUniformv(GLMessage msg, boolean isFloats) { 1268 // void glUniform1fv(GLint location, GLsizei count, const GLfloat *value); 1269 int location = msg.getArgs(0).getIntValue(0); 1270 List<?> uniforms; 1271 if (isFloats) { 1272 uniforms = msg.getArgs(2).getFloatValueList(); 1273 } else { 1274 uniforms = msg.getArgs(2).getIntValueList(); 1275 } 1276 1277 IStateTransform setValues = new PropertyChangeTransform( 1278 new CurrentProgramPropertyAccessor(msg.getContextId(), 1279 GLStateType.ACTIVE_UNIFORMS, 1280 location, 1281 GLStateType.UNIFORM_VALUE), 1282 uniforms); 1283 1284 return Collections.singletonList(setValues); 1285 } 1286 1287 private static List<IStateTransform> transformsForGlUniform(GLMessage msg, boolean isFloats) { 1288 // void glUniform1f(GLint location, GLfloat v0); 1289 // void glUniform2f(GLint location, GLfloat v0, GLfloat v1); 1290 // .. 3f 1291 // .. 4f 1292 // void glUniform1i(GLint location, GLfloat v0); 1293 // void glUniform2i(GLint location, GLfloat v0, GLfloat v1); 1294 // .. 3i 1295 // .. 4i 1296 1297 int location = msg.getArgs(0).getIntValue(0); 1298 if (location < 0) { 1299 throw new IllegalArgumentException("Argument location cannot be less than 0."); 1300 } 1301 List<?> uniforms; 1302 if (isFloats) { 1303 List<Float> args = new ArrayList<Float>(msg.getArgsCount() - 1); 1304 for (int i = 1; i < msg.getArgsCount(); i++) { 1305 args.add(Float.valueOf(msg.getArgs(1).getFloatValue(0))); 1306 } 1307 uniforms = args; 1308 } else { 1309 List<Integer> args = new ArrayList<Integer>(msg.getArgsCount() - 1); 1310 for (int i = 1; i < msg.getArgsCount(); i++) { 1311 args.add(Integer.valueOf(msg.getArgs(1).getIntValue(0))); 1312 } 1313 uniforms = args; 1314 } 1315 1316 IStateTransform setValues = new PropertyChangeTransform( 1317 new CurrentProgramPropertyAccessor(msg.getContextId(), 1318 GLStateType.ACTIVE_UNIFORMS, 1319 location, 1320 GLStateType.UNIFORM_VALUE), 1321 uniforms); 1322 1323 return Collections.singletonList(setValues); 1324 } 1325 1326 private static List<IStateTransform> transformsForGlCreateShader(GLMessage msg) { 1327 // GLuint glCreateShader(GLenum shaderType); 1328 GLEnum shaderType = GLEnum.valueOf(msg.getArgs(0).getIntValue(0)); 1329 int shader = msg.getReturnValue().getIntValue(0); 1330 1331 IStateTransform addShader = new SparseArrayElementAddTransform( 1332 GLPropertyAccessor.makeAccessor(msg.getContextId(), 1333 GLStateType.SHADERS), 1334 shader); 1335 IStateTransform setShaderType = new PropertyChangeTransform( 1336 GLPropertyAccessor.makeAccessor(msg.getContextId(), 1337 GLStateType.SHADERS, 1338 Integer.valueOf(shader), 1339 GLStateType.SHADER_TYPE), 1340 shaderType); 1341 return Arrays.asList(addShader, setShaderType); 1342 } 1343 1344 private static List<IStateTransform> transformsForGlDeleteShader(GLMessage msg) { 1345 // void glDeleteShader(GLuint shader); 1346 int shader = msg.getArgs(0).getIntValue(0); 1347 1348 IStateTransform transform = new SparseArrayElementRemoveTransform( 1349 GLPropertyAccessor.makeAccessor(msg.getContextId(), 1350 GLStateType.SHADERS), 1351 shader); 1352 return Collections.singletonList(transform); 1353 } 1354 1355 private static List<IStateTransform> transformsForGlShaderSource(GLMessage msg) { 1356 // void glShaderSource(GLuint shader, GLsizei count, const GLchar **string, 1357 // const GLint *length); 1358 // This message is patched up on the device to return a single string as opposed to a 1359 // list of strings 1360 int shader = msg.getArgs(0).getIntValue(0); 1361 String src = msg.getArgs(2).getCharValue(0).toStringUtf8(); 1362 1363 IStateTransform transform = new PropertyChangeTransform( 1364 GLPropertyAccessor.makeAccessor(msg.getContextId(), 1365 GLStateType.SHADERS, 1366 Integer.valueOf(shader), 1367 GLStateType.SHADER_SOURCE), 1368 src); 1369 return Collections.singletonList(transform); 1370 } 1371 1372 private static List<IStateTransform> transformsForEglCreateContext(GLMessage msg) { 1373 // void eglCreateContext(int version, int context); 1374 int version = msg.getArgs(0).getIntValue(0); 1375 IGLProperty glState = null; 1376 if (version == 0) { 1377 glState = GLState.createDefaultES1State(); 1378 } else { 1379 glState = GLState.createDefaultES2State(); 1380 } 1381 IStateTransform transform = new ListElementAddTransform(null, glState); 1382 return Collections.singletonList(transform); 1383 } 1384 } 1385