Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <vector> | 5 #include <vector> |
| 6 #include <string> | 6 #include <string> |
| 7 #include <map> | 7 #include <map> |
| 8 #include <build/build_config.h> | 8 #include <build/build_config.h> |
| 9 #include "base/scoped_ptr.h" | 9 #include "base/scoped_ptr.h" |
| 10 #define GLES2_GPU_SERVICE 1 | 10 #define GLES2_GPU_SERVICE 1 |
| 11 #include "gpu/command_buffer/common/gles2_cmd_format.h" | 11 #include "gpu/command_buffer/common/gles2_cmd_format.h" |
| 12 #include "gpu/command_buffer/common/gles2_cmd_utils.h" | 12 #include "gpu/command_buffer/common/gles2_cmd_utils.h" |
| 13 #include "gpu/command_buffer/service/cmd_buffer_engine.h" | 13 #include "gpu/command_buffer/service/cmd_buffer_engine.h" |
| 14 #include "gpu/command_buffer/service/gl_utils.h" | 14 #include "gpu/command_buffer/service/gl_utils.h" |
| 15 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" | 15 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" |
| 16 #include "gpu/command_buffer/service/gles2_cmd_validation.h" | 16 #include "gpu/command_buffer/service/gles2_cmd_validation.h" |
| 17 | 17 |
| 18 namespace gpu { | 18 namespace gpu { |
| 19 namespace gles2 { | 19 namespace gles2 { |
| 20 | 20 |
| 21 // Check that certain assumptions the code makes are true. There are places in | |
| 22 // the code where shared memory is passed direclty to GL. Example, glUniformiv, | |
| 23 // glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe | |
| 24 // a few others) are 32bits. If they are not 32bits the code will have to change | |
| 25 // to call those GL functions with service side memory and then copy the results | |
| 26 // to shared memory, converting the sizes. | |
| 27 COMPILE_ASSERT(sizeof(GLint) == sizeof(uint32), // NOLINT | |
| 28 GLint_not_same_size_as_uint32); | |
| 29 COMPILE_ASSERT(sizeof(GLsizei) == sizeof(uint32), // NOLINT | |
| 30 GLint_not_same_size_as_uint32); | |
| 31 | |
| 21 namespace { | 32 namespace { |
| 22 | 33 |
| 34 size_t GetGLTypeSize(GLenum type) { | |
| 35 switch (type) { | |
| 36 case GL_BYTE: | |
| 37 return sizeof(GLbyte); // NOLINT | |
| 38 case GL_UNSIGNED_BYTE: | |
| 39 return sizeof(GLubyte); // NOLINT | |
| 40 case GL_SHORT: | |
| 41 return sizeof(GLshort); // NOLINT | |
| 42 case GL_UNSIGNED_SHORT: | |
| 43 return sizeof(GLushort); // NOLINT | |
| 44 case GL_FLOAT: | |
| 45 return sizeof(GLfloat); // NOLINT | |
| 46 default: | |
| 47 return 0; | |
| 48 } | |
| 49 } | |
| 50 | |
| 23 // Returns the address of the first byte after a struct. | 51 // Returns the address of the first byte after a struct. |
| 24 template <typename T> | 52 template <typename T> |
| 25 const void* AddressAfterStruct(const T& pod) { | 53 const void* AddressAfterStruct(const T& pod) { |
| 26 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod); | 54 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod); |
| 27 } | 55 } |
| 28 | 56 |
| 29 // Returns the address of the frst byte after the struct. | 57 // Returns the address of the frst byte after the struct or NULL if size > |
| 58 // immediate_data_size. | |
| 30 template <typename RETURN_TYPE, typename COMMAND_TYPE> | 59 template <typename RETURN_TYPE, typename COMMAND_TYPE> |
| 31 RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod) { | 60 RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod, |
| 32 return static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))); | 61 uint32 size, |
| 62 uint32 immediate_data_size) { | |
| 63 return (size <= immediate_data_size) ? | |
| 64 static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))) : | |
| 65 NULL; | |
| 33 } | 66 } |
| 34 | 67 |
| 35 // Checks if there is enough immediate data. | 68 // Computes the data size for certain gl commands like glUniform. |
| 36 template<typename T> | 69 uint32 ComputeImmediateDataSize( |
| 37 bool CheckImmediateDataSize( | |
| 38 uint32 immediate_data_size, | 70 uint32 immediate_data_size, |
| 39 GLuint count, | 71 GLuint count, |
| 40 size_t size, | 72 size_t size, |
| 41 unsigned int elements_per_unit) { | 73 unsigned int elements_per_unit) { |
| 42 return immediate_data_size == count * size * elements_per_unit; | 74 return count * size * elements_per_unit; |
| 43 } | 75 } |
| 44 | 76 |
| 45 // A struct to hold info about each command. | 77 // A struct to hold info about each command. |
| 46 struct CommandInfo { | 78 struct CommandInfo { |
| 47 int arg_flags; // How to handle the arguments for this command | 79 int arg_flags; // How to handle the arguments for this command |
| 48 int arg_count; // How many arguments are expected for this command. | 80 int arg_count; // How many arguments are expected for this command. |
| 49 }; | 81 }; |
| 50 | 82 |
| 51 // A table of CommandInfo for all the commands. | 83 // A table of CommandInfo for all the commands. |
| 52 const CommandInfo g_command_info[] = { | 84 const CommandInfo g_command_info[] = { |
| 53 #define GLES2_CMD_OP(name) { \ | 85 #define GLES2_CMD_OP(name) { \ |
| 54 name::kArgFlags, \ | 86 name::kArgFlags, \ |
| 55 sizeof(name) / sizeof(CommandBufferEntry) - 1, }, /* NOLINT */ \ | 87 sizeof(name) / sizeof(CommandBufferEntry) - 1, }, /* NOLINT */ \ |
| 56 | 88 |
| 57 GLES2_COMMAND_LIST(GLES2_CMD_OP) | 89 GLES2_COMMAND_LIST(GLES2_CMD_OP) |
| 58 | 90 |
| 59 #undef GLES2_CMD_OP | 91 #undef GLES2_CMD_OP |
| 60 }; | 92 }; |
| 61 | 93 |
| 62 // These commands convert from c calls to local os calls. | |
| 63 void GLGenBuffersHelper(GLsizei n, GLuint* ids) { | |
| 64 glGenBuffersARB(n, ids); | |
| 65 } | |
| 66 | |
| 67 void GLGenFramebuffersHelper(GLsizei n, GLuint* ids) { | |
| 68 glGenFramebuffersEXT(n, ids); | |
| 69 } | |
| 70 | |
| 71 void GLGenRenderbuffersHelper(GLsizei n, GLuint* ids) { | |
| 72 glGenRenderbuffersEXT(n, ids); | |
| 73 } | |
| 74 | |
| 75 void GLGenTexturesHelper(GLsizei n, GLuint* ids) { | |
| 76 glGenTextures(n, ids); | |
| 77 } | |
| 78 | |
| 79 void GLDeleteBuffersHelper(GLsizei n, GLuint* ids) { | |
| 80 glDeleteBuffersARB(n, ids); | |
| 81 } | |
| 82 | |
| 83 void GLDeleteFramebuffersHelper(GLsizei n, GLuint* ids) { | |
| 84 glDeleteFramebuffersEXT(n, ids); | |
| 85 } | |
| 86 | |
| 87 void GLDeleteRenderbuffersHelper(GLsizei n, GLuint* ids) { | |
| 88 glDeleteRenderbuffersEXT(n, ids); | |
| 89 } | |
| 90 | |
| 91 void GLDeleteTexturesHelper(GLsizei n, GLuint* ids) { | |
| 92 glDeleteTextures(n, ids); | |
| 93 } | |
| 94 | |
| 95 namespace GLErrorBit { | 94 namespace GLErrorBit { |
| 96 enum GLErrorBit { | 95 enum GLErrorBit { |
| 97 kNoError = 0, | 96 kNoError = 0, |
| 98 kInvalidEnum, | 97 kInvalidEnum, |
| 99 kInvalidValue, | 98 kInvalidValue, |
| 100 kInvalidOperation, | 99 kInvalidOperation, |
| 101 kOutOfMemory, | 100 kOutOfMemory, |
| 102 kInvalidFrameBufferOperation, | 101 kInvalidFrameBufferOperation, |
| 103 }; | 102 }; |
| 104 } | 103 } |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 214 return true; | 213 return true; |
| 215 } | 214 } |
| 216 } | 215 } |
| 217 return false; | 216 return false; |
| 218 } | 217 } |
| 219 | 218 |
| 220 // This class implements GLES2Decoder so we don't have to expose all the GLES2 | 219 // This class implements GLES2Decoder so we don't have to expose all the GLES2 |
| 221 // cmd stuff to outside this class. | 220 // cmd stuff to outside this class. |
| 222 class GLES2DecoderImpl : public GLES2Decoder { | 221 class GLES2DecoderImpl : public GLES2Decoder { |
| 223 public: | 222 public: |
| 223 // Info about Vertex Attributes. This is used to track what the user currently | |
| 224 // has bound on each Vertex Attribute so that checking can be done at | |
| 225 // glDrawXXX time. | |
| 226 class VertexAttribInfo { | |
| 227 public: | |
| 228 VertexAttribInfo() | |
| 229 : enabled_(false), | |
| 230 size_(0), | |
| 231 type_(0), | |
| 232 offset_(0), | |
| 233 real_stride_(0), | |
| 234 buffer_(0), | |
| 235 buffer_size_(0), | |
| 236 num_elements_(0) { | |
| 237 } | |
| 238 // Returns true if this VertexAttrib can access index. | |
| 239 bool CanAccess(GLuint index); | |
| 240 | |
| 241 void set_enabled(bool enabled) { | |
| 242 enabled_ = enabled; | |
| 243 } | |
| 244 | |
| 245 GLuint buffer() const { | |
| 246 return buffer_; | |
| 247 } | |
| 248 | |
| 249 void Clear() { | |
| 250 buffer_ = 0; | |
| 251 SetBufferSize(0); | |
| 252 } | |
| 253 | |
| 254 void SetBufferSize(GLsizeiptr buffer_size) { | |
| 255 buffer_size_ = buffer_size; | |
| 256 if (offset_ > buffer_size || real_stride_ == 0) { | |
| 257 num_elements_ = 0; | |
| 258 } else { | |
| 259 uint32 size = buffer_size - offset_; | |
| 260 num_elements_ = size / real_stride_ + | |
| 261 (size % real_stride_ >= GetGLTypeSize(type_) ? 1 : 0); | |
| 262 } | |
| 263 } | |
| 264 | |
| 265 void SetInfo( | |
| 266 GLuint buffer, | |
| 267 GLsizeiptr buffer_size, | |
| 268 GLint size, | |
| 269 GLenum type, | |
| 270 GLsizei real_stride, | |
| 271 GLsizei offset) { | |
| 272 DCHECK(real_stride > 0); | |
| 273 buffer_ = buffer; | |
| 274 size_ = size; | |
| 275 type_ = type; | |
| 276 real_stride_ = real_stride; | |
| 277 offset_ = offset; | |
| 278 SetBufferSize(buffer_size); | |
| 279 } | |
| 280 | |
| 281 private: | |
| 282 // Whether or not this attribute is enabled. | |
| 283 bool enabled_; | |
| 284 | |
| 285 // number of components (1, 2, 3, 4) | |
| 286 GLint size_; | |
| 287 | |
| 288 // GL_BYTE, GL_FLOAT, etc. See glVertexAttribPointer. | |
| 289 GLenum type_; | |
| 290 | |
| 291 // The offset into the buffer. | |
| 292 GLsizei offset_; | |
| 293 | |
| 294 // The stride that will be used to access the buffer. This is the actual | |
| 295 // stide, NOT the GL bogus stride. In other words there is never a stride | |
| 296 // of 0. | |
| 297 GLsizei real_stride_; | |
| 298 | |
| 299 // The service side name of the buffer bound to this attribute. 0 = invalid | |
| 300 GLuint buffer_; | |
| 301 | |
| 302 // The size of the buffer. | |
| 303 GLsizeiptr buffer_size_; | |
| 304 | |
| 305 // The number of elements that can be accessed. | |
| 306 GLuint num_elements_; | |
| 307 }; | |
| 308 | |
| 309 // Info about Buffers currently in the system. | |
| 310 struct BufferInfo { | |
| 311 BufferInfo() | |
| 312 : size(0) { | |
| 313 } | |
| 314 | |
| 315 explicit BufferInfo(GLsizeiptr _size) | |
| 316 : size(_size) { | |
| 317 } | |
| 318 | |
| 319 GLsizeiptr size; | |
| 320 }; | |
| 321 | |
| 322 // This is used to track which attributes a particular program needs | |
| 323 // so we can verify at glDrawXXX time that every attribute is either disabled | |
| 324 // or if enabled that it points to a valid source. | |
| 325 class ProgramInfo { | |
| 326 public: | |
| 327 typedef std::vector<GLuint> AttribLocationVector; | |
| 328 | |
| 329 ProgramInfo() { | |
| 330 } | |
| 331 | |
| 332 void SetNumAttributes(int num_attribs) { | |
| 333 attrib_locations_.resize(num_attribs); | |
| 334 } | |
| 335 | |
| 336 void SetAttributeLocation(GLuint index, int location) { | |
| 337 DCHECK(index < attrib_locations_.size()); | |
| 338 attrib_locations_[index] = location; | |
| 339 } | |
| 340 | |
| 341 const AttribLocationVector& GetAttribLocations() const { | |
| 342 return attrib_locations_; | |
| 343 } | |
| 344 private: | |
| 345 AttribLocationVector attrib_locations_; | |
| 346 }; | |
| 347 | |
| 224 GLES2DecoderImpl(); | 348 GLES2DecoderImpl(); |
| 225 | 349 |
| 226 // Overridden from AsyncAPIInterface. | 350 // Overridden from AsyncAPIInterface. |
| 227 virtual ParseError DoCommand(unsigned int command, | 351 virtual ParseError DoCommand(unsigned int command, |
| 228 unsigned int arg_count, | 352 unsigned int arg_count, |
| 229 const void* args); | 353 const void* args); |
| 230 | 354 |
| 231 // Overridden from AsyncAPIInterface. | 355 // Overridden from AsyncAPIInterface. |
| 232 virtual const char* GetCommandName(unsigned int command_id) const; | 356 virtual const char* GetCommandName(unsigned int command_id) const; |
| 233 | 357 |
| 234 // Overridden from GLES2Decoder. | 358 // Overridden from GLES2Decoder. |
| 235 virtual bool Initialize(); | 359 virtual bool Initialize(); |
| 236 | 360 |
| 237 // Overridden from GLES2Decoder. | 361 // Overridden from GLES2Decoder. |
| 238 virtual void Destroy(); | 362 virtual void Destroy(); |
| 239 | 363 |
| 364 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used | |
| 365 // on glDeleteBuffers so we can make sure the user does not try to render | |
| 366 // with deleted buffers. | |
| 367 void RemoveBufferInfo(GLuint buffer_id); | |
| 368 | |
| 240 private: | 369 private: |
| 241 bool InitPlatformSpecific(); | 370 bool InitPlatformSpecific(); |
| 242 bool InitGlew(); | 371 bool InitGlew(); |
| 243 | 372 |
| 244 // Template to help call glGenXXX functions. | 373 // Template to help call glGenXXX functions. |
| 245 template <void gl_gen_function(GLsizei, GLuint*)> | 374 template <void gl_gen_function(GLES2DecoderImpl*, GLsizei, GLuint*)> |
| 246 bool GenGLObjects(GLsizei n, const GLuint* client_ids) { | 375 bool GenGLObjects(GLsizei n, const GLuint* client_ids) { |
| 247 // TODO(gman): Verify client ids are unused. | 376 // TODO(gman): Verify client ids are unused. |
| 248 scoped_array<GLuint>temp(new GLuint[n]); | 377 scoped_array<GLuint>temp(new GLuint[n]); |
| 249 gl_gen_function(n, temp.get()); | 378 gl_gen_function(this, n, temp.get()); |
| 250 // TODO(gman): check for success before copying results. | 379 // TODO(gman): check for success before copying results. |
| 251 for (GLsizei ii = 0; ii < n; ++ii) { | 380 return RegisterObjects(n, client_ids, temp.get()); |
| 252 if (!id_map_.AddMapping(client_ids[ii], temp[ii])) { | 381 } |
| 253 // TODO(gman): fail. | 382 |
| 254 } | 383 // Template to help call glDeleteXXX functions. |
| 255 } | 384 template <void gl_delete_function(GLES2DecoderImpl*, GLsizei, GLuint*)> |
| 385 bool DeleteGLObjects(GLsizei n, const GLuint* client_ids) { | |
| 386 scoped_array<GLuint>temp(new GLuint[n]); | |
| 387 UnregisterObjects(n, client_ids, temp.get()); | |
| 388 gl_delete_function(this, n, temp.get()); | |
| 256 return true; | 389 return true; |
| 257 } | 390 } |
| 258 | 391 |
| 259 // Template to help call glDeleteXXX functions. | 392 // Register client ids with generated service ids. |
| 260 template <void gl_delete_function(GLsizei, GLuint*)> | 393 bool RegisterObjects( |
| 261 bool DeleteGLObjects(GLsizei n, const GLuint* client_ids) { | 394 GLsizei n, const GLuint* client_ids, const GLuint* service_ids); |
| 262 scoped_array<GLuint>temp(new GLuint[n]); | 395 |
| 263 // TODO(gman): check for success before copying results. | 396 // Unregisters client ids with service ids. |
| 264 for (GLsizei ii = 0; ii < n; ++ii) { | 397 void UnregisterObjects( |
| 265 if (id_map_.GetServiceId(client_ids[ii], &temp[ii])) { | 398 GLsizei n, const GLuint* client_ids, GLuint* service_ids); |
| 266 id_map_.RemoveMapping(client_ids[ii], temp[ii]); | 399 |
| 267 } else { | 400 // Gets the program info for the given program. Returns NULL if none exists. |
| 268 temp[ii] = 0; | 401 // Programs that have no had glLinkProgram succesfully called on them will |
| 269 } | 402 // not exist. |
| 270 } | 403 ProgramInfo* GetProgramInfo(GLuint program); |
| 271 gl_delete_function(n, temp.get()); | 404 |
| 272 return true; | 405 // Updates the program info for the given program. |
| 273 } | 406 void UpdateProgramInfo(GLuint program); |
| 407 | |
| 408 // Deletes the program info for the given program. | |
| 409 void RemoveProgramInfo(GLuint program); | |
| 410 | |
| 411 // Gets the buffer info for the given buffer. | |
| 412 const BufferInfo* GetBufferInfo(GLuint buffer); | |
| 413 | |
| 414 // Sets the info for a buffer. | |
| 415 void SetBufferInfo(GLuint buffer, GLsizeiptr size); | |
| 274 | 416 |
| 275 // Wrapper for glCreateProgram | 417 // Wrapper for glCreateProgram |
| 276 void CreateProgramHelper(GLuint client_id); | 418 void CreateProgramHelper(GLuint client_id); |
| 277 | 419 |
| 278 // Wrapper for glCreateShader | 420 // Wrapper for glCreateShader |
| 279 void CreateShaderHelper(GLenum type, GLuint client_id); | 421 void CreateShaderHelper(GLenum type, GLuint client_id); |
| 280 | 422 |
| 281 // Wrapper for glBindBuffer since we need to track the current targets. | 423 // Wrapper for glBindBuffer since we need to track the current targets. |
| 282 void DoBindBuffer(GLenum target, GLuint buffer); | 424 void DoBindBuffer(GLenum target, GLuint buffer); |
| 283 | 425 |
| 426 // Wrapper for glBindBuffer since we need to track the current targets. | |
|
apatrick
2009/12/22 02:37:21
BindBuffer -> DrawArrays
| |
| 427 void DoDrawArrays(GLenum mode, GLint first, GLsizei count); | |
| 428 | |
| 429 // Wrapper for glDisableVertexAttribArray. | |
| 430 void DoDisableVertexAttribArray(GLuint index); | |
| 431 | |
| 432 // Wrapper for glEnableVertexAttribArray. | |
| 433 void DoEnableVertexAttribArray(GLuint index); | |
| 434 | |
| 435 // Wrapper for glLinkProgram | |
| 436 void DoLinkProgram(GLuint program); | |
| 437 | |
| 284 // Swaps the buffers (copies/renders to the current window). | 438 // Swaps the buffers (copies/renders to the current window). |
| 285 void DoSwapBuffers(); | 439 void DoSwapBuffers(); |
| 286 | 440 |
| 441 // Wrapper for glUseProgram | |
| 442 void DoUseProgram(GLuint program); | |
| 443 | |
| 287 // Gets the GLError through our wrapper. | 444 // Gets the GLError through our wrapper. |
| 288 GLenum GetGLError(); | 445 GLenum GetGLError(); |
| 289 | 446 |
| 290 // Sets our wrapper for the GLError. | 447 // Sets our wrapper for the GLError. |
| 291 void SetGLError(GLenum error); | 448 void SetGLError(GLenum error); |
| 292 | 449 |
| 450 // Copies the real GL errors to the wrapper. This is so we can | |
| 451 // make sure there are no native GL errors before calling some GL function | |
| 452 // so that on return we know any error generated was for that specific | |
| 453 // command. | |
| 454 void CopyRealGLErrorsToWrapper(); | |
| 455 | |
| 456 // Checks if the current program and vertex attributes are valid for drawing. | |
| 457 bool IsDrawValid(GLuint max_vertex_accessed); | |
| 458 | |
| 459 // Gets the buffer id for a given target. | |
| 460 GLuint GetBufferForTarget(GLenum target) { | |
| 461 DCHECK(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER); | |
| 462 return target == GL_ARRAY_BUFFER ? bound_array_buffer_ : | |
| 463 bound_element_array_buffer_; | |
| 464 } | |
| 465 | |
| 293 // Generate a member function prototype for each command in an automated and | 466 // Generate a member function prototype for each command in an automated and |
| 294 // typesafe way. | 467 // typesafe way. |
| 295 #define GLES2_CMD_OP(name) \ | 468 #define GLES2_CMD_OP(name) \ |
| 296 ParseError Handle ## name( \ | 469 ParseError Handle ## name( \ |
| 297 uint32 immediate_data_size, \ | 470 uint32 immediate_data_size, \ |
| 298 const gles2::name& args); \ | 471 const gles2::name& args); \ |
| 299 | 472 |
| 300 GLES2_COMMAND_LIST(GLES2_CMD_OP) | 473 GLES2_COMMAND_LIST(GLES2_CMD_OP) |
| 301 | 474 |
| 302 #undef GLES2_CMD_OP | 475 #undef GLES2_CMD_OP |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 317 GLint unpack_alignment_; | 490 GLint unpack_alignment_; |
| 318 | 491 |
| 319 // The currently bound array buffer. If this is 0 it is illegal to call | 492 // The currently bound array buffer. If this is 0 it is illegal to call |
| 320 // glVertexAttribPointer. | 493 // glVertexAttribPointer. |
| 321 GLuint bound_array_buffer_; | 494 GLuint bound_array_buffer_; |
| 322 | 495 |
| 323 // The currently bound element array buffer. If this is 0 it is illegal | 496 // The currently bound element array buffer. If this is 0 it is illegal |
| 324 // to call glDrawElements. | 497 // to call glDrawElements. |
| 325 GLuint bound_element_array_buffer_; | 498 GLuint bound_element_array_buffer_; |
| 326 | 499 |
| 500 // The maximum vertex attributes. | |
| 501 GLuint max_vertex_attribs_; | |
| 502 | |
| 503 // Info for each vertex attribute saved so we can check at glDrawXXX time | |
| 504 // if it is safe to draw. | |
| 505 scoped_array<VertexAttribInfo> vertex_attrib_infos_; | |
| 506 | |
| 507 // Infor for each buffer in the system. | |
|
apatrick
2009/12/22 02:37:21
Infor -> Info
| |
| 508 // TODO(gman): Choose a faster container. | |
| 509 typedef std::map<GLuint, BufferInfo> BufferInfoMap; | |
| 510 BufferInfoMap buffer_infos_; | |
| 511 | |
| 512 // Info for each "successfully linked" program by service side program Id. | |
| 513 // TODO(gman): Choose a faster container. | |
| 514 typedef std::map<GLuint, ProgramInfo> ProgramInfoMap; | |
| 515 ProgramInfoMap program_infos_; | |
| 516 | |
| 517 // The program in current use through glUseProgram. | |
| 518 ProgramInfo* current_program_info_; | |
| 519 | |
| 327 #if defined(OS_WIN) | 520 #if defined(OS_WIN) |
| 328 HDC device_context_; | 521 HDC device_context_; |
| 329 HGLRC gl_context_; | 522 HGLRC gl_context_; |
| 330 #endif | 523 #endif |
| 331 | 524 |
| 332 bool anti_aliased_; | 525 bool anti_aliased_; |
| 333 | 526 |
| 334 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl); | 527 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl); |
| 335 }; | 528 }; |
| 336 | 529 |
| 337 GLES2Decoder* GLES2Decoder::Create() { | 530 GLES2Decoder* GLES2Decoder::Create() { |
| 338 return new GLES2DecoderImpl(); | 531 return new GLES2DecoderImpl(); |
| 339 } | 532 } |
| 340 | 533 |
| 341 GLES2DecoderImpl::GLES2DecoderImpl() | 534 GLES2DecoderImpl::GLES2DecoderImpl() |
| 342 : GLES2Decoder(), | 535 : GLES2Decoder(), |
| 343 error_bits_(0), | 536 error_bits_(0), |
| 344 util_(0), // TODO(gman): Set to actual num compress texture formats. | 537 util_(0), // TODO(gman): Set to actual num compress texture formats. |
| 345 pack_alignment_(4), | 538 pack_alignment_(4), |
| 346 unpack_alignment_(4), | 539 unpack_alignment_(4), |
| 347 bound_array_buffer_(0), | 540 bound_array_buffer_(0), |
| 348 bound_element_array_buffer_(0), | 541 bound_element_array_buffer_(0), |
| 542 max_vertex_attribs_(0), | |
| 543 current_program_info_(NULL), | |
| 349 #ifdef OS_WIN | 544 #ifdef OS_WIN |
| 350 device_context_(NULL), | 545 device_context_(NULL), |
| 351 gl_context_(NULL), | 546 gl_context_(NULL), |
| 352 #endif | 547 #endif |
| 353 anti_aliased_(false) { | 548 anti_aliased_(false) { |
| 354 } | 549 } |
| 355 | 550 |
| 356 bool GLES2DecoderImpl::Initialize() { | 551 bool GLES2DecoderImpl::Initialize() { |
| 357 if (!InitPlatformSpecific()) | 552 if (!InitPlatformSpecific()) |
| 358 return false; | 553 return false; |
| 359 if (!InitGlew()) | 554 if (!InitGlew()) |
| 360 return false; | 555 return false; |
| 361 CHECK_GL_ERROR(); | 556 CHECK_GL_ERROR(); |
| 362 | 557 |
| 558 // Lookup GL things we need to know. | |
| 559 GLint value; | |
| 560 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &value); | |
| 561 max_vertex_attribs_ = value; | |
| 562 | |
| 563 DCHECK_GE(max_vertex_attribs_, 8u); | |
| 564 | |
| 565 vertex_attrib_infos_.reset(new VertexAttribInfo[max_vertex_attribs_]); | |
| 566 memset(vertex_attrib_infos_.get(), 0, | |
| 567 sizeof(vertex_attrib_infos_[0]) * max_vertex_attribs_); | |
| 568 | |
| 363 //glBindFramebuffer(0, 0); | 569 //glBindFramebuffer(0, 0); |
| 364 return true; | 570 return true; |
| 365 } | 571 } |
| 366 | 572 |
| 367 #if defined(OS_WIN) | 573 #if defined(OS_WIN) |
| 368 namespace { | 574 namespace { |
| 369 | 575 |
| 370 const PIXELFORMATDESCRIPTOR kPixelFormatDescriptor = { | 576 const PIXELFORMATDESCRIPTOR kPixelFormatDescriptor = { |
| 371 sizeof(kPixelFormatDescriptor), // Size of structure. | 577 sizeof(kPixelFormatDescriptor), // Size of structure. |
| 372 1, // Default version. | 578 1, // Default version. |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 526 | 732 |
| 527 ::wglMakeCurrent(intermediate_dc, NULL); | 733 ::wglMakeCurrent(intermediate_dc, NULL); |
| 528 ::wglDeleteContext(gl_context); | 734 ::wglDeleteContext(gl_context); |
| 529 ::ReleaseDC(intermediate_window, intermediate_dc); | 735 ::ReleaseDC(intermediate_window, intermediate_dc); |
| 530 ::DestroyWindow(intermediate_window); | 736 ::DestroyWindow(intermediate_window); |
| 531 ::UnregisterClass(reinterpret_cast<wchar_t*>(class_registration), | 737 ::UnregisterClass(reinterpret_cast<wchar_t*>(class_registration), |
| 532 module_handle); | 738 module_handle); |
| 533 return true; | 739 return true; |
| 534 } | 740 } |
| 535 | 741 |
| 742 // These commands convert from c calls to local os calls. | |
| 743 void GLGenBuffersHelper( | |
| 744 GLES2DecoderImpl*, GLsizei n, GLuint* ids) { | |
| 745 glGenBuffersARB(n, ids); | |
| 746 } | |
| 747 | |
| 748 void GLGenFramebuffersHelper( | |
| 749 GLES2DecoderImpl*, GLsizei n, GLuint* ids) { | |
| 750 glGenFramebuffersEXT(n, ids); | |
| 751 } | |
| 752 | |
| 753 void GLGenRenderbuffersHelper( | |
| 754 GLES2DecoderImpl*, GLsizei n, GLuint* ids) { | |
| 755 glGenRenderbuffersEXT(n, ids); | |
| 756 } | |
| 757 | |
| 758 void GLGenTexturesHelper( | |
| 759 GLES2DecoderImpl*, GLsizei n, GLuint* ids) { | |
| 760 glGenTextures(n, ids); | |
| 761 } | |
| 762 | |
| 763 void GLDeleteBuffersHelper( | |
| 764 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids) { | |
| 765 glDeleteBuffersARB(n, ids); | |
| 766 for (GLsizei ii = 0; ii < n; ++ii) { | |
| 767 decoder->RemoveBufferInfo(ids[ii]); | |
| 768 } | |
| 769 } | |
| 770 | |
| 771 void GLDeleteFramebuffersHelper( | |
| 772 GLES2DecoderImpl*, GLsizei n, GLuint* ids) { | |
| 773 glDeleteFramebuffersEXT(n, ids); | |
| 774 } | |
| 775 | |
| 776 void GLDeleteRenderbuffersHelper( | |
| 777 GLES2DecoderImpl*, GLsizei n, GLuint* ids) { | |
| 778 glDeleteRenderbuffersEXT(n, ids); | |
| 779 } | |
| 780 | |
| 781 void GLDeleteTexturesHelper( | |
| 782 GLES2DecoderImpl*, GLsizei n, GLuint* ids) { | |
| 783 glDeleteTextures(n, ids); | |
| 784 } | |
| 785 | |
| 536 } // anonymous namespace | 786 } // anonymous namespace |
| 537 #endif | 787 #endif |
| 538 | 788 |
| 789 bool GLES2DecoderImpl::RegisterObjects( | |
| 790 GLsizei n, const GLuint* client_ids, const GLuint* service_ids) { | |
| 791 for (GLsizei ii = 0; ii < n; ++ii) { | |
| 792 if (!id_map_.AddMapping(client_ids[ii], service_ids[ii])) { | |
| 793 // TODO(gman): fail. | |
| 794 } | |
| 795 } | |
| 796 return true; | |
| 797 } | |
| 798 | |
| 799 void GLES2DecoderImpl::UnregisterObjects( | |
| 800 GLsizei n, const GLuint* client_ids, GLuint* service_ids) { | |
| 801 // TODO(gman): check for success before copying results. | |
| 802 for (GLsizei ii = 0; ii < n; ++ii) { | |
| 803 if (id_map_.GetServiceId(client_ids[ii], &service_ids[ii])) { | |
| 804 id_map_.RemoveMapping(client_ids[ii], service_ids[ii]); | |
| 805 } else { | |
| 806 service_ids[ii] = 0; | |
| 807 } | |
| 808 } | |
| 809 } | |
| 810 | |
| 811 void GLES2DecoderImpl::RemoveBufferInfo(GLuint buffer_id) { | |
| 812 for (GLuint ii = 0; ii < max_vertex_attribs_; ++ii) { | |
| 813 if (vertex_attrib_infos_[ii].buffer() == buffer_id) { | |
| 814 vertex_attrib_infos_[ii].Clear(); | |
| 815 } | |
| 816 } | |
| 817 buffer_infos_.erase(buffer_id); | |
| 818 } | |
| 819 | |
| 539 bool GLES2DecoderImpl::InitPlatformSpecific() { | 820 bool GLES2DecoderImpl::InitPlatformSpecific() { |
| 540 #if defined(OS_WIN) | 821 #if defined(OS_WIN) |
| 541 device_context_ = ::GetDC(hwnd()); | 822 device_context_ = ::GetDC(hwnd()); |
| 542 | 823 |
| 543 int pixel_format; | 824 int pixel_format; |
| 544 | 825 |
| 545 if (!GetWindowsPixelFormat(hwnd(), | 826 if (!GetWindowsPixelFormat(hwnd(), |
| 546 anti_aliased_, | 827 anti_aliased_, |
| 547 &pixel_format)) { | 828 &pixel_format)) { |
| 548 DLOG(ERROR) << "Unable to determine optimal pixel format for GL context."; | 829 DLOG(ERROR) << "Unable to determine optimal pixel format for GL context."; |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 671 case name::kCmdId: \ | 952 case name::kCmdId: \ |
| 672 result = Handle ## name( \ | 953 result = Handle ## name( \ |
| 673 immediate_data_size, \ | 954 immediate_data_size, \ |
| 674 *static_cast<const name*>(cmd_data)); \ | 955 *static_cast<const name*>(cmd_data)); \ |
| 675 break; \ | 956 break; \ |
| 676 | 957 |
| 677 GLES2_COMMAND_LIST(GLES2_CMD_OP) | 958 GLES2_COMMAND_LIST(GLES2_CMD_OP) |
| 678 #undef GLES2_CMD_OP | 959 #undef GLES2_CMD_OP |
| 679 } | 960 } |
| 680 if (debug()) { | 961 if (debug()) { |
| 681 if (glGetError() != 0) { | 962 GLenum error; |
| 963 while ((error = glGetError()) != GL_NO_ERROR) { | |
| 682 // TODO(gman): Change output to something useful for NaCl. | 964 // TODO(gman): Change output to something useful for NaCl. |
| 965 SetGLError(error); | |
| 683 printf("GL ERROR b4: %s\n", GetCommandName(command)); | 966 printf("GL ERROR b4: %s\n", GetCommandName(command)); |
| 684 } | 967 } |
| 685 } | 968 } |
| 686 } else { | 969 } else { |
| 687 result = parse_error::kParseInvalidArguments; | 970 result = parse_error::kParseInvalidArguments; |
| 688 } | 971 } |
| 689 } else { | 972 } else { |
| 690 result = DoCommonCommand(command, arg_count, cmd_data); | 973 result = DoCommonCommand(command, arg_count, cmd_data); |
| 691 } | 974 } |
| 692 return result; | 975 return result; |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 716 case GL_ELEMENT_ARRAY_BUFFER: | 999 case GL_ELEMENT_ARRAY_BUFFER: |
| 717 bound_element_array_buffer_ = buffer; | 1000 bound_element_array_buffer_ = buffer; |
| 718 break; | 1001 break; |
| 719 default: | 1002 default: |
| 720 DCHECK(false); // Validation should prevent us getting here. | 1003 DCHECK(false); // Validation should prevent us getting here. |
| 721 break; | 1004 break; |
| 722 } | 1005 } |
| 723 glBindBuffer(target, buffer); | 1006 glBindBuffer(target, buffer); |
| 724 } | 1007 } |
| 725 | 1008 |
| 1009 void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) { | |
| 1010 if (index < max_vertex_attribs_) { | |
| 1011 vertex_attrib_infos_[index].set_enabled(false); | |
| 1012 glEnableVertexAttribArray(index); | |
| 1013 } else { | |
| 1014 SetGLError(GL_INVALID_VALUE); | |
| 1015 } | |
| 1016 } | |
| 1017 | |
| 1018 void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) { | |
| 1019 if (index < max_vertex_attribs_) { | |
| 1020 vertex_attrib_infos_[index].set_enabled(true); | |
| 1021 glEnableVertexAttribArray(index); | |
| 1022 } else { | |
| 1023 SetGLError(GL_INVALID_VALUE); | |
| 1024 } | |
| 1025 } | |
| 1026 | |
| 726 parse_error::ParseError GLES2DecoderImpl::HandleDeleteShader( | 1027 parse_error::ParseError GLES2DecoderImpl::HandleDeleteShader( |
| 727 uint32 immediate_data_size, const gles2::DeleteShader& c) { | 1028 uint32 immediate_data_size, const gles2::DeleteShader& c) { |
| 728 GLuint shader = c.shader; | 1029 GLuint shader = c.shader; |
| 729 GLuint service_id; | 1030 GLuint service_id; |
| 730 if (!id_map_.GetServiceId(shader, &service_id)) { | 1031 if (!id_map_.GetServiceId(shader, &service_id)) { |
| 731 SetGLError(GL_INVALID_VALUE); | 1032 SetGLError(GL_INVALID_VALUE); |
| 732 return parse_error::kParseNoError; | 1033 return parse_error::kParseNoError; |
| 733 } | 1034 } |
| 734 glDeleteProgram(service_id); | 1035 glDeleteShader(service_id); |
| 735 id_map_.RemoveMapping(shader, service_id); | 1036 id_map_.RemoveMapping(shader, service_id); |
| 736 return parse_error::kParseNoError; | 1037 return parse_error::kParseNoError; |
| 737 } | 1038 } |
| 738 | 1039 |
| 739 parse_error::ParseError GLES2DecoderImpl::HandleDeleteProgram( | 1040 parse_error::ParseError GLES2DecoderImpl::HandleDeleteProgram( |
| 740 uint32 immediate_data_size, const gles2::DeleteProgram& c) { | 1041 uint32 immediate_data_size, const gles2::DeleteProgram& c) { |
| 741 GLuint program = c.program; | 1042 GLuint program = c.program; |
| 742 GLuint service_id; | 1043 GLuint service_id; |
| 743 if (!id_map_.GetServiceId(program, &service_id)) { | 1044 if (!id_map_.GetServiceId(program, &service_id)) { |
| 744 SetGLError(GL_INVALID_VALUE); | 1045 SetGLError(GL_INVALID_VALUE); |
| 745 return parse_error::kParseNoError; | 1046 return parse_error::kParseNoError; |
| 746 } | 1047 } |
| 1048 RemoveProgramInfo(program); | |
| 747 glDeleteProgram(service_id); | 1049 glDeleteProgram(service_id); |
| 748 id_map_.RemoveMapping(program, service_id); | 1050 id_map_.RemoveMapping(program, service_id); |
| 749 return parse_error::kParseNoError; | 1051 return parse_error::kParseNoError; |
| 750 } | 1052 } |
| 751 | 1053 |
| 1054 void GLES2DecoderImpl::DoDrawArrays( | |
| 1055 GLenum mode, GLint first, GLsizei count) { | |
| 1056 if (IsDrawValid(first + count - 1)) { | |
| 1057 glDrawArrays(mode, first, count); | |
| 1058 } | |
| 1059 } | |
| 1060 | |
| 1061 void GLES2DecoderImpl::DoLinkProgram(GLuint program) { | |
| 1062 CopyRealGLErrorsToWrapper(); | |
| 1063 glLinkProgram(program); | |
| 1064 GLenum error = glGetError(); | |
| 1065 if (error != GL_NO_ERROR) { | |
| 1066 RemoveProgramInfo(program); | |
| 1067 SetGLError(error); | |
| 1068 } else { | |
| 1069 UpdateProgramInfo(program); | |
| 1070 } | |
| 1071 }; | |
| 1072 | |
| 752 // NOTE: If you need to know the results of SwapBuffers (like losing | 1073 // NOTE: If you need to know the results of SwapBuffers (like losing |
| 753 // the context) then add a new command. Do NOT make SwapBuffers synchronous. | 1074 // the context) then add a new command. Do NOT make SwapBuffers synchronous. |
| 754 void GLES2DecoderImpl::DoSwapBuffers() { | 1075 void GLES2DecoderImpl::DoSwapBuffers() { |
| 755 #ifdef OS_WIN | 1076 #ifdef OS_WIN |
| 756 ::SwapBuffers(device_context_); | 1077 ::SwapBuffers(device_context_); |
| 757 #endif | 1078 #endif |
| 758 | 1079 |
| 759 #ifdef OS_LINUX | 1080 #ifdef OS_LINUX |
| 760 DCHECK(window()); | 1081 DCHECK(window()); |
| 761 window()->SwapBuffers(); | 1082 window()->SwapBuffers(); |
| 762 #endif | 1083 #endif |
| 763 } | 1084 } |
| 764 | 1085 |
| 1086 void GLES2DecoderImpl::DoUseProgram(GLuint program) { | |
| 1087 ProgramInfo* info = GetProgramInfo(program); | |
| 1088 if (!info) { | |
| 1089 // Program was not linked successfully. (ie, glLinkProgram) | |
| 1090 SetGLError(GL_INVALID_OPERATION); | |
| 1091 } else { | |
| 1092 current_program_info_ = info; | |
| 1093 glUseProgram(program); | |
| 1094 } | |
| 1095 } | |
| 1096 | |
| 765 GLenum GLES2DecoderImpl::GetGLError() { | 1097 GLenum GLES2DecoderImpl::GetGLError() { |
| 766 // Check the GL error first, then our wrapped error. | 1098 // Check the GL error first, then our wrapped error. |
| 767 GLenum error = glGetError(); | 1099 GLenum error = glGetError(); |
| 768 if (error == GL_NO_ERROR && error_bits_ != 0) { | 1100 if (error == GL_NO_ERROR && error_bits_ != 0) { |
| 769 uint32 mask = 1; | 1101 uint32 mask = 1; |
| 770 while (mask) { | 1102 while (mask) { |
| 771 if ((error_bits_ & mask) != 0) { | 1103 if ((error_bits_ & mask) != 0) { |
| 772 error = GLErrorBitToGLError(mask); | 1104 error = GLErrorBitToGLError(mask); |
| 773 break; | 1105 break; |
| 774 } | 1106 } |
| 775 } | 1107 } |
| 776 } | 1108 } |
| 777 | 1109 |
| 778 if (error != GL_NO_ERROR) { | 1110 if (error != GL_NO_ERROR) { |
| 779 // There was an error, clear the corresponding wrapped error. | 1111 // There was an error, clear the corresponding wrapped error. |
| 780 error_bits_ &= ~GLErrorToErrorBit(error); | 1112 error_bits_ &= ~GLErrorToErrorBit(error); |
| 781 } | 1113 } |
| 782 return error; | 1114 return error; |
| 783 } | 1115 } |
| 784 | 1116 |
| 785 void GLES2DecoderImpl::SetGLError(GLenum error) { | 1117 void GLES2DecoderImpl::SetGLError(GLenum error) { |
| 786 error_bits_ |= GLErrorToErrorBit(error); | 1118 error_bits_ |= GLErrorToErrorBit(error); |
| 787 } | 1119 } |
| 788 | 1120 |
| 1121 void GLES2DecoderImpl::CopyRealGLErrorsToWrapper() { | |
| 1122 GLenum error; | |
| 1123 while ((error = glGetError()) != GL_NO_ERROR) { | |
| 1124 SetGLError(error); | |
| 1125 } | |
| 1126 } | |
| 1127 | |
| 1128 const GLES2DecoderImpl::BufferInfo* GLES2DecoderImpl::GetBufferInfo( | |
| 1129 GLuint buffer) { | |
| 1130 BufferInfoMap::iterator it = buffer_infos_.find(buffer); | |
| 1131 return it != buffer_infos_.end() ? &it->second : NULL; | |
| 1132 } | |
| 1133 | |
| 1134 void GLES2DecoderImpl::SetBufferInfo(GLuint buffer, GLsizeiptr size) { | |
| 1135 buffer_infos_[buffer] = BufferInfo(size); | |
| 1136 | |
| 1137 // Also go through VertexAttribInfo and update any info that references | |
| 1138 // the same buffer. | |
| 1139 for (GLuint ii = 0; ii < max_vertex_attribs_; ++ii) { | |
| 1140 if (vertex_attrib_infos_[ii].buffer() == buffer) { | |
| 1141 vertex_attrib_infos_[ii].SetBufferSize(size); | |
| 1142 } | |
| 1143 } | |
| 1144 } | |
| 1145 | |
| 1146 GLES2DecoderImpl::ProgramInfo* GLES2DecoderImpl::GetProgramInfo( | |
| 1147 GLuint program) { | |
| 1148 ProgramInfoMap::iterator it = program_infos_.find(program); | |
| 1149 return it != program_infos_.end() ? &it->second : NULL; | |
| 1150 } | |
| 1151 | |
| 1152 void GLES2DecoderImpl::UpdateProgramInfo(GLuint program) { | |
| 1153 ProgramInfo* info = GetProgramInfo(program); | |
| 1154 if (!info) { | |
| 1155 std::pair<ProgramInfoMap::iterator, bool> result = | |
| 1156 program_infos_.insert(std::make_pair(program, ProgramInfo())); | |
| 1157 DCHECK(result.second); | |
| 1158 info = &result.first->second; | |
| 1159 } | |
| 1160 GLint num_attribs = 0; | |
| 1161 GLint max_len = 0; | |
| 1162 glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &num_attribs); | |
| 1163 info->SetNumAttributes(num_attribs); | |
| 1164 glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_len); | |
| 1165 // TODO(gman): Should we check for error? | |
| 1166 scoped_array<char> name_buffer(new char[max_len + 1]); | |
| 1167 for (GLint ii = 0; ii < num_attribs; ++ii) { | |
| 1168 GLsizei length; | |
| 1169 GLsizei size; | |
| 1170 GLenum type; | |
| 1171 glGetActiveAttrib( | |
| 1172 program, ii, max_len + 1, &length, &size, &type, name_buffer.get()); | |
| 1173 // TODO(gman): Should we check for error? | |
| 1174 GLint location = glGetAttribLocation(program, name_buffer.get()); | |
| 1175 info->SetAttributeLocation(ii, num_attribs); | |
| 1176 } | |
| 1177 } | |
| 1178 | |
| 1179 void GLES2DecoderImpl::RemoveProgramInfo(GLuint program) { | |
| 1180 ProgramInfoMap::iterator it = program_infos_.find(program); | |
| 1181 if (it != program_infos_.end()) { | |
| 1182 if (current_program_info_ == &it->second) { | |
| 1183 current_program_info_ = NULL; | |
| 1184 } | |
| 1185 program_infos_.erase(it); | |
| 1186 } | |
| 1187 } | |
| 1188 | |
| 1189 bool GLES2DecoderImpl::VertexAttribInfo::CanAccess(GLuint index) { | |
| 1190 return !enabled_ || (buffer_ != 0 && index < num_elements_); | |
| 1191 } | |
| 1192 | |
| 1193 bool GLES2DecoderImpl::IsDrawValid(GLuint max_vertex_accessed) { | |
| 1194 if (current_program_info_) { | |
| 1195 // Validate that all attribs current program needs are setup correctly. | |
| 1196 const ProgramInfo::AttribLocationVector& locations = | |
| 1197 current_program_info_->GetAttribLocations(); | |
| 1198 for (size_t ii = 0; ii < locations.size(); ++ii) { | |
| 1199 GLuint location = locations[ii]; | |
| 1200 DCHECK_LT(location, max_vertex_attribs_); | |
| 1201 if (!vertex_attrib_infos_[location].CanAccess(max_vertex_accessed)) { | |
| 1202 SetGLError(GL_INVALID_OPERATION); | |
| 1203 } | |
| 1204 } | |
| 1205 return true; | |
| 1206 } | |
| 1207 // We do not set a GL error here because the GL spec says no error if the | |
| 1208 // program is invalid. | |
| 1209 return false; | |
| 1210 }; | |
| 1211 | |
| 789 parse_error::ParseError GLES2DecoderImpl::HandleDrawElements( | 1212 parse_error::ParseError GLES2DecoderImpl::HandleDrawElements( |
| 790 uint32 immediate_data_size, const gles2::DrawElements& c) { | 1213 uint32 immediate_data_size, const gles2::DrawElements& c) { |
| 791 if (bound_element_array_buffer_ != 0) { | 1214 if (bound_element_array_buffer_ != 0) { |
| 792 GLenum mode = c.mode; | 1215 GLenum mode = c.mode; |
| 793 GLsizei count = c.count; | 1216 GLsizei count = c.count; |
| 794 GLenum type = c.type; | 1217 GLenum type = c.type; |
| 795 if (!ValidateGLenumDrawMode(mode) || | 1218 if (!ValidateGLenumDrawMode(mode) || |
| 796 !ValidateGLenumIndexType(type)) { | 1219 !ValidateGLenumIndexType(type)) { |
| 797 SetGLError(GL_INVALID_VALUE); | 1220 SetGLError(GL_INVALID_VALUE); |
| 798 } else { | 1221 } else { |
| 799 const GLvoid* indices = reinterpret_cast<const GLvoid*>(c.index_offset); | 1222 const GLvoid* indices = reinterpret_cast<const GLvoid*>(c.index_offset); |
| 800 // TODO(gman): Validate indices | 1223 // TODO(gman): Validate indices. Get maximum index. |
| 801 // TOOD(gman): Validate all attribs current program needs are setup. | 1224 // |
| 802 glDrawElements(mode, count, type, indices); | 1225 // This value should be computed by walking the index buffer from 0 to |
| 1226 // count and finding the maximum vertex accessed. | |
| 1227 // For now we'll special case 0 to not check. | |
| 1228 GLuint max_vertex_accessed = 0; | |
| 1229 if (IsDrawValid(max_vertex_accessed)) { | |
| 1230 glDrawElements(mode, count, type, indices); | |
| 1231 } | |
| 803 } | 1232 } |
| 804 } else { | 1233 } else { |
| 805 SetGLError(GL_INVALID_VALUE); | 1234 SetGLError(GL_INVALID_VALUE); |
| 806 } | 1235 } |
| 807 return parse_error::kParseNoError; | 1236 return parse_error::kParseNoError; |
| 808 } | 1237 } |
| 809 | 1238 |
| 810 namespace { | 1239 namespace { |
| 811 | 1240 |
| 812 // Calls glShaderSource for the various versions of the ShaderSource command. | 1241 // Calls glShaderSource for the various versions of the ShaderSource command. |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 858 | 1287 |
| 859 parse_error::ParseError GLES2DecoderImpl::HandleShaderSourceImmediate( | 1288 parse_error::ParseError GLES2DecoderImpl::HandleShaderSourceImmediate( |
| 860 uint32 immediate_data_size, const gles2::ShaderSourceImmediate& c) { | 1289 uint32 immediate_data_size, const gles2::ShaderSourceImmediate& c) { |
| 861 GLuint shader; | 1290 GLuint shader; |
| 862 if (!id_map_.GetServiceId(c.shader, &shader)) { | 1291 if (!id_map_.GetServiceId(c.shader, &shader)) { |
| 863 SetGLError(GL_INVALID_VALUE); | 1292 SetGLError(GL_INVALID_VALUE); |
| 864 return parse_error::kParseNoError; | 1293 return parse_error::kParseNoError; |
| 865 } | 1294 } |
| 866 GLsizei count = c.count; | 1295 GLsizei count = c.count; |
| 867 uint32 data_size = c.data_size; | 1296 uint32 data_size = c.data_size; |
| 868 // TODO(gman): need to check that data_size is in range for arg_count. | 1297 const char** data = GetImmediateDataAs<const char**>( |
| 869 const char** data = GetImmediateDataAs<const char**>(c); | 1298 c, data_size, immediate_data_size); |
| 870 if (!data) { | 1299 if (!data) { |
| 871 return parse_error::kParseOutOfBounds; | 1300 return parse_error::kParseOutOfBounds; |
| 872 } | 1301 } |
| 873 return ShaderSourceHelper( | 1302 return ShaderSourceHelper( |
| 874 shader, count, reinterpret_cast<const char*>(data), data_size); | 1303 shader, count, reinterpret_cast<const char*>(data), data_size); |
| 875 } | 1304 } |
| 876 | 1305 |
| 877 parse_error::ParseError GLES2DecoderImpl::HandleVertexAttribPointer( | 1306 parse_error::ParseError GLES2DecoderImpl::HandleVertexAttribPointer( |
| 878 uint32 immediate_data_size, const gles2::VertexAttribPointer& c) { | 1307 uint32 immediate_data_size, const gles2::VertexAttribPointer& c) { |
| 879 // TODO(gman): Is this a valid check or does this check have to come | |
| 880 // at glDrawElements time. | |
| 881 if (bound_array_buffer_ != 0) { | 1308 if (bound_array_buffer_ != 0) { |
| 882 GLuint indx = c.indx; | 1309 GLuint indx = c.indx; |
| 883 GLint size = c.size; | 1310 GLint size = c.size; |
| 884 GLenum type = c.type; | 1311 GLenum type = c.type; |
| 885 GLboolean normalized = c.normalized; | 1312 GLboolean normalized = c.normalized; |
| 886 GLsizei stride = c.stride; | 1313 GLsizei stride = c.stride; |
| 887 GLuint offset = c.offset; | 1314 GLsizei offset = c.offset; |
| 888 const void* ptr = reinterpret_cast<const void*>(c.offset); | 1315 const void* ptr = reinterpret_cast<const void*>(offset); |
| 889 if (!ValidateGLenumVertexAttribType(type) || | 1316 if (!ValidateGLenumVertexAttribType(type) || |
| 890 !ValidateGLenumVertexAttribSize(size)) { | 1317 !ValidateGLenumVertexAttribSize(size) || |
| 1318 indx >= max_vertex_attribs_ || | |
| 1319 stride < 0) { | |
| 891 SetGLError(GL_INVALID_VALUE); | 1320 SetGLError(GL_INVALID_VALUE); |
| 892 return parse_error::kParseNoError; | 1321 return parse_error::kParseNoError; |
| 893 } | 1322 } |
| 1323 const BufferInfo* buffer_info = GetBufferInfo(bound_array_buffer_); | |
| 1324 GLsizei component_size = GetGLTypeSize(type); | |
| 1325 GLsizei real_stride = stride != 0 ? stride : component_size * size; | |
| 1326 if (offset % component_size > 0) { | |
| 1327 SetGLError(GL_INVALID_VALUE); | |
| 1328 return parse_error::kParseNoError; | |
| 1329 } | |
| 1330 vertex_attrib_infos_[indx].SetInfo( | |
| 1331 bound_array_buffer_, | |
| 1332 buffer_info ? buffer_info->size : 0, | |
| 1333 size, | |
| 1334 type, | |
| 1335 real_stride, | |
| 1336 offset); | |
| 894 glVertexAttribPointer(indx, size, type, normalized, stride, ptr); | 1337 glVertexAttribPointer(indx, size, type, normalized, stride, ptr); |
| 895 } else { | 1338 } else { |
| 896 SetGLError(GL_INVALID_VALUE); | 1339 SetGLError(GL_INVALID_VALUE); |
| 897 } | 1340 } |
| 898 return parse_error::kParseNoError; | 1341 return parse_error::kParseNoError; |
| 899 } | 1342 } |
| 900 | 1343 |
| 901 parse_error::ParseError GLES2DecoderImpl::HandleReadPixels( | 1344 parse_error::ParseError GLES2DecoderImpl::HandleReadPixels( |
| 902 uint32 immediate_data_size, const gles2::ReadPixels& c) { | 1345 uint32 immediate_data_size, const gles2::ReadPixels& c) { |
| 903 GLint x = c.x; | 1346 GLint x = c.x; |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 968 } | 1411 } |
| 969 | 1412 |
| 970 parse_error::ParseError GLES2DecoderImpl::HandleGetAttribLocationImmediate( | 1413 parse_error::ParseError GLES2DecoderImpl::HandleGetAttribLocationImmediate( |
| 971 uint32 immediate_data_size, const gles2::GetAttribLocationImmediate& c) { | 1414 uint32 immediate_data_size, const gles2::GetAttribLocationImmediate& c) { |
| 972 GLuint program; | 1415 GLuint program; |
| 973 if (!id_map_.GetServiceId(c.program, &program)) { | 1416 if (!id_map_.GetServiceId(c.program, &program)) { |
| 974 SetGLError(GL_INVALID_VALUE); | 1417 SetGLError(GL_INVALID_VALUE); |
| 975 return parse_error::kParseNoError; | 1418 return parse_error::kParseNoError; |
| 976 } | 1419 } |
| 977 uint32 name_size = c.data_size; | 1420 uint32 name_size = c.data_size; |
| 978 const char* name = GetImmediateDataAs<const char*>(c); | 1421 const char* name = GetImmediateDataAs<const char*>( |
| 979 // TODO(gman): Make sure validate checks arg_count | 1422 c, name_size, immediate_data_size); |
| 980 // covers data_size. | |
| 981 GLint* location = GetSharedMemoryAs<GLint*>( | 1423 GLint* location = GetSharedMemoryAs<GLint*>( |
| 982 c.location_shm_id, c.location_shm_offset, sizeof(GLint)); | 1424 c.location_shm_id, c.location_shm_offset, sizeof(GLint)); |
| 983 if (!location || !name) { | 1425 if (!location || !name) { |
| 984 return parse_error::kParseOutOfBounds; | 1426 return parse_error::kParseOutOfBounds; |
| 985 } | 1427 } |
| 986 String name_str(name, name_size); | 1428 String name_str(name, name_size); |
| 987 *location = glGetAttribLocation(program, name_str.c_str()); | 1429 *location = glGetAttribLocation(program, name_str.c_str()); |
| 988 return parse_error::kParseNoError; | 1430 return parse_error::kParseNoError; |
| 989 } | 1431 } |
| 990 | 1432 |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 1009 } | 1451 } |
| 1010 | 1452 |
| 1011 parse_error::ParseError GLES2DecoderImpl::HandleGetUniformLocationImmediate( | 1453 parse_error::ParseError GLES2DecoderImpl::HandleGetUniformLocationImmediate( |
| 1012 uint32 immediate_data_size, const gles2::GetUniformLocationImmediate& c) { | 1454 uint32 immediate_data_size, const gles2::GetUniformLocationImmediate& c) { |
| 1013 GLuint program; | 1455 GLuint program; |
| 1014 if (!id_map_.GetServiceId(c.program, &program)) { | 1456 if (!id_map_.GetServiceId(c.program, &program)) { |
| 1015 SetGLError(GL_INVALID_VALUE); | 1457 SetGLError(GL_INVALID_VALUE); |
| 1016 return parse_error::kParseNoError; | 1458 return parse_error::kParseNoError; |
| 1017 } | 1459 } |
| 1018 uint32 name_size = c.data_size; | 1460 uint32 name_size = c.data_size; |
| 1019 const char* name = GetImmediateDataAs<const char*>(c); | 1461 const char* name = GetImmediateDataAs<const char*>( |
| 1020 // TODO(gman): Make sure validate checks arg_count | 1462 c, name_size, immediate_data_size); |
| 1021 // covers data_size. | |
| 1022 GLint* location = GetSharedMemoryAs<GLint*>( | 1463 GLint* location = GetSharedMemoryAs<GLint*>( |
| 1023 c.location_shm_id, c.location_shm_offset, sizeof(GLint)); | 1464 c.location_shm_id, c.location_shm_offset, sizeof(GLint)); |
| 1024 if (!location || !name) { | 1465 if (!location || !name) { |
| 1025 return parse_error::kParseOutOfBounds; | 1466 return parse_error::kParseOutOfBounds; |
| 1026 } | 1467 } |
| 1027 String name_str(name, name_size); | 1468 String name_str(name, name_size); |
| 1028 *location = glGetUniformLocation(program, name_str.c_str()); | 1469 *location = glGetUniformLocation(program, name_str.c_str()); |
| 1029 return parse_error::kParseNoError; | 1470 return parse_error::kParseNoError; |
| 1030 } | 1471 } |
| 1031 | 1472 |
| 1032 parse_error::ParseError GLES2DecoderImpl::HandleBufferData( | 1473 parse_error::ParseError GLES2DecoderImpl::HandleBufferData( |
| 1033 uint32 immediate_data_size, const gles2::BufferData& c) { | 1474 uint32 immediate_data_size, const gles2::BufferData& c) { |
| 1034 GLenum target = static_cast<GLenum>(c.target); | 1475 GLenum target = static_cast<GLenum>(c.target); |
| 1035 GLsizeiptr size = static_cast<GLsizeiptr>(c.size); | 1476 GLsizeiptr size = static_cast<GLsizeiptr>(c.size); |
| 1036 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id); | 1477 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id); |
| 1037 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset); | 1478 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset); |
| 1038 GLenum usage = static_cast<GLenum>(c.usage); | 1479 GLenum usage = static_cast<GLenum>(c.usage); |
| 1039 const void* data = NULL; | 1480 const void* data = NULL; |
| 1040 if (data_shm_id != 0 || data_shm_offset != 0) { | 1481 if (data_shm_id != 0 || data_shm_offset != 0) { |
| 1041 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size); | 1482 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size); |
| 1042 if (!data) { | 1483 if (!data) { |
| 1043 return parse_error::kParseOutOfBounds; | 1484 return parse_error::kParseOutOfBounds; |
| 1044 } | 1485 } |
| 1045 } | 1486 } |
| 1046 // TODO(gman): Validate case where data is NULL. | |
| 1047 if (!ValidateGLenumBufferTarget(target) || | 1487 if (!ValidateGLenumBufferTarget(target) || |
| 1048 !ValidateGLenumBufferUsage(usage)) { | 1488 !ValidateGLenumBufferUsage(usage)) { |
| 1049 SetGLError(GL_INVALID_VALUE); | 1489 SetGLError(GL_INVALID_VALUE); |
| 1050 return parse_error::kParseNoError; | 1490 return parse_error::kParseNoError; |
| 1051 } | 1491 } |
| 1492 // Clear the buffer to 0 if no initial data was passed in. | |
| 1493 scoped_array<int8> zero; | |
| 1494 if (!data) { | |
| 1495 zero.reset(new int8[size]); | |
| 1496 memset(zero.get(), 0, size); | |
| 1497 data = zero.get(); | |
| 1498 } | |
| 1499 CopyRealGLErrorsToWrapper(); | |
| 1052 glBufferData(target, size, data, usage); | 1500 glBufferData(target, size, data, usage); |
| 1501 GLenum error = glGetError(); | |
| 1502 if (error != GL_NO_ERROR) { | |
| 1503 SetGLError(error); | |
| 1504 } else { | |
| 1505 SetBufferInfo(GetBufferForTarget(target), size); | |
| 1506 } | |
| 1053 return parse_error::kParseNoError; | 1507 return parse_error::kParseNoError; |
| 1054 } | 1508 } |
| 1055 | 1509 |
| 1056 parse_error::ParseError GLES2DecoderImpl::HandleBufferDataImmediate( | 1510 parse_error::ParseError GLES2DecoderImpl::HandleBufferDataImmediate( |
| 1057 uint32 immediate_data_size, const gles2::BufferDataImmediate& c) { | 1511 uint32 immediate_data_size, const gles2::BufferDataImmediate& c) { |
| 1058 GLenum target = static_cast<GLenum>(c.target); | 1512 GLenum target = static_cast<GLenum>(c.target); |
| 1059 GLsizeiptr size = static_cast<GLsizeiptr>(c.size); | 1513 GLsizeiptr size = static_cast<GLsizeiptr>(c.size); |
| 1060 const void* data = GetImmediateDataAs<const void*>(c); | 1514 const void* data = GetImmediateDataAs<const void*>( |
| 1515 c, size, immediate_data_size); | |
| 1516 if (!data) { | |
| 1517 return parse_error::kParseOutOfBounds; | |
| 1518 } | |
| 1061 GLenum usage = static_cast<GLenum>(c.usage); | 1519 GLenum usage = static_cast<GLenum>(c.usage); |
| 1062 if (!ValidateGLenumBufferTarget(target) || | 1520 if (!ValidateGLenumBufferTarget(target) || |
| 1063 !ValidateGLenumBufferUsage(usage)) { | 1521 !ValidateGLenumBufferUsage(usage)) { |
| 1064 SetGLError(GL_INVALID_VALUE); | 1522 SetGLError(GL_INVALID_VALUE); |
| 1065 return parse_error::kParseNoError; | 1523 return parse_error::kParseNoError; |
| 1066 } | 1524 } |
| 1067 // TODO(gman): Handle case where data is NULL. | 1525 CopyRealGLErrorsToWrapper(); |
| 1068 glBufferData(target, size, data, usage); | 1526 glBufferData(target, size, data, usage); |
| 1527 GLenum error = glGetError(); | |
| 1528 if (error != GL_NO_ERROR) { | |
| 1529 SetGLError(error); | |
| 1530 } else { | |
| 1531 SetBufferInfo(GetBufferForTarget(target), size); | |
| 1532 } | |
| 1069 return parse_error::kParseNoError; | 1533 return parse_error::kParseNoError; |
| 1070 } | 1534 } |
| 1071 | 1535 |
| 1072 parse_error::ParseError GLES2DecoderImpl::HandleCompressedTexImage2D( | 1536 parse_error::ParseError GLES2DecoderImpl::HandleCompressedTexImage2D( |
| 1073 uint32 immediate_data_size, const gles2::CompressedTexImage2D& c) { | 1537 uint32 immediate_data_size, const gles2::CompressedTexImage2D& c) { |
| 1074 GLenum target = static_cast<GLenum>(c.target); | 1538 GLenum target = static_cast<GLenum>(c.target); |
| 1075 GLint level = static_cast<GLint>(c.level); | 1539 GLint level = static_cast<GLint>(c.level); |
| 1076 GLenum internal_format = static_cast<GLenum>(c.internalformat); | 1540 GLenum internal_format = static_cast<GLenum>(c.internalformat); |
| 1077 GLsizei width = static_cast<GLsizei>(c.width); | 1541 GLsizei width = static_cast<GLsizei>(c.width); |
| 1078 GLsizei height = static_cast<GLsizei>(c.height); | 1542 GLsizei height = static_cast<GLsizei>(c.height); |
| 1079 GLint border = static_cast<GLint>(c.border); | 1543 GLint border = static_cast<GLint>(c.border); |
| 1080 GLsizei image_size = static_cast<GLsizei>(c.imageSize); | 1544 GLsizei image_size = static_cast<GLsizei>(c.imageSize); |
| 1081 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id); | 1545 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id); |
| 1082 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset); | 1546 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset); |
| 1083 const void* data = NULL; | 1547 const void* data = NULL; |
| 1084 if (data_shm_id != 0 || data_shm_offset != 0) { | 1548 if (data_shm_id != 0 || data_shm_offset != 0) { |
| 1085 data = GetSharedMemoryAs<const void*>( | 1549 data = GetSharedMemoryAs<const void*>( |
| 1086 data_shm_id, data_shm_offset, image_size); | 1550 data_shm_id, data_shm_offset, image_size); |
| 1087 if (!data) { | 1551 if (!data) { |
| 1088 return parse_error::kParseOutOfBounds; | 1552 return parse_error::kParseOutOfBounds; |
| 1089 } | 1553 } |
| 1090 } | 1554 } |
| 1091 // TODO(gman): Validate internal_format | 1555 // TODO(gman): Validate internal_format |
| 1092 if (!ValidateGLenumTextureTarget(target)) { | 1556 if (!ValidateGLenumTextureTarget(target)) { |
| 1093 SetGLError(GL_INVALID_VALUE); | 1557 SetGLError(GL_INVALID_VALUE); |
| 1094 return parse_error::kParseNoError; | 1558 return parse_error::kParseNoError; |
| 1095 } | 1559 } |
| 1096 // TODO(gman): Validate case where data is NULL. | 1560 scoped_array<int8> zero; |
| 1561 if (!data) { | |
| 1562 zero.reset(new int8[image_size]); | |
| 1563 memset(zero.get(), 0, image_size); | |
| 1564 data = zero.get(); | |
| 1565 } | |
| 1097 glCompressedTexImage2D( | 1566 glCompressedTexImage2D( |
| 1098 target, level, internal_format, width, height, border, image_size, data); | 1567 target, level, internal_format, width, height, border, image_size, data); |
| 1099 return parse_error::kParseNoError; | 1568 return parse_error::kParseNoError; |
| 1100 } | 1569 } |
| 1101 | 1570 |
| 1102 parse_error::ParseError GLES2DecoderImpl::HandleCompressedTexImage2DImmediate( | 1571 parse_error::ParseError GLES2DecoderImpl::HandleCompressedTexImage2DImmediate( |
| 1103 uint32 immediate_data_size, const gles2::CompressedTexImage2DImmediate& c) { | 1572 uint32 immediate_data_size, const gles2::CompressedTexImage2DImmediate& c) { |
| 1104 GLenum target = static_cast<GLenum>(c.target); | 1573 GLenum target = static_cast<GLenum>(c.target); |
| 1105 GLint level = static_cast<GLint>(c.level); | 1574 GLint level = static_cast<GLint>(c.level); |
| 1106 GLenum internal_format = static_cast<GLenum>(c.internalformat); | 1575 GLenum internal_format = static_cast<GLenum>(c.internalformat); |
| 1107 GLsizei width = static_cast<GLsizei>(c.width); | 1576 GLsizei width = static_cast<GLsizei>(c.width); |
| 1108 GLsizei height = static_cast<GLsizei>(c.height); | 1577 GLsizei height = static_cast<GLsizei>(c.height); |
| 1109 GLint border = static_cast<GLint>(c.border); | 1578 GLint border = static_cast<GLint>(c.border); |
| 1110 GLsizei image_size = static_cast<GLsizei>(c.imageSize); | 1579 GLsizei image_size = static_cast<GLsizei>(c.imageSize); |
| 1111 const void* data = GetImmediateDataAs<const void*>(c); | 1580 const void* data = GetImmediateDataAs<const void*>( |
| 1112 // Immediate version. | 1581 c, image_size, immediate_data_size); |
| 1113 // TODO(gman): Handle case where data is NULL. | |
| 1114 if (!data) { | 1582 if (!data) { |
| 1115 return parse_error::kParseOutOfBounds; | 1583 return parse_error::kParseOutOfBounds; |
| 1116 } | 1584 } |
| 1117 // TODO(gman): Validate internal_format | 1585 // TODO(gman): Validate internal_format |
| 1118 if (!ValidateGLenumTextureTarget(target)) { | 1586 if (!ValidateGLenumTextureTarget(target)) { |
| 1119 SetGLError(GL_INVALID_VALUE); | 1587 SetGLError(GL_INVALID_VALUE); |
| 1120 return parse_error::kParseNoError; | 1588 return parse_error::kParseNoError; |
| 1121 } | 1589 } |
| 1122 glCompressedTexImage2D( | 1590 glCompressedTexImage2D( |
| 1123 target, level, internal_format, width, height, border, image_size, data); | 1591 target, level, internal_format, width, height, border, image_size, data); |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 1146 return parse_error::kParseOutOfBounds; | 1614 return parse_error::kParseOutOfBounds; |
| 1147 } | 1615 } |
| 1148 } | 1616 } |
| 1149 if (!ValidateGLenumTextureTarget(target) || | 1617 if (!ValidateGLenumTextureTarget(target) || |
| 1150 !ValidateGLenumTextureFormat(internal_format) || | 1618 !ValidateGLenumTextureFormat(internal_format) || |
| 1151 !ValidateGLenumTextureFormat(format) || | 1619 !ValidateGLenumTextureFormat(format) || |
| 1152 !ValidateGLenumPixelType(type)) { | 1620 !ValidateGLenumPixelType(type)) { |
| 1153 SetGLError(GL_INVALID_VALUE); | 1621 SetGLError(GL_INVALID_VALUE); |
| 1154 return parse_error::kParseNoError; | 1622 return parse_error::kParseNoError; |
| 1155 } | 1623 } |
| 1156 // TODO(gman): Validate case where data is NULL. | 1624 scoped_array<int8> zero; |
| 1625 if (!pixels) { | |
| 1626 zero.reset(new int8[pixels_size]); | |
| 1627 memset(zero.get(), 0, pixels_size); | |
| 1628 pixels = zero.get(); | |
| 1629 } | |
| 1157 glTexImage2D( | 1630 glTexImage2D( |
| 1158 target, level, internal_format, width, height, border, format, type, | 1631 target, level, internal_format, width, height, border, format, type, |
| 1159 pixels); | 1632 pixels); |
| 1160 return parse_error::kParseNoError; | 1633 return parse_error::kParseNoError; |
| 1161 } | 1634 } |
| 1162 | 1635 |
| 1163 parse_error::ParseError GLES2DecoderImpl::HandleTexImage2DImmediate( | 1636 parse_error::ParseError GLES2DecoderImpl::HandleTexImage2DImmediate( |
| 1164 uint32 immediate_data_size, const gles2::TexImage2DImmediate& c) { | 1637 uint32 immediate_data_size, const gles2::TexImage2DImmediate& c) { |
| 1165 GLenum target = static_cast<GLenum>(c.target); | 1638 GLenum target = static_cast<GLenum>(c.target); |
| 1166 GLint level = static_cast<GLint>(c.level); | 1639 GLint level = static_cast<GLint>(c.level); |
| 1167 GLint internal_format = static_cast<GLint>(c.internalformat); | 1640 GLint internal_format = static_cast<GLint>(c.internalformat); |
| 1168 GLsizei width = static_cast<GLsizei>(c.width); | 1641 GLsizei width = static_cast<GLsizei>(c.width); |
| 1169 GLsizei height = static_cast<GLsizei>(c.height); | 1642 GLsizei height = static_cast<GLsizei>(c.height); |
| 1170 GLint border = static_cast<GLint>(c.border); | 1643 GLint border = static_cast<GLint>(c.border); |
| 1171 GLenum format = static_cast<GLenum>(c.format); | 1644 GLenum format = static_cast<GLenum>(c.format); |
| 1172 GLenum type = static_cast<GLenum>(c.type); | 1645 GLenum type = static_cast<GLenum>(c.type); |
| 1173 const void* pixels = GetImmediateDataAs<const void*>(c); | 1646 uint32 size = GLES2Util::ComputeImageDataSize( |
| 1174 // Immediate version. | 1647 width, height, format, type, unpack_alignment_); |
| 1175 // TODO(gman): Handle case where data is NULL. | 1648 const void* pixels = GetImmediateDataAs<const void*>( |
| 1649 c, size, immediate_data_size); | |
| 1176 if (!pixels) { | 1650 if (!pixels) { |
| 1177 return parse_error::kParseOutOfBounds; | 1651 return parse_error::kParseOutOfBounds; |
| 1178 } | 1652 } |
| 1179 if (!ValidateGLenumTextureTarget(target) || | 1653 if (!ValidateGLenumTextureTarget(target) || |
| 1180 !ValidateGLenumTextureFormat(internal_format) || | 1654 !ValidateGLenumTextureFormat(internal_format) || |
| 1181 !ValidateGLenumTextureFormat(format) || | 1655 !ValidateGLenumTextureFormat(format) || |
| 1182 !ValidateGLenumPixelType(type)) { | 1656 !ValidateGLenumPixelType(type)) { |
| 1183 SetGLError(GL_INVALID_VALUE); | 1657 SetGLError(GL_INVALID_VALUE); |
| 1184 return parse_error::kParseNoError; | 1658 return parse_error::kParseNoError; |
| 1185 } | 1659 } |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1232 } | 1706 } |
| 1233 | 1707 |
| 1234 // Include the auto-generated part of this file. We split this because it means | 1708 // Include the auto-generated part of this file. We split this because it means |
| 1235 // we can easily edit the non-auto generated parts right here in this file | 1709 // we can easily edit the non-auto generated parts right here in this file |
| 1236 // instead of having to edit some template or the code generator. | 1710 // instead of having to edit some template or the code generator. |
| 1237 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h" | 1711 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h" |
| 1238 | 1712 |
| 1239 } // namespace gles2 | 1713 } // namespace gles2 |
| 1240 } // namespace gpu | 1714 } // namespace gpu |
| 1241 | 1715 |
| OLD | NEW |