blob: 034558002c0d3f67737a0fa1d680e818c09bce9c [file] [log] [blame]
[email protected]1bee3982009-12-17 23:15:281// Copyright (c) 2009 The Chromium Authors. All rights reserved.
[email protected]96449d2c2009-11-25 00:01:322// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]8a837bb2010-01-05 00:21:245#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
[email protected]96449d2c2009-11-25 00:01:326#include <vector>
7#include <string>
8#include <map>
9#include <build/build_config.h>
10#include "base/scoped_ptr.h"
11#define GLES2_GPU_SERVICE 1
12#include "gpu/command_buffer/common/gles2_cmd_format.h"
13#include "gpu/command_buffer/common/gles2_cmd_utils.h"
14#include "gpu/command_buffer/service/cmd_buffer_engine.h"
15#include "gpu/command_buffer/service/gl_utils.h"
[email protected]ba3176a2009-12-16 18:19:4616#include "gpu/command_buffer/service/gles2_cmd_validation.h"
[email protected]96449d2c2009-11-25 00:01:3217
[email protected]a7a27ace2009-12-12 00:11:2518namespace gpu {
[email protected]96449d2c2009-11-25 00:01:3219namespace gles2 {
20
[email protected]07f54fcc2009-12-22 02:46:3021// 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.
27COMPILE_ASSERT(sizeof(GLint) == sizeof(uint32), // NOLINT
28 GLint_not_same_size_as_uint32);
29COMPILE_ASSERT(sizeof(GLsizei) == sizeof(uint32), // NOLINT
30 GLint_not_same_size_as_uint32);
31
[email protected]96449d2c2009-11-25 00:01:3232namespace {
33
[email protected]07f54fcc2009-12-22 02:46:3034size_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
[email protected]96449d2c2009-11-25 00:01:3251// Returns the address of the first byte after a struct.
52template <typename T>
53const void* AddressAfterStruct(const T& pod) {
54 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
55}
56
[email protected]07f54fcc2009-12-22 02:46:3057// Returns the address of the frst byte after the struct or NULL if size >
58// immediate_data_size.
[email protected]96449d2c2009-11-25 00:01:3259template <typename RETURN_TYPE, typename COMMAND_TYPE>
[email protected]07f54fcc2009-12-22 02:46:3060RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& 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;
[email protected]96449d2c2009-11-25 00:01:3266}
67
[email protected]07f54fcc2009-12-22 02:46:3068// Computes the data size for certain gl commands like glUniform.
69uint32 ComputeImmediateDataSize(
[email protected]b9849abf2009-11-25 19:13:1970 uint32 immediate_data_size,
[email protected]96449d2c2009-11-25 00:01:3271 GLuint count,
72 size_t size,
73 unsigned int elements_per_unit) {
[email protected]07f54fcc2009-12-22 02:46:3074 return count * size * elements_per_unit;
[email protected]96449d2c2009-11-25 00:01:3275}
76
77// A struct to hold info about each command.
78struct CommandInfo {
79 int arg_flags; // How to handle the arguments for this command
80 int arg_count; // How many arguments are expected for this command.
81};
82
83// A table of CommandInfo for all the commands.
84const CommandInfo g_command_info[] = {
85 #define GLES2_CMD_OP(name) { \
86 name::kArgFlags, \
87 sizeof(name) / sizeof(CommandBufferEntry) - 1, }, /* NOLINT */ \
88
89 GLES2_COMMAND_LIST(GLES2_CMD_OP)
90
91 #undef GLES2_CMD_OP
92};
93
[email protected]96449d2c2009-11-25 00:01:3294namespace GLErrorBit {
95enum GLErrorBit {
96 kNoError = 0,
97 kInvalidEnum,
98 kInvalidValue,
99 kInvalidOperation,
100 kOutOfMemory,
101 kInvalidFrameBufferOperation,
102};
103}
104
105uint32 GLErrorToErrorBit(GLenum error) {
[email protected]a7a27ace2009-12-12 00:11:25106 switch (error) {
[email protected]96449d2c2009-11-25 00:01:32107 case GL_INVALID_ENUM:
108 return GLErrorBit::kInvalidEnum;
109 case GL_INVALID_VALUE:
110 return GLErrorBit::kInvalidValue;
111 case GL_INVALID_OPERATION:
112 return GLErrorBit::kInvalidOperation;
113 case GL_OUT_OF_MEMORY:
114 return GLErrorBit::kOutOfMemory;
115 case GL_INVALID_FRAMEBUFFER_OPERATION:
116 return GLErrorBit::kInvalidFrameBufferOperation;
117 default:
118 DCHECK(false);
119 return GLErrorBit::kNoError;
120 }
121}
122
123GLenum GLErrorBitToGLError(uint32 error_bit) {
[email protected]a7a27ace2009-12-12 00:11:25124 switch (error_bit) {
[email protected]96449d2c2009-11-25 00:01:32125 case GLErrorBit::kInvalidEnum:
126 return GL_INVALID_ENUM;
127 case GLErrorBit::kInvalidValue:
128 return GL_INVALID_VALUE;
129 case GLErrorBit::kInvalidOperation:
130 return GL_INVALID_OPERATION;
131 case GLErrorBit::kOutOfMemory:
132 return GL_OUT_OF_MEMORY;
133 case GLErrorBit::kInvalidFrameBufferOperation:
134 return GL_INVALID_FRAMEBUFFER_OPERATION;
135 default:
136 DCHECK(false);
137 return GL_NO_ERROR;
138 }
139}
140
141} // anonymous namespace.
142
[email protected]69d80ae2009-12-23 08:57:42143#if defined(UNIT_TEST)
[email protected]8a837bb2010-01-05 00:21:24144GLES2Decoder::GLES2Decoder()
145 : debug_(false) {
[email protected]69d80ae2009-12-23 08:57:42146#elif defined(OS_LINUX)
[email protected]96449d2c2009-11-25 00:01:32147GLES2Decoder::GLES2Decoder()
[email protected]b9849abf2009-11-25 19:13:19148 : debug_(false),
149 window_(NULL) {
150#elif defined(OS_WIN)
151GLES2Decoder::GLES2Decoder()
152 : debug_(false),
153 hwnd_(NULL) {
154#else
[email protected]8a837bb2010-01-05 00:21:24155GLES2Decoder::GLES2Decoder()
156 : debug_(false) {
[email protected]96449d2c2009-11-25 00:01:32157#endif
158}
159
160// This class maps one set of ids to another.
161class IdMap {
162 public:
163 // Maps a client_id to a service_id. Return false if the client_id or
164 // service_id are already mapped to something else.
165 bool AddMapping(GLuint client_id, GLuint service_id);
166
167 // Unmaps a pair of ids. Returns false if the pair were not previously mapped.
168 bool RemoveMapping(GLuint client_id, GLuint service_id);
169
170 // Gets the corresponding service_id for the given client_id.
171 // Returns false if there is no corresponding service_id.
172 bool GetServiceId(GLuint client_id, GLuint* service_id);
173
174 // Gets the corresponding client_id for the given service_id.
175 // Returns false if there is no corresponding client_id.
176 bool GetClientId(GLuint service_id, GLuint* client_id);
177
178 private:
179 // TODO(gman): Replace with faster implementation.
180 typedef std::map<GLuint, GLuint> MapType;
181 MapType id_map_;
182};
183
184bool IdMap::AddMapping(GLuint client_id, GLuint service_id) {
185 std::pair<MapType::iterator, bool> result = id_map_.insert(
186 std::make_pair(client_id, service_id));
187 return result.second;
188}
189
190bool IdMap::RemoveMapping(GLuint client_id, GLuint service_id) {
191 MapType::iterator iter = id_map_.find(client_id);
192 if (iter != id_map_.end() && iter->second == service_id) {
193 id_map_.erase(iter);
194 return true;
195 }
196 return false;
197}
198
199bool IdMap::GetServiceId(GLuint client_id, GLuint* service_id) {
200 DCHECK(service_id);
201 MapType::iterator iter = id_map_.find(client_id);
202 if (iter != id_map_.end()) {
203 *service_id = iter->second;
204 return true;
205 }
206 return false;
207}
208
209bool IdMap::GetClientId(GLuint service_id, GLuint* client_id) {
210 DCHECK(client_id);
211 MapType::iterator end(id_map_.end());
212 for (MapType::iterator iter(id_map_.begin());
213 iter != end;
214 ++iter) {
215 if (iter->second == service_id) {
216 *client_id = iter->first;
217 return true;
218 }
219 }
220 return false;
221}
222
223// This class implements GLES2Decoder so we don't have to expose all the GLES2
224// cmd stuff to outside this class.
225class GLES2DecoderImpl : public GLES2Decoder {
226 public:
[email protected]07f54fcc2009-12-22 02:46:30227 // Info about Vertex Attributes. This is used to track what the user currently
228 // has bound on each Vertex Attribute so that checking can be done at
229 // glDrawXXX time.
230 class VertexAttribInfo {
231 public:
232 VertexAttribInfo()
233 : enabled_(false),
234 size_(0),
235 type_(0),
236 offset_(0),
237 real_stride_(0),
238 buffer_(0),
239 buffer_size_(0),
240 num_elements_(0) {
241 }
242 // Returns true if this VertexAttrib can access index.
243 bool CanAccess(GLuint index);
244
245 void set_enabled(bool enabled) {
246 enabled_ = enabled;
247 }
248
249 GLuint buffer() const {
250 return buffer_;
251 }
252
253 void Clear() {
254 buffer_ = 0;
255 SetBufferSize(0);
256 }
257
258 void SetBufferSize(GLsizeiptr buffer_size) {
259 buffer_size_ = buffer_size;
260 if (offset_ > buffer_size || real_stride_ == 0) {
261 num_elements_ = 0;
262 } else {
263 uint32 size = buffer_size - offset_;
264 num_elements_ = size / real_stride_ +
265 (size % real_stride_ >= GetGLTypeSize(type_) ? 1 : 0);
266 }
267 }
268
269 void SetInfo(
270 GLuint buffer,
271 GLsizeiptr buffer_size,
272 GLint size,
273 GLenum type,
274 GLsizei real_stride,
275 GLsizei offset) {
[email protected]8a837bb2010-01-05 00:21:24276 DCHECK_GT(real_stride, 0);
[email protected]07f54fcc2009-12-22 02:46:30277 buffer_ = buffer;
278 size_ = size;
279 type_ = type;
280 real_stride_ = real_stride;
281 offset_ = offset;
282 SetBufferSize(buffer_size);
283 }
284
285 private:
286 // Whether or not this attribute is enabled.
287 bool enabled_;
288
289 // number of components (1, 2, 3, 4)
290 GLint size_;
291
292 // GL_BYTE, GL_FLOAT, etc. See glVertexAttribPointer.
293 GLenum type_;
294
295 // The offset into the buffer.
296 GLsizei offset_;
297
298 // The stride that will be used to access the buffer. This is the actual
299 // stide, NOT the GL bogus stride. In other words there is never a stride
300 // of 0.
301 GLsizei real_stride_;
302
303 // The service side name of the buffer bound to this attribute. 0 = invalid
304 GLuint buffer_;
305
306 // The size of the buffer.
307 GLsizeiptr buffer_size_;
308
309 // The number of elements that can be accessed.
310 GLuint num_elements_;
311 };
312
313 // Info about Buffers currently in the system.
314 struct BufferInfo {
315 BufferInfo()
316 : size(0) {
317 }
318
319 explicit BufferInfo(GLsizeiptr _size)
320 : size(_size) {
321 }
322
323 GLsizeiptr size;
324 };
325
326 // This is used to track which attributes a particular program needs
327 // so we can verify at glDrawXXX time that every attribute is either disabled
328 // or if enabled that it points to a valid source.
329 class ProgramInfo {
330 public:
331 typedef std::vector<GLuint> AttribLocationVector;
332
333 ProgramInfo() {
334 }
335
336 void SetNumAttributes(int num_attribs) {
337 attrib_locations_.resize(num_attribs);
338 }
339
340 void SetAttributeLocation(GLuint index, int location) {
341 DCHECK(index < attrib_locations_.size());
342 attrib_locations_[index] = location;
343 }
344
345 const AttribLocationVector& GetAttribLocations() const {
346 return attrib_locations_;
347 }
348 private:
349 AttribLocationVector attrib_locations_;
350 };
351
[email protected]96449d2c2009-11-25 00:01:32352 GLES2DecoderImpl();
353
354 // Overridden from AsyncAPIInterface.
355 virtual ParseError DoCommand(unsigned int command,
356 unsigned int arg_count,
357 const void* args);
358
359 // Overridden from AsyncAPIInterface.
360 virtual const char* GetCommandName(unsigned int command_id) const;
361
362 // Overridden from GLES2Decoder.
363 virtual bool Initialize();
364
365 // Overridden from GLES2Decoder.
366 virtual void Destroy();
367
[email protected]8a837bb2010-01-05 00:21:24368 // Overridden from GLES2Decoder.
369 virtual uint32 GetServiceIdForTesting(uint32 client_id);
370
[email protected]07f54fcc2009-12-22 02:46:30371 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
372 // on glDeleteBuffers so we can make sure the user does not try to render
373 // with deleted buffers.
374 void RemoveBufferInfo(GLuint buffer_id);
375
[email protected]96449d2c2009-11-25 00:01:32376 private:
377 bool InitPlatformSpecific();
378 bool InitGlew();
379
[email protected]96449d2c2009-11-25 00:01:32380 // Template to help call glGenXXX functions.
[email protected]07f54fcc2009-12-22 02:46:30381 template <void gl_gen_function(GLES2DecoderImpl*, GLsizei, GLuint*)>
[email protected]96449d2c2009-11-25 00:01:32382 bool GenGLObjects(GLsizei n, const GLuint* client_ids) {
[email protected]8a837bb2010-01-05 00:21:24383 if (n < 0) {
384 SetGLError(GL_INVALID_VALUE);
385 return true;
386 }
387 if (!ValidateIdsAreUnused(n, client_ids)) {
388 return false;
389 }
[email protected]96449d2c2009-11-25 00:01:32390 scoped_array<GLuint>temp(new GLuint[n]);
[email protected]07f54fcc2009-12-22 02:46:30391 gl_gen_function(this, n, temp.get());
[email protected]07f54fcc2009-12-22 02:46:30392 return RegisterObjects(n, client_ids, temp.get());
[email protected]96449d2c2009-11-25 00:01:32393 }
394
395 // Template to help call glDeleteXXX functions.
[email protected]07f54fcc2009-12-22 02:46:30396 template <void gl_delete_function(GLES2DecoderImpl*, GLsizei, GLuint*)>
[email protected]96449d2c2009-11-25 00:01:32397 bool DeleteGLObjects(GLsizei n, const GLuint* client_ids) {
398 scoped_array<GLuint>temp(new GLuint[n]);
[email protected]07f54fcc2009-12-22 02:46:30399 UnregisterObjects(n, client_ids, temp.get());
400 gl_delete_function(this, n, temp.get());
[email protected]96449d2c2009-11-25 00:01:32401 return true;
402 }
403
[email protected]8a837bb2010-01-05 00:21:24404 // Check that the given ids are not used.
405 bool ValidateIdsAreUnused(GLsizei n, const GLuint* client_ids);
406
[email protected]07f54fcc2009-12-22 02:46:30407 // Register client ids with generated service ids.
408 bool RegisterObjects(
409 GLsizei n, const GLuint* client_ids, const GLuint* service_ids);
410
411 // Unregisters client ids with service ids.
412 void UnregisterObjects(
413 GLsizei n, const GLuint* client_ids, GLuint* service_ids);
414
415 // Gets the program info for the given program. Returns NULL if none exists.
416 // Programs that have no had glLinkProgram succesfully called on them will
417 // not exist.
418 ProgramInfo* GetProgramInfo(GLuint program);
419
420 // Updates the program info for the given program.
421 void UpdateProgramInfo(GLuint program);
422
423 // Deletes the program info for the given program.
424 void RemoveProgramInfo(GLuint program);
425
426 // Gets the buffer info for the given buffer.
427 const BufferInfo* GetBufferInfo(GLuint buffer);
428
429 // Sets the info for a buffer.
430 void SetBufferInfo(GLuint buffer, GLsizeiptr size);
431
[email protected]96449d2c2009-11-25 00:01:32432 // Wrapper for glCreateProgram
433 void CreateProgramHelper(GLuint client_id);
434
435 // Wrapper for glCreateShader
436 void CreateShaderHelper(GLenum type, GLuint client_id);
437
438 // Wrapper for glBindBuffer since we need to track the current targets.
439 void DoBindBuffer(GLenum target, GLuint buffer);
440
[email protected]07f54fcc2009-12-22 02:46:30441 // Wrapper for glDrawArrays.
442 void DoDrawArrays(GLenum mode, GLint first, GLsizei count);
443
444 // Wrapper for glDisableVertexAttribArray.
445 void DoDisableVertexAttribArray(GLuint index);
446
447 // Wrapper for glEnableVertexAttribArray.
448 void DoEnableVertexAttribArray(GLuint index);
449
450 // Wrapper for glLinkProgram
451 void DoLinkProgram(GLuint program);
452
[email protected]96449d2c2009-11-25 00:01:32453 // Swaps the buffers (copies/renders to the current window).
454 void DoSwapBuffers();
455
[email protected]07f54fcc2009-12-22 02:46:30456 // Wrapper for glUseProgram
457 void DoUseProgram(GLuint program);
458
[email protected]96449d2c2009-11-25 00:01:32459 // Gets the GLError through our wrapper.
460 GLenum GetGLError();
461
462 // Sets our wrapper for the GLError.
463 void SetGLError(GLenum error);
464
[email protected]07f54fcc2009-12-22 02:46:30465 // Copies the real GL errors to the wrapper. This is so we can
466 // make sure there are no native GL errors before calling some GL function
467 // so that on return we know any error generated was for that specific
468 // command.
469 void CopyRealGLErrorsToWrapper();
470
471 // Checks if the current program and vertex attributes are valid for drawing.
472 bool IsDrawValid(GLuint max_vertex_accessed);
473
474 // Gets the buffer id for a given target.
475 GLuint GetBufferForTarget(GLenum target) {
476 DCHECK(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER);
477 return target == GL_ARRAY_BUFFER ? bound_array_buffer_ :
478 bound_element_array_buffer_;
479 }
480
[email protected]96449d2c2009-11-25 00:01:32481 // Generate a member function prototype for each command in an automated and
482 // typesafe way.
483 #define GLES2_CMD_OP(name) \
484 ParseError Handle ## name( \
[email protected]b9849abf2009-11-25 19:13:19485 uint32 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:32486 const gles2::name& args); \
487
488 GLES2_COMMAND_LIST(GLES2_CMD_OP)
489
490 #undef GLES2_CMD_OP
491
492 // Current GL error bits.
493 uint32 error_bits_;
494
495 // Map of client ids to GL ids.
496 IdMap id_map_;
497
498 // Util to help with GL.
499 GLES2Util util_;
500
501 // pack alignment as last set by glPixelStorei
502 GLint pack_alignment_;
503
504 // unpack alignment as last set by glPixelStorei
505 GLint unpack_alignment_;
506
507 // The currently bound array buffer. If this is 0 it is illegal to call
508 // glVertexAttribPointer.
509 GLuint bound_array_buffer_;
510
511 // The currently bound element array buffer. If this is 0 it is illegal
512 // to call glDrawElements.
513 GLuint bound_element_array_buffer_;
514
[email protected]07f54fcc2009-12-22 02:46:30515 // The maximum vertex attributes.
516 GLuint max_vertex_attribs_;
517
518 // Info for each vertex attribute saved so we can check at glDrawXXX time
519 // if it is safe to draw.
520 scoped_array<VertexAttribInfo> vertex_attrib_infos_;
521
522 // Info for each buffer in the system.
523 // TODO(gman): Choose a faster container.
524 typedef std::map<GLuint, BufferInfo> BufferInfoMap;
525 BufferInfoMap buffer_infos_;
526
527 // Info for each "successfully linked" program by service side program Id.
528 // TODO(gman): Choose a faster container.
529 typedef std::map<GLuint, ProgramInfo> ProgramInfoMap;
530 ProgramInfoMap program_infos_;
531
532 // The program in current use through glUseProgram.
533 ProgramInfo* current_program_info_;
534
[email protected]69d80ae2009-12-23 08:57:42535#if defined(UNIT_TEST)
536#elif defined(OS_WIN)
[email protected]96449d2c2009-11-25 00:01:32537 HDC device_context_;
538 HGLRC gl_context_;
539#endif
540
541 bool anti_aliased_;
542
543 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
544};
545
546GLES2Decoder* GLES2Decoder::Create() {
547 return new GLES2DecoderImpl();
548}
549
550GLES2DecoderImpl::GLES2DecoderImpl()
551 : GLES2Decoder(),
552 error_bits_(0),
553 util_(0), // TODO(gman): Set to actual num compress texture formats.
554 pack_alignment_(4),
555 unpack_alignment_(4),
556 bound_array_buffer_(0),
557 bound_element_array_buffer_(0),
[email protected]07f54fcc2009-12-22 02:46:30558 max_vertex_attribs_(0),
559 current_program_info_(NULL),
[email protected]69d80ae2009-12-23 08:57:42560#if defined(UNIT_TEST)
561#elif defined(OS_WIN)
[email protected]96449d2c2009-11-25 00:01:32562 device_context_(NULL),
563 gl_context_(NULL),
564#endif
565 anti_aliased_(false) {
566}
567
568bool GLES2DecoderImpl::Initialize() {
569 if (!InitPlatformSpecific())
570 return false;
571 if (!InitGlew())
572 return false;
573 CHECK_GL_ERROR();
574
[email protected]07f54fcc2009-12-22 02:46:30575 // Lookup GL things we need to know.
576 GLint value;
577 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &value);
578 max_vertex_attribs_ = value;
579
580 DCHECK_GE(max_vertex_attribs_, 8u);
581
582 vertex_attrib_infos_.reset(new VertexAttribInfo[max_vertex_attribs_]);
583 memset(vertex_attrib_infos_.get(), 0,
584 sizeof(vertex_attrib_infos_[0]) * max_vertex_attribs_);
585
[email protected]8a837bb2010-01-05 00:21:24586 // glBindFramebuffer(0, 0);
[email protected]96449d2c2009-11-25 00:01:32587 return true;
588}
589
[email protected]96449d2c2009-11-25 00:01:32590namespace {
591
[email protected]69d80ae2009-12-23 08:57:42592#if defined(UNIT_TEST)
593#elif defined(OS_WIN)
594
[email protected]96449d2c2009-11-25 00:01:32595const PIXELFORMATDESCRIPTOR kPixelFormatDescriptor = {
596 sizeof(kPixelFormatDescriptor), // Size of structure.
597 1, // Default version.
598 PFD_DRAW_TO_WINDOW | // Window drawing support.
599 PFD_SUPPORT_OPENGL | // OpenGL support.
600 PFD_DOUBLEBUFFER, // Double buffering support (not stereo).
601 PFD_TYPE_RGBA, // RGBA color mode (not indexed).
602 24, // 24 bit color mode.
603 0, 0, 0, 0, 0, 0, // Don't set RGB bits & shifts.
604 8, 0, // 8 bit alpha
605 0, // No accumulation buffer.
606 0, 0, 0, 0, // Ignore accumulation bits.
607 24, // 24 bit z-buffer size.
608 8, // 8-bit stencil buffer.
609 0, // No aux buffer.
610 PFD_MAIN_PLANE, // Main drawing plane (not overlay).
611 0, // Reserved.
612 0, 0, 0, // Layer masks ignored.
613};
614
615LRESULT CALLBACK IntermediateWindowProc(HWND window,
616 UINT message,
617 WPARAM w_param,
618 LPARAM l_param) {
619 return ::DefWindowProc(window, message, w_param, l_param);
620}
621
622// Helper routine that returns the highest quality pixel format supported on
623// the current platform. Returns true upon success.
624bool GetWindowsPixelFormat(HWND window,
625 bool anti_aliased,
626 int* pixel_format) {
627 // We must initialize a GL context before we can determine the multi-sampling
628 // supported on the current hardware, so we create an intermediate window
629 // and context here.
630 HINSTANCE module_handle;
631 if (!::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT |
632 GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
633 reinterpret_cast<wchar_t*>(IntermediateWindowProc),
634 &module_handle)) {
635 return false;
636 }
637
638 WNDCLASS intermediate_class;
639 intermediate_class.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
640 intermediate_class.lpfnWndProc = IntermediateWindowProc;
641 intermediate_class.cbClsExtra = 0;
642 intermediate_class.cbWndExtra = 0;
643 intermediate_class.hInstance = module_handle;
644 intermediate_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
645 intermediate_class.hCursor = LoadCursor(NULL, IDC_ARROW);
646 intermediate_class.hbrBackground = NULL;
647 intermediate_class.lpszMenuName = NULL;
648 intermediate_class.lpszClassName = L"Intermediate GL Window";
649
650 ATOM class_registration = ::RegisterClass(&intermediate_class);
651 if (!class_registration) {
652 return false;
653 }
654
655 HWND intermediate_window = ::CreateWindow(
656 reinterpret_cast<wchar_t*>(class_registration),
657 L"",
658 WS_OVERLAPPEDWINDOW,
659 0, 0,
660 CW_USEDEFAULT, CW_USEDEFAULT,
661 NULL,
662 NULL,
663 NULL,
664 NULL);
665
666 if (!intermediate_window) {
667 ::UnregisterClass(reinterpret_cast<wchar_t*>(class_registration),
668 module_handle);
669 return false;
670 }
671
672 HDC intermediate_dc = ::GetDC(intermediate_window);
673 int format_index = ::ChoosePixelFormat(intermediate_dc,
674 &kPixelFormatDescriptor);
675 if (format_index == 0) {
676 DLOG(ERROR) << "Unable to get the pixel format for GL context.";
677 ::ReleaseDC(intermediate_window, intermediate_dc);
678 ::DestroyWindow(intermediate_window);
679 ::UnregisterClass(reinterpret_cast<wchar_t*>(class_registration),
680 module_handle);
681 return false;
682 }
683 if (!::SetPixelFormat(intermediate_dc, format_index,
684 &kPixelFormatDescriptor)) {
685 DLOG(ERROR) << "Unable to set the pixel format for GL context.";
686 ::ReleaseDC(intermediate_window, intermediate_dc);
687 ::DestroyWindow(intermediate_window);
688 ::UnregisterClass(reinterpret_cast<wchar_t*>(class_registration),
689 module_handle);
690 return false;
691 }
692
693 // Store the pixel format without multisampling.
694 *pixel_format = format_index;
695 HGLRC gl_context = ::wglCreateContext(intermediate_dc);
696 if (::wglMakeCurrent(intermediate_dc, gl_context)) {
697 // GL context was successfully created and applied to the window's DC.
698 // Startup GLEW, the GL extensions wrangler.
699 GLenum glew_error = ::glewInit();
700 if (glew_error == GLEW_OK) {
701 DLOG(INFO) << "Initialized GLEW " << ::glewGetString(GLEW_VERSION);
702 } else {
703 DLOG(ERROR) << "Unable to initialise GLEW : "
704 << ::glewGetErrorString(glew_error);
705 ::wglMakeCurrent(intermediate_dc, NULL);
706 ::wglDeleteContext(gl_context);
707 ::ReleaseDC(intermediate_window, intermediate_dc);
708 ::DestroyWindow(intermediate_window);
709 ::UnregisterClass(reinterpret_cast<wchar_t*>(class_registration),
710 module_handle);
711 return false;
712 }
713
714 // If the multi-sample extensions are present, query the api to determine
715 // the pixel format.
716 if (anti_aliased && WGLEW_ARB_pixel_format && WGLEW_ARB_multisample) {
717 int pixel_attributes[] = {
718 WGL_SAMPLES_ARB, 4,
719 WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
720 WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
721 WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
722 WGL_COLOR_BITS_ARB, 24,
723 WGL_ALPHA_BITS_ARB, 8,
724 WGL_DEPTH_BITS_ARB, 24,
725 WGL_STENCIL_BITS_ARB, 8,
726 WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
727 WGL_SAMPLE_BUFFERS_ARB, GL_TRUE,
728 0, 0};
729
730 float pixel_attributes_f[] = {0, 0};
731 int msaa_pixel_format;
732 unsigned int num_formats;
733
734 // Query for the highest sampling rate supported, starting at 4x.
735 static const int kSampleCount[] = {4, 2};
736 static const int kNumSamples = 2;
737 for (int sample = 0; sample < kNumSamples; ++sample) {
738 pixel_attributes[1] = kSampleCount[sample];
739 if (GL_TRUE == ::wglChoosePixelFormatARB(intermediate_dc,
740 pixel_attributes,
741 pixel_attributes_f,
742 1,
743 &msaa_pixel_format,
744 &num_formats)) {
745 *pixel_format = msaa_pixel_format;
746 break;
747 }
748 }
749 }
750 }
751
752 ::wglMakeCurrent(intermediate_dc, NULL);
753 ::wglDeleteContext(gl_context);
754 ::ReleaseDC(intermediate_window, intermediate_dc);
755 ::DestroyWindow(intermediate_window);
756 ::UnregisterClass(reinterpret_cast<wchar_t*>(class_registration),
757 module_handle);
758 return true;
759}
760
[email protected]69d80ae2009-12-23 08:57:42761#endif // OS_WIN
762
[email protected]07f54fcc2009-12-22 02:46:30763// These commands convert from c calls to local os calls.
764void GLGenBuffersHelper(
765 GLES2DecoderImpl*, GLsizei n, GLuint* ids) {
766 glGenBuffersARB(n, ids);
767}
768
769void GLGenFramebuffersHelper(
770 GLES2DecoderImpl*, GLsizei n, GLuint* ids) {
771 glGenFramebuffersEXT(n, ids);
772}
773
774void GLGenRenderbuffersHelper(
775 GLES2DecoderImpl*, GLsizei n, GLuint* ids) {
776 glGenRenderbuffersEXT(n, ids);
777}
778
779void GLGenTexturesHelper(
780 GLES2DecoderImpl*, GLsizei n, GLuint* ids) {
781 glGenTextures(n, ids);
782}
783
784void GLDeleteBuffersHelper(
785 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids) {
786 glDeleteBuffersARB(n, ids);
787 for (GLsizei ii = 0; ii < n; ++ii) {
788 decoder->RemoveBufferInfo(ids[ii]);
789 }
790}
791
792void GLDeleteFramebuffersHelper(
793 GLES2DecoderImpl*, GLsizei n, GLuint* ids) {
794 glDeleteFramebuffersEXT(n, ids);
795}
796
797void GLDeleteRenderbuffersHelper(
798 GLES2DecoderImpl*, GLsizei n, GLuint* ids) {
799 glDeleteRenderbuffersEXT(n, ids);
800}
801
802void GLDeleteTexturesHelper(
803 GLES2DecoderImpl*, GLsizei n, GLuint* ids) {
804 glDeleteTextures(n, ids);
805}
806
[email protected]96449d2c2009-11-25 00:01:32807} // anonymous namespace
[email protected]96449d2c2009-11-25 00:01:32808
[email protected]8a837bb2010-01-05 00:21:24809uint32 GLES2DecoderImpl::GetServiceIdForTesting(uint32 client_id) {
810#if defined(UNIT_TEST)
811 GLuint service_id;
812 bool result = id_map_.GetServiceId(client_id, &service_id);
813 return result ? service_id : 0u;
814#else
815 DCHECK(false);
816 return 0u;
817#endif
818}
819
820bool GLES2DecoderImpl::ValidateIdsAreUnused(
821 GLsizei n, const GLuint* client_ids) {
822 for (GLsizei ii = 0; ii < n; ++ii) {
823 GLuint service_id;
824 if (id_map_.GetServiceId(client_ids[ii], &service_id)) {
825 return false;
826 }
827 }
828 return true;
829}
830
[email protected]07f54fcc2009-12-22 02:46:30831bool GLES2DecoderImpl::RegisterObjects(
832 GLsizei n, const GLuint* client_ids, const GLuint* service_ids) {
833 for (GLsizei ii = 0; ii < n; ++ii) {
834 if (!id_map_.AddMapping(client_ids[ii], service_ids[ii])) {
[email protected]8a837bb2010-01-05 00:21:24835 NOTREACHED();
836 return false;
[email protected]07f54fcc2009-12-22 02:46:30837 }
838 }
839 return true;
840}
841
842void GLES2DecoderImpl::UnregisterObjects(
843 GLsizei n, const GLuint* client_ids, GLuint* service_ids) {
[email protected]07f54fcc2009-12-22 02:46:30844 for (GLsizei ii = 0; ii < n; ++ii) {
845 if (id_map_.GetServiceId(client_ids[ii], &service_ids[ii])) {
846 id_map_.RemoveMapping(client_ids[ii], service_ids[ii]);
847 } else {
848 service_ids[ii] = 0;
849 }
850 }
851}
852
853void GLES2DecoderImpl::RemoveBufferInfo(GLuint buffer_id) {
854 for (GLuint ii = 0; ii < max_vertex_attribs_; ++ii) {
855 if (vertex_attrib_infos_[ii].buffer() == buffer_id) {
856 vertex_attrib_infos_[ii].Clear();
857 }
858 }
859 buffer_infos_.erase(buffer_id);
860}
861
[email protected]96449d2c2009-11-25 00:01:32862bool GLES2DecoderImpl::InitPlatformSpecific() {
[email protected]69d80ae2009-12-23 08:57:42863#if defined(UNIT_TEST)
864#elif defined(OS_WIN)
[email protected]96449d2c2009-11-25 00:01:32865 device_context_ = ::GetDC(hwnd());
866
867 int pixel_format;
868
869 if (!GetWindowsPixelFormat(hwnd(),
870 anti_aliased_,
871 &pixel_format)) {
872 DLOG(ERROR) << "Unable to determine optimal pixel format for GL context.";
873 return false;
874 }
875
876 if (!::SetPixelFormat(device_context_, pixel_format,
877 &kPixelFormatDescriptor)) {
878 DLOG(ERROR) << "Unable to set the pixel format for GL context.";
879 return false;
880 }
881
882 gl_context_ = ::wglCreateContext(device_context_);
883 if (!gl_context_) {
884 DLOG(ERROR) << "Failed to create GL context.";
885 return false;
886 }
887
888 if (!::wglMakeCurrent(device_context_, gl_context_)) {
889 DLOG(ERROR) << "Unable to make gl context current.";
890 return false;
891 }
892#elif defined(OS_LINUX)
893 DCHECK(window());
894 if (!window()->Initialize())
895 return false;
896 if (!window()->MakeCurrent())
897 return false;
898#endif
899
900 return true;
901}
902
903bool GLES2DecoderImpl::InitGlew() {
[email protected]69d80ae2009-12-23 08:57:42904#if !defined(UNIT_TEST)
[email protected]96449d2c2009-11-25 00:01:32905 DLOG(INFO) << "Initializing GL and GLEW for GLES2Decoder.";
906
907 GLenum glew_error = glewInit();
908 if (glew_error != GLEW_OK) {
909 DLOG(ERROR) << "Unable to initialise GLEW : "
910 << ::glewGetErrorString(glew_error);
911 return false;
912 }
913
914 // Check to see that we can use the OpenGL vertex attribute APIs
915 // TODO(petersont): Return false if this check fails, but because some
916 // Intel hardware does not support OpenGL 2.0, yet does support all of the
917 // extensions we require, we only log an error. A future CL should change
918 // this check to ensure that all of the extension strings we require are
919 // present.
920 if (!GLEW_VERSION_2_0) {
921 DLOG(ERROR) << "GL drivers do not have OpenGL 2.0 functionality.";
922 }
923
924 bool extensions_found = true;
925 if (!GLEW_ARB_vertex_buffer_object) {
926 // NOTE: Linux NVidia drivers claim to support OpenGL 2.0 when using
927 // indirect rendering (e.g. remote X), but it is actually lying. The
928 // ARB_vertex_buffer_object functions silently no-op (!) when using
929 // indirect rendering, leading to crashes. Fortunately, in that case, the
930 // driver claims to not support ARB_vertex_buffer_object, so fail in that
931 // case.
932 DLOG(ERROR) << "GL drivers do not support vertex buffer objects.";
933 extensions_found = false;
934 }
935 if (!GLEW_EXT_framebuffer_object) {
936 DLOG(ERROR) << "GL drivers do not support framebuffer objects.";
937 extensions_found = false;
938 }
939 // Check for necessary extensions
940 if (!GLEW_VERSION_2_0 && !GLEW_EXT_stencil_two_side) {
941 DLOG(ERROR) << "Two sided stencil extension missing.";
942 extensions_found = false;
943 }
944 if (!GLEW_VERSION_1_4 && !GLEW_EXT_blend_func_separate) {
945 DLOG(ERROR) <<"Separate blend func extension missing.";
946 extensions_found = false;
947 }
948 if (!GLEW_VERSION_2_0 && !GLEW_EXT_blend_equation_separate) {
949 DLOG(ERROR) << "Separate blend function extension missing.";
950 extensions_found = false;
951 }
952 if (!extensions_found)
953 return false;
[email protected]69d80ae2009-12-23 08:57:42954#endif
[email protected]96449d2c2009-11-25 00:01:32955
956 return true;
957}
958
959void GLES2DecoderImpl::Destroy() {
[email protected]69d80ae2009-12-23 08:57:42960#if defined(UNIT_TEST)
961#elif defined(OS_LINUX)
[email protected]96449d2c2009-11-25 00:01:32962 DCHECK(window());
963 window()->Destroy();
964#endif
965}
966
967const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
968 if (command_id > kStartPoint && command_id < kNumCommands) {
969 return gles2::GetCommandName(static_cast<CommandId>(command_id));
970 }
971 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
972}
973
974// Decode command with its arguments, and call the corresponding GL function.
975// Note: args is a pointer to the command buffer. As such, it could be changed
976// by a (malicious) client at any time, so if validation has to happen, it
977// should operate on a copy of them.
978parse_error::ParseError GLES2DecoderImpl::DoCommand(
979 unsigned int command,
980 unsigned int arg_count,
981 const void* cmd_data) {
[email protected]b9849abf2009-11-25 19:13:19982 parse_error::ParseError result;
983 if (debug()) {
984 // TODO(gman): Change output to something useful for NaCl.
985 const char* f = GetCommandName(command);
986 printf("cmd: %s\n", GetCommandName(command));
987 }
[email protected]96449d2c2009-11-25 00:01:32988 unsigned int command_index = command - kStartPoint - 1;
989 if (command_index < arraysize(g_command_info)) {
990 const CommandInfo& info = g_command_info[command_index];
991 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
992 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
993 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
[email protected]b9849abf2009-11-25 19:13:19994 uint32 immediate_data_size =
995 (arg_count - info_arg_count) * sizeof(CommandBufferEntry); // NOLINT
[email protected]96449d2c2009-11-25 00:01:32996 switch (command) {
997 #define GLES2_CMD_OP(name) \
998 case name::kCmdId: \
[email protected]b9849abf2009-11-25 19:13:19999 result = Handle ## name( \
1000 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:321001 *static_cast<const name*>(cmd_data)); \
[email protected]b9849abf2009-11-25 19:13:191002 break; \
[email protected]96449d2c2009-11-25 00:01:321003
1004 GLES2_COMMAND_LIST(GLES2_CMD_OP)
[email protected]96449d2c2009-11-25 00:01:321005 #undef GLES2_CMD_OP
[email protected]bf0985e2009-12-17 03:04:381006 }
1007 if (debug()) {
[email protected]07f54fcc2009-12-22 02:46:301008 GLenum error;
1009 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]bf0985e2009-12-17 03:04:381010 // TODO(gman): Change output to something useful for NaCl.
[email protected]07f54fcc2009-12-22 02:46:301011 SetGLError(error);
[email protected]bf0985e2009-12-17 03:04:381012 printf("GL ERROR b4: %s\n", GetCommandName(command));
[email protected]b9849abf2009-11-25 19:13:191013 }
[email protected]96449d2c2009-11-25 00:01:321014 }
1015 } else {
[email protected]b9849abf2009-11-25 19:13:191016 result = parse_error::kParseInvalidArguments;
[email protected]96449d2c2009-11-25 00:01:321017 }
[email protected]b9849abf2009-11-25 19:13:191018 } else {
1019 result = DoCommonCommand(command, arg_count, cmd_data);
[email protected]96449d2c2009-11-25 00:01:321020 }
[email protected]b9849abf2009-11-25 19:13:191021 return result;
[email protected]96449d2c2009-11-25 00:01:321022}
1023
[email protected]96449d2c2009-11-25 00:01:321024void GLES2DecoderImpl::CreateProgramHelper(GLuint client_id) {
1025 // TODO(gman): verify client_id is unused.
1026 GLuint service_id = glCreateProgram();
1027 if (service_id) {
1028 id_map_.AddMapping(client_id, service_id);
1029 }
1030}
1031
1032void GLES2DecoderImpl::CreateShaderHelper(GLenum type, GLuint client_id) {
1033 // TODO(gman): verify client_id is unused.
1034 GLuint service_id = glCreateShader(type);
1035 if (service_id) {
1036 id_map_.AddMapping(client_id, service_id);
1037 }
1038}
1039
1040void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint buffer) {
1041 switch (target) {
1042 case GL_ARRAY_BUFFER:
1043 bound_array_buffer_ = buffer;
1044 break;
1045 case GL_ELEMENT_ARRAY_BUFFER:
1046 bound_element_array_buffer_ = buffer;
1047 break;
1048 default:
[email protected]bf0985e2009-12-17 03:04:381049 DCHECK(false); // Validation should prevent us getting here.
[email protected]96449d2c2009-11-25 00:01:321050 break;
1051 }
1052 glBindBuffer(target, buffer);
1053}
1054
[email protected]07f54fcc2009-12-22 02:46:301055void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
1056 if (index < max_vertex_attribs_) {
1057 vertex_attrib_infos_[index].set_enabled(false);
[email protected]8a837bb2010-01-05 00:21:241058 glDisableVertexAttribArray(index);
[email protected]07f54fcc2009-12-22 02:46:301059 } else {
1060 SetGLError(GL_INVALID_VALUE);
1061 }
1062}
1063
1064void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
1065 if (index < max_vertex_attribs_) {
1066 vertex_attrib_infos_[index].set_enabled(true);
1067 glEnableVertexAttribArray(index);
1068 } else {
1069 SetGLError(GL_INVALID_VALUE);
1070 }
1071}
1072
[email protected]ba3176a2009-12-16 18:19:461073parse_error::ParseError GLES2DecoderImpl::HandleDeleteShader(
1074 uint32 immediate_data_size, const gles2::DeleteShader& c) {
1075 GLuint shader = c.shader;
[email protected]96449d2c2009-11-25 00:01:321076 GLuint service_id;
[email protected]ba3176a2009-12-16 18:19:461077 if (!id_map_.GetServiceId(shader, &service_id)) {
1078 SetGLError(GL_INVALID_VALUE);
1079 return parse_error::kParseNoError;
[email protected]96449d2c2009-11-25 00:01:321080 }
[email protected]07f54fcc2009-12-22 02:46:301081 glDeleteShader(service_id);
[email protected]ba3176a2009-12-16 18:19:461082 id_map_.RemoveMapping(shader, service_id);
1083 return parse_error::kParseNoError;
[email protected]96449d2c2009-11-25 00:01:321084}
1085
[email protected]ba3176a2009-12-16 18:19:461086parse_error::ParseError GLES2DecoderImpl::HandleDeleteProgram(
1087 uint32 immediate_data_size, const gles2::DeleteProgram& c) {
1088 GLuint program = c.program;
[email protected]96449d2c2009-11-25 00:01:321089 GLuint service_id;
[email protected]ba3176a2009-12-16 18:19:461090 if (!id_map_.GetServiceId(program, &service_id)) {
1091 SetGLError(GL_INVALID_VALUE);
1092 return parse_error::kParseNoError;
[email protected]96449d2c2009-11-25 00:01:321093 }
[email protected]07f54fcc2009-12-22 02:46:301094 RemoveProgramInfo(program);
[email protected]ba3176a2009-12-16 18:19:461095 glDeleteProgram(service_id);
1096 id_map_.RemoveMapping(program, service_id);
1097 return parse_error::kParseNoError;
[email protected]96449d2c2009-11-25 00:01:321098}
1099
[email protected]07f54fcc2009-12-22 02:46:301100void GLES2DecoderImpl::DoDrawArrays(
1101 GLenum mode, GLint first, GLsizei count) {
1102 if (IsDrawValid(first + count - 1)) {
1103 glDrawArrays(mode, first, count);
1104 }
1105}
1106
1107void GLES2DecoderImpl::DoLinkProgram(GLuint program) {
1108 CopyRealGLErrorsToWrapper();
1109 glLinkProgram(program);
1110 GLenum error = glGetError();
1111 if (error != GL_NO_ERROR) {
1112 RemoveProgramInfo(program);
1113 SetGLError(error);
1114 } else {
1115 UpdateProgramInfo(program);
1116 }
1117};
1118
[email protected]96449d2c2009-11-25 00:01:321119// NOTE: If you need to know the results of SwapBuffers (like losing
1120// the context) then add a new command. Do NOT make SwapBuffers synchronous.
1121void GLES2DecoderImpl::DoSwapBuffers() {
[email protected]69d80ae2009-12-23 08:57:421122#if defined(UNIT_TEST)
1123#elif defined(OS_WIN)
[email protected]96449d2c2009-11-25 00:01:321124 ::SwapBuffers(device_context_);
[email protected]69d80ae2009-12-23 08:57:421125#elif defined(OS_LINUX)
[email protected]96449d2c2009-11-25 00:01:321126 DCHECK(window());
1127 window()->SwapBuffers();
1128#endif
1129}
1130
[email protected]07f54fcc2009-12-22 02:46:301131void GLES2DecoderImpl::DoUseProgram(GLuint program) {
1132 ProgramInfo* info = GetProgramInfo(program);
1133 if (!info) {
1134 // Program was not linked successfully. (ie, glLinkProgram)
1135 SetGLError(GL_INVALID_OPERATION);
1136 } else {
1137 current_program_info_ = info;
1138 glUseProgram(program);
1139 }
1140}
1141
[email protected]96449d2c2009-11-25 00:01:321142GLenum GLES2DecoderImpl::GetGLError() {
1143 // Check the GL error first, then our wrapped error.
1144 GLenum error = glGetError();
1145 if (error == GL_NO_ERROR && error_bits_ != 0) {
1146 uint32 mask = 1;
1147 while (mask) {
1148 if ((error_bits_ & mask) != 0) {
1149 error = GLErrorBitToGLError(mask);
1150 break;
1151 }
1152 }
1153 }
1154
1155 if (error != GL_NO_ERROR) {
1156 // There was an error, clear the corresponding wrapped error.
1157 error_bits_ &= ~GLErrorToErrorBit(error);
1158 }
1159 return error;
1160}
1161
1162void GLES2DecoderImpl::SetGLError(GLenum error) {
1163 error_bits_ |= GLErrorToErrorBit(error);
1164}
1165
[email protected]07f54fcc2009-12-22 02:46:301166void GLES2DecoderImpl::CopyRealGLErrorsToWrapper() {
1167 GLenum error;
1168 while ((error = glGetError()) != GL_NO_ERROR) {
1169 SetGLError(error);
1170 }
1171}
1172
1173const GLES2DecoderImpl::BufferInfo* GLES2DecoderImpl::GetBufferInfo(
1174 GLuint buffer) {
1175 BufferInfoMap::iterator it = buffer_infos_.find(buffer);
1176 return it != buffer_infos_.end() ? &it->second : NULL;
1177}
1178
1179void GLES2DecoderImpl::SetBufferInfo(GLuint buffer, GLsizeiptr size) {
1180 buffer_infos_[buffer] = BufferInfo(size);
1181
1182 // Also go through VertexAttribInfo and update any info that references
1183 // the same buffer.
1184 for (GLuint ii = 0; ii < max_vertex_attribs_; ++ii) {
1185 if (vertex_attrib_infos_[ii].buffer() == buffer) {
1186 vertex_attrib_infos_[ii].SetBufferSize(size);
1187 }
1188 }
1189}
1190
1191GLES2DecoderImpl::ProgramInfo* GLES2DecoderImpl::GetProgramInfo(
1192 GLuint program) {
1193 ProgramInfoMap::iterator it = program_infos_.find(program);
1194 return it != program_infos_.end() ? &it->second : NULL;
1195}
1196
1197void GLES2DecoderImpl::UpdateProgramInfo(GLuint program) {
1198 ProgramInfo* info = GetProgramInfo(program);
1199 if (!info) {
1200 std::pair<ProgramInfoMap::iterator, bool> result =
1201 program_infos_.insert(std::make_pair(program, ProgramInfo()));
1202 DCHECK(result.second);
1203 info = &result.first->second;
1204 }
1205 GLint num_attribs = 0;
1206 GLint max_len = 0;
1207 glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &num_attribs);
1208 info->SetNumAttributes(num_attribs);
1209 glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_len);
1210 // TODO(gman): Should we check for error?
1211 scoped_array<char> name_buffer(new char[max_len + 1]);
1212 for (GLint ii = 0; ii < num_attribs; ++ii) {
1213 GLsizei length;
1214 GLsizei size;
1215 GLenum type;
1216 glGetActiveAttrib(
1217 program, ii, max_len + 1, &length, &size, &type, name_buffer.get());
1218 // TODO(gman): Should we check for error?
1219 GLint location = glGetAttribLocation(program, name_buffer.get());
1220 info->SetAttributeLocation(ii, num_attribs);
1221 }
1222}
1223
1224void GLES2DecoderImpl::RemoveProgramInfo(GLuint program) {
1225 ProgramInfoMap::iterator it = program_infos_.find(program);
1226 if (it != program_infos_.end()) {
1227 if (current_program_info_ == &it->second) {
1228 current_program_info_ = NULL;
1229 }
1230 program_infos_.erase(it);
1231 }
1232}
1233
1234bool GLES2DecoderImpl::VertexAttribInfo::CanAccess(GLuint index) {
1235 return !enabled_ || (buffer_ != 0 && index < num_elements_);
1236}
1237
1238bool GLES2DecoderImpl::IsDrawValid(GLuint max_vertex_accessed) {
1239 if (current_program_info_) {
1240 // Validate that all attribs current program needs are setup correctly.
1241 const ProgramInfo::AttribLocationVector& locations =
1242 current_program_info_->GetAttribLocations();
1243 for (size_t ii = 0; ii < locations.size(); ++ii) {
1244 GLuint location = locations[ii];
1245 DCHECK_LT(location, max_vertex_attribs_);
1246 if (!vertex_attrib_infos_[location].CanAccess(max_vertex_accessed)) {
1247 SetGLError(GL_INVALID_OPERATION);
1248 }
1249 }
1250 return true;
1251 }
1252 // We do not set a GL error here because the GL spec says no error if the
1253 // program is invalid.
1254 return false;
1255};
1256
[email protected]96449d2c2009-11-25 00:01:321257parse_error::ParseError GLES2DecoderImpl::HandleDrawElements(
[email protected]b9849abf2009-11-25 19:13:191258 uint32 immediate_data_size, const gles2::DrawElements& c) {
[email protected]96449d2c2009-11-25 00:01:321259 if (bound_element_array_buffer_ != 0) {
1260 GLenum mode = c.mode;
1261 GLsizei count = c.count;
1262 GLenum type = c.type;
[email protected]ba3176a2009-12-16 18:19:461263 if (!ValidateGLenumDrawMode(mode) ||
1264 !ValidateGLenumIndexType(type)) {
1265 SetGLError(GL_INVALID_VALUE);
1266 } else {
1267 const GLvoid* indices = reinterpret_cast<const GLvoid*>(c.index_offset);
[email protected]07f54fcc2009-12-22 02:46:301268 // TODO(gman): Validate indices. Get maximum index.
1269 //
1270 // This value should be computed by walking the index buffer from 0 to
1271 // count and finding the maximum vertex accessed.
1272 // For now we'll special case 0 to not check.
1273 GLuint max_vertex_accessed = 0;
1274 if (IsDrawValid(max_vertex_accessed)) {
1275 glDrawElements(mode, count, type, indices);
1276 }
[email protected]ba3176a2009-12-16 18:19:461277 }
[email protected]96449d2c2009-11-25 00:01:321278 } else {
1279 SetGLError(GL_INVALID_VALUE);
1280 }
1281 return parse_error::kParseNoError;
1282}
1283
1284namespace {
1285
1286// Calls glShaderSource for the various versions of the ShaderSource command.
1287// Assumes that data / data_size points to a piece of memory that is in range
1288// of whatever context it came from (shared memory, immediate memory, bucket
1289// memory.)
1290parse_error::ParseError ShaderSourceHelper(
1291 GLuint shader, GLsizei count, const char* data, uint32 data_size) {
1292 std::vector<std::string> strings(count);
1293 scoped_array<const char*> string_pointers(new const char* [count]);
1294
1295 const uint32* ends = reinterpret_cast<const uint32*>(data);
1296 uint32 start_offset = count * sizeof(*ends);
1297 if (start_offset > data_size) {
1298 return parse_error::kParseOutOfBounds;
1299 }
1300 for (GLsizei ii = 0; ii < count; ++ii) {
1301 uint32 end_offset = ends[ii];
1302 if (end_offset > data_size || end_offset < start_offset) {
1303 return parse_error::kParseOutOfBounds;
1304 }
1305 strings[ii] = std::string(data + start_offset, end_offset - start_offset);
1306 string_pointers[ii] = strings[ii].c_str();
1307 }
1308
1309 glShaderSource(shader, count, string_pointers.get(), NULL);
1310 return parse_error::kParseNoError;
1311}
1312
1313} // anonymous namespace.
1314
1315parse_error::ParseError GLES2DecoderImpl::HandleShaderSource(
[email protected]b9849abf2009-11-25 19:13:191316 uint32 immediate_data_size, const gles2::ShaderSource& c) {
1317 GLuint shader;
1318 if (!id_map_.GetServiceId(c.shader, &shader)) {
1319 SetGLError(GL_INVALID_VALUE);
1320 return parse_error::kParseNoError;
1321 }
[email protected]96449d2c2009-11-25 00:01:321322 GLsizei count = c.count;
1323 uint32 data_size = c.data_size;
1324 const char** data = GetSharedMemoryAs<const char**>(
1325 c.data_shm_id, c.data_shm_offset, data_size);
[email protected]ba3176a2009-12-16 18:19:461326 if (!data) {
1327 return parse_error::kParseOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:321328 }
1329 return ShaderSourceHelper(
1330 shader, count, reinterpret_cast<const char*>(data), data_size);
1331}
1332
1333parse_error::ParseError GLES2DecoderImpl::HandleShaderSourceImmediate(
[email protected]b9849abf2009-11-25 19:13:191334 uint32 immediate_data_size, const gles2::ShaderSourceImmediate& c) {
1335 GLuint shader;
1336 if (!id_map_.GetServiceId(c.shader, &shader)) {
1337 SetGLError(GL_INVALID_VALUE);
1338 return parse_error::kParseNoError;
1339 }
[email protected]96449d2c2009-11-25 00:01:321340 GLsizei count = c.count;
1341 uint32 data_size = c.data_size;
[email protected]07f54fcc2009-12-22 02:46:301342 const char** data = GetImmediateDataAs<const char**>(
1343 c, data_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:461344 if (!data) {
1345 return parse_error::kParseOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:321346 }
1347 return ShaderSourceHelper(
1348 shader, count, reinterpret_cast<const char*>(data), data_size);
1349}
1350
1351parse_error::ParseError GLES2DecoderImpl::HandleVertexAttribPointer(
[email protected]b9849abf2009-11-25 19:13:191352 uint32 immediate_data_size, const gles2::VertexAttribPointer& c) {
[email protected]96449d2c2009-11-25 00:01:321353 if (bound_array_buffer_ != 0) {
1354 GLuint indx = c.indx;
1355 GLint size = c.size;
1356 GLenum type = c.type;
1357 GLboolean normalized = c.normalized;
1358 GLsizei stride = c.stride;
[email protected]07f54fcc2009-12-22 02:46:301359 GLsizei offset = c.offset;
1360 const void* ptr = reinterpret_cast<const void*>(offset);
[email protected]ba3176a2009-12-16 18:19:461361 if (!ValidateGLenumVertexAttribType(type) ||
[email protected]8a837bb2010-01-05 00:21:241362 !ValidateGLintVertexAttribSize(size) ||
[email protected]07f54fcc2009-12-22 02:46:301363 indx >= max_vertex_attribs_ ||
1364 stride < 0) {
[email protected]ba3176a2009-12-16 18:19:461365 SetGLError(GL_INVALID_VALUE);
1366 return parse_error::kParseNoError;
[email protected]96449d2c2009-11-25 00:01:321367 }
[email protected]07f54fcc2009-12-22 02:46:301368 const BufferInfo* buffer_info = GetBufferInfo(bound_array_buffer_);
1369 GLsizei component_size = GetGLTypeSize(type);
1370 GLsizei real_stride = stride != 0 ? stride : component_size * size;
1371 if (offset % component_size > 0) {
1372 SetGLError(GL_INVALID_VALUE);
1373 return parse_error::kParseNoError;
1374 }
1375 vertex_attrib_infos_[indx].SetInfo(
1376 bound_array_buffer_,
1377 buffer_info ? buffer_info->size : 0,
1378 size,
1379 type,
1380 real_stride,
1381 offset);
[email protected]96449d2c2009-11-25 00:01:321382 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
1383 } else {
1384 SetGLError(GL_INVALID_VALUE);
1385 }
1386 return parse_error::kParseNoError;
1387}
1388
1389parse_error::ParseError GLES2DecoderImpl::HandleReadPixels(
[email protected]b9849abf2009-11-25 19:13:191390 uint32 immediate_data_size, const gles2::ReadPixels& c) {
[email protected]612d2f82009-12-08 20:49:311391 GLint x = c.x;
1392 GLint y = c.y;
1393 GLsizei width = c.width;
1394 GLsizei height = c.height;
1395 GLenum format = c.format;
1396 GLenum type = c.type;
1397 uint32 pixels_size = GLES2Util::ComputeImageDataSize(
1398 width, height, format, type, pack_alignment_);
1399 void* pixels = GetSharedMemoryAs<void*>(
1400 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
[email protected]ba3176a2009-12-16 18:19:461401 if (!pixels) {
1402 return parse_error::kParseOutOfBounds;
1403 }
1404 if (!ValidateGLenumReadPixelFormat(format) ||
1405 !ValidateGLenumPixelType(type)) {
1406 SetGLError(GL_INVALID_VALUE);
1407 return parse_error::kParseNoError;
[email protected]612d2f82009-12-08 20:49:311408 }
1409 glReadPixels(x, y, width, height, format, type, pixels);
[email protected]96449d2c2009-11-25 00:01:321410 return parse_error::kParseNoError;
1411}
1412
1413parse_error::ParseError GLES2DecoderImpl::HandlePixelStorei(
[email protected]b9849abf2009-11-25 19:13:191414 uint32 immediate_data_size, const gles2::PixelStorei& c) {
1415 GLenum pname = c.pname;
1416 GLenum param = c.param;
[email protected]ba3176a2009-12-16 18:19:461417 if (!ValidateGLenumPixelStore(pname) ||
[email protected]8a837bb2010-01-05 00:21:241418 !ValidateGLintPixelStoreAlignment(param)) {
[email protected]ba3176a2009-12-16 18:19:461419 SetGLError(GL_INVALID_VALUE);
1420 return parse_error::kParseNoError;
[email protected]b9849abf2009-11-25 19:13:191421 }
1422 glPixelStorei(pname, param);
1423 switch (pname) {
1424 case GL_PACK_ALIGNMENT:
1425 pack_alignment_ = param;
1426 break;
1427 case GL_UNPACK_ALIGNMENT:
1428 unpack_alignment_ = param;
1429 break;
1430 default:
1431 // Validation should have prevented us from getting here.
1432 DCHECK(false);
1433 break;
1434 }
1435 return parse_error::kParseNoError;
1436}
1437
1438parse_error::ParseError GLES2DecoderImpl::HandleGetAttribLocation(
1439 uint32 immediate_data_size, const gles2::GetAttribLocation& c) {
1440 GLuint program;
1441 if (!id_map_.GetServiceId(c.program, &program)) {
1442 SetGLError(GL_INVALID_VALUE);
1443 return parse_error::kParseNoError;
1444 }
1445 uint32 name_size = c.data_size;
1446 const char* name = GetSharedMemoryAs<const char*>(
1447 c.name_shm_id, c.name_shm_offset, name_size);
1448 GLint* location = GetSharedMemoryAs<GLint*>(
1449 c.location_shm_id, c.location_shm_offset, sizeof(GLint));
1450 if (!location || !name) {
1451 return parse_error::kParseOutOfBounds;
1452 }
1453 String name_str(name, name_size);
1454 *location = glGetAttribLocation(program, name_str.c_str());
1455 return parse_error::kParseNoError;
1456}
1457
1458parse_error::ParseError GLES2DecoderImpl::HandleGetAttribLocationImmediate(
1459 uint32 immediate_data_size, const gles2::GetAttribLocationImmediate& c) {
1460 GLuint program;
1461 if (!id_map_.GetServiceId(c.program, &program)) {
1462 SetGLError(GL_INVALID_VALUE);
1463 return parse_error::kParseNoError;
1464 }
1465 uint32 name_size = c.data_size;
[email protected]07f54fcc2009-12-22 02:46:301466 const char* name = GetImmediateDataAs<const char*>(
1467 c, name_size, immediate_data_size);
[email protected]b9849abf2009-11-25 19:13:191468 GLint* location = GetSharedMemoryAs<GLint*>(
1469 c.location_shm_id, c.location_shm_offset, sizeof(GLint));
1470 if (!location || !name) {
1471 return parse_error::kParseOutOfBounds;
1472 }
1473 String name_str(name, name_size);
1474 *location = glGetAttribLocation(program, name_str.c_str());
1475 return parse_error::kParseNoError;
1476}
1477
1478parse_error::ParseError GLES2DecoderImpl::HandleGetUniformLocation(
1479 uint32 immediate_data_size, const gles2::GetUniformLocation& c) {
1480 GLuint program;
1481 if (!id_map_.GetServiceId(c.program, &program)) {
1482 SetGLError(GL_INVALID_VALUE);
1483 return parse_error::kParseNoError;
1484 }
1485 uint32 name_size = c.data_size;
1486 const char* name = GetSharedMemoryAs<const char*>(
1487 c.name_shm_id, c.name_shm_offset, name_size);
1488 GLint* location = GetSharedMemoryAs<GLint*>(
1489 c.location_shm_id, c.location_shm_offset, sizeof(GLint));
1490 if (!location || !name) {
1491 return parse_error::kParseOutOfBounds;
1492 }
1493 String name_str(name, name_size);
1494 *location = glGetUniformLocation(program, name_str.c_str());
1495 return parse_error::kParseNoError;
1496}
1497
1498parse_error::ParseError GLES2DecoderImpl::HandleGetUniformLocationImmediate(
1499 uint32 immediate_data_size, const gles2::GetUniformLocationImmediate& c) {
1500 GLuint program;
1501 if (!id_map_.GetServiceId(c.program, &program)) {
1502 SetGLError(GL_INVALID_VALUE);
1503 return parse_error::kParseNoError;
1504 }
1505 uint32 name_size = c.data_size;
[email protected]07f54fcc2009-12-22 02:46:301506 const char* name = GetImmediateDataAs<const char*>(
1507 c, name_size, immediate_data_size);
[email protected]b9849abf2009-11-25 19:13:191508 GLint* location = GetSharedMemoryAs<GLint*>(
1509 c.location_shm_id, c.location_shm_offset, sizeof(GLint));
1510 if (!location || !name) {
1511 return parse_error::kParseOutOfBounds;
1512 }
1513 String name_str(name, name_size);
1514 *location = glGetUniformLocation(program, name_str.c_str());
1515 return parse_error::kParseNoError;
1516}
1517
1518parse_error::ParseError GLES2DecoderImpl::HandleBufferData(
1519 uint32 immediate_data_size, const gles2::BufferData& c) {
1520 GLenum target = static_cast<GLenum>(c.target);
1521 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
1522 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
1523 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
1524 GLenum usage = static_cast<GLenum>(c.usage);
1525 const void* data = NULL;
1526 if (data_shm_id != 0 || data_shm_offset != 0) {
1527 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
[email protected]ba3176a2009-12-16 18:19:461528 if (!data) {
1529 return parse_error::kParseOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:191530 }
1531 }
[email protected]ba3176a2009-12-16 18:19:461532 if (!ValidateGLenumBufferTarget(target) ||
1533 !ValidateGLenumBufferUsage(usage)) {
1534 SetGLError(GL_INVALID_VALUE);
1535 return parse_error::kParseNoError;
1536 }
[email protected]07f54fcc2009-12-22 02:46:301537 // Clear the buffer to 0 if no initial data was passed in.
1538 scoped_array<int8> zero;
1539 if (!data) {
1540 zero.reset(new int8[size]);
1541 memset(zero.get(), 0, size);
1542 data = zero.get();
1543 }
1544 CopyRealGLErrorsToWrapper();
[email protected]b9849abf2009-11-25 19:13:191545 glBufferData(target, size, data, usage);
[email protected]07f54fcc2009-12-22 02:46:301546 GLenum error = glGetError();
1547 if (error != GL_NO_ERROR) {
1548 SetGLError(error);
1549 } else {
1550 SetBufferInfo(GetBufferForTarget(target), size);
1551 }
[email protected]b9849abf2009-11-25 19:13:191552 return parse_error::kParseNoError;
1553}
1554
1555parse_error::ParseError GLES2DecoderImpl::HandleBufferDataImmediate(
1556 uint32 immediate_data_size, const gles2::BufferDataImmediate& c) {
1557 GLenum target = static_cast<GLenum>(c.target);
1558 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
[email protected]07f54fcc2009-12-22 02:46:301559 const void* data = GetImmediateDataAs<const void*>(
1560 c, size, immediate_data_size);
1561 if (!data) {
1562 return parse_error::kParseOutOfBounds;
1563 }
[email protected]b9849abf2009-11-25 19:13:191564 GLenum usage = static_cast<GLenum>(c.usage);
[email protected]ba3176a2009-12-16 18:19:461565 if (!ValidateGLenumBufferTarget(target) ||
1566 !ValidateGLenumBufferUsage(usage)) {
1567 SetGLError(GL_INVALID_VALUE);
1568 return parse_error::kParseNoError;
[email protected]b9849abf2009-11-25 19:13:191569 }
[email protected]07f54fcc2009-12-22 02:46:301570 CopyRealGLErrorsToWrapper();
[email protected]b9849abf2009-11-25 19:13:191571 glBufferData(target, size, data, usage);
[email protected]07f54fcc2009-12-22 02:46:301572 GLenum error = glGetError();
1573 if (error != GL_NO_ERROR) {
1574 SetGLError(error);
1575 } else {
1576 SetBufferInfo(GetBufferForTarget(target), size);
1577 }
[email protected]b9849abf2009-11-25 19:13:191578 return parse_error::kParseNoError;
1579}
1580
1581parse_error::ParseError GLES2DecoderImpl::HandleCompressedTexImage2D(
1582 uint32 immediate_data_size, const gles2::CompressedTexImage2D& c) {
1583 GLenum target = static_cast<GLenum>(c.target);
1584 GLint level = static_cast<GLint>(c.level);
1585 GLenum internal_format = static_cast<GLenum>(c.internalformat);
1586 GLsizei width = static_cast<GLsizei>(c.width);
1587 GLsizei height = static_cast<GLsizei>(c.height);
1588 GLint border = static_cast<GLint>(c.border);
1589 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
1590 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
1591 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
1592 const void* data = NULL;
1593 if (data_shm_id != 0 || data_shm_offset != 0) {
1594 data = GetSharedMemoryAs<const void*>(
1595 data_shm_id, data_shm_offset, image_size);
[email protected]ba3176a2009-12-16 18:19:461596 if (!data) {
1597 return parse_error::kParseOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:191598 }
1599 }
[email protected]ba3176a2009-12-16 18:19:461600 // TODO(gman): Validate internal_format
1601 if (!ValidateGLenumTextureTarget(target)) {
1602 SetGLError(GL_INVALID_VALUE);
1603 return parse_error::kParseNoError;
1604 }
[email protected]07f54fcc2009-12-22 02:46:301605 scoped_array<int8> zero;
1606 if (!data) {
1607 zero.reset(new int8[image_size]);
1608 memset(zero.get(), 0, image_size);
1609 data = zero.get();
1610 }
[email protected]b9849abf2009-11-25 19:13:191611 glCompressedTexImage2D(
1612 target, level, internal_format, width, height, border, image_size, data);
1613 return parse_error::kParseNoError;
1614}
1615
1616parse_error::ParseError GLES2DecoderImpl::HandleCompressedTexImage2DImmediate(
1617 uint32 immediate_data_size, const gles2::CompressedTexImage2DImmediate& c) {
1618 GLenum target = static_cast<GLenum>(c.target);
1619 GLint level = static_cast<GLint>(c.level);
1620 GLenum internal_format = static_cast<GLenum>(c.internalformat);
1621 GLsizei width = static_cast<GLsizei>(c.width);
1622 GLsizei height = static_cast<GLsizei>(c.height);
1623 GLint border = static_cast<GLint>(c.border);
1624 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
[email protected]07f54fcc2009-12-22 02:46:301625 const void* data = GetImmediateDataAs<const void*>(
1626 c, image_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:461627 if (!data) {
1628 return parse_error::kParseOutOfBounds;
1629 }
1630 // TODO(gman): Validate internal_format
1631 if (!ValidateGLenumTextureTarget(target)) {
1632 SetGLError(GL_INVALID_VALUE);
1633 return parse_error::kParseNoError;
[email protected]b9849abf2009-11-25 19:13:191634 }
1635 glCompressedTexImage2D(
1636 target, level, internal_format, width, height, border, image_size, data);
1637 return parse_error::kParseNoError;
1638}
1639
1640parse_error::ParseError GLES2DecoderImpl::HandleTexImage2D(
1641 uint32 immediate_data_size, const gles2::TexImage2D& c) {
1642 GLenum target = static_cast<GLenum>(c.target);
1643 GLint level = static_cast<GLint>(c.level);
1644 GLint internal_format = static_cast<GLint>(c.internalformat);
1645 GLsizei width = static_cast<GLsizei>(c.width);
1646 GLsizei height = static_cast<GLsizei>(c.height);
1647 GLint border = static_cast<GLint>(c.border);
1648 GLenum format = static_cast<GLenum>(c.format);
1649 GLenum type = static_cast<GLenum>(c.type);
1650 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
1651 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
1652 uint32 pixels_size = GLES2Util::ComputeImageDataSize(
1653 width, height, format, type, unpack_alignment_);
1654 const void* pixels = NULL;
1655 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
1656 pixels = GetSharedMemoryAs<const void*>(
1657 pixels_shm_id, pixels_shm_offset, pixels_size);
[email protected]ba3176a2009-12-16 18:19:461658 if (!pixels) {
1659 return parse_error::kParseOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:191660 }
1661 }
[email protected]ba3176a2009-12-16 18:19:461662 if (!ValidateGLenumTextureTarget(target) ||
1663 !ValidateGLenumTextureFormat(internal_format) ||
1664 !ValidateGLenumTextureFormat(format) ||
1665 !ValidateGLenumPixelType(type)) {
1666 SetGLError(GL_INVALID_VALUE);
1667 return parse_error::kParseNoError;
1668 }
[email protected]07f54fcc2009-12-22 02:46:301669 scoped_array<int8> zero;
1670 if (!pixels) {
1671 zero.reset(new int8[pixels_size]);
1672 memset(zero.get(), 0, pixels_size);
1673 pixels = zero.get();
1674 }
[email protected]b9849abf2009-11-25 19:13:191675 glTexImage2D(
1676 target, level, internal_format, width, height, border, format, type,
1677 pixels);
1678 return parse_error::kParseNoError;
1679}
1680
1681parse_error::ParseError GLES2DecoderImpl::HandleTexImage2DImmediate(
1682 uint32 immediate_data_size, const gles2::TexImage2DImmediate& c) {
1683 GLenum target = static_cast<GLenum>(c.target);
1684 GLint level = static_cast<GLint>(c.level);
[email protected]ba3176a2009-12-16 18:19:461685 GLint internal_format = static_cast<GLint>(c.internalformat);
[email protected]b9849abf2009-11-25 19:13:191686 GLsizei width = static_cast<GLsizei>(c.width);
1687 GLsizei height = static_cast<GLsizei>(c.height);
1688 GLint border = static_cast<GLint>(c.border);
1689 GLenum format = static_cast<GLenum>(c.format);
1690 GLenum type = static_cast<GLenum>(c.type);
[email protected]07f54fcc2009-12-22 02:46:301691 uint32 size = GLES2Util::ComputeImageDataSize(
1692 width, height, format, type, unpack_alignment_);
1693 const void* pixels = GetImmediateDataAs<const void*>(
1694 c, size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:461695 if (!pixels) {
1696 return parse_error::kParseOutOfBounds;
1697 }
1698 if (!ValidateGLenumTextureTarget(target) ||
1699 !ValidateGLenumTextureFormat(internal_format) ||
1700 !ValidateGLenumTextureFormat(format) ||
1701 !ValidateGLenumPixelType(type)) {
1702 SetGLError(GL_INVALID_VALUE);
1703 return parse_error::kParseNoError;
[email protected]b9849abf2009-11-25 19:13:191704 }
1705 glTexImage2D(
[email protected]ba3176a2009-12-16 18:19:461706 target, level, internal_format, width, height, border, format, type,
[email protected]b9849abf2009-11-25 19:13:191707 pixels);
[email protected]96449d2c2009-11-25 00:01:321708 return parse_error::kParseNoError;
1709}
1710
1711parse_error::ParseError GLES2DecoderImpl::HandleGetVertexAttribPointerv(
[email protected]b9849abf2009-11-25 19:13:191712 uint32 immediate_data_size, const gles2::GetVertexAttribPointerv& c) {
[email protected]96449d2c2009-11-25 00:01:321713 // TODO(gman): Implement.
1714 return parse_error::kParseNoError;
1715}
1716
1717parse_error::ParseError GLES2DecoderImpl::HandleGetUniformiv(
[email protected]b9849abf2009-11-25 19:13:191718 uint32 immediate_data_size, const gles2::GetUniformiv& c) {
[email protected]96449d2c2009-11-25 00:01:321719 // TODO(gman): Implement.
1720 return parse_error::kParseNoError;
1721}
1722
1723parse_error::ParseError GLES2DecoderImpl::HandleGetUniformfv(
[email protected]b9849abf2009-11-25 19:13:191724 uint32 immediate_data_size, const gles2::GetUniformfv& c) {
[email protected]96449d2c2009-11-25 00:01:321725 // TODO(gman): Implement.
1726 return parse_error::kParseNoError;
1727}
1728
1729parse_error::ParseError GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
[email protected]b9849abf2009-11-25 19:13:191730 uint32 immediate_data_size, const gles2::GetShaderPrecisionFormat& c) {
[email protected]96449d2c2009-11-25 00:01:321731 // TODO(gman): Implement.
1732 return parse_error::kParseNoError;
1733}
1734
1735parse_error::ParseError GLES2DecoderImpl::HandleGetAttachedShaders(
[email protected]b9849abf2009-11-25 19:13:191736 uint32 immediate_data_size, const gles2::GetAttachedShaders& c) {
[email protected]96449d2c2009-11-25 00:01:321737 // TODO(gman): Implement.
1738 return parse_error::kParseNoError;
1739}
1740
1741parse_error::ParseError GLES2DecoderImpl::HandleGetActiveUniform(
[email protected]b9849abf2009-11-25 19:13:191742 uint32 immediate_data_size, const gles2::GetActiveUniform& c) {
[email protected]96449d2c2009-11-25 00:01:321743 // TODO(gman): Implement.
1744 return parse_error::kParseNoError;
1745}
1746
1747parse_error::ParseError GLES2DecoderImpl::HandleGetActiveAttrib(
[email protected]b9849abf2009-11-25 19:13:191748 uint32 immediate_data_size, const gles2::GetActiveAttrib& c) {
[email protected]96449d2c2009-11-25 00:01:321749 // TODO(gman): Implement.
1750 return parse_error::kParseNoError;
1751}
1752
1753// Include the auto-generated part of this file. We split this because it means
1754// we can easily edit the non-auto generated parts right here in this file
1755// instead of having to edit some template or the code generator.
1756#include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
1757
1758} // namespace gles2
[email protected]a7a27ace2009-12-12 00:11:251759} // namespace gpu
[email protected]96449d2c2009-11-25 00:01:321760