blob: 6940f8d1b5f09b9c8cfbdf66bb972788f2584c04 [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]74470702010-01-06 18:51:166
7#include <stdio.h>
8
[email protected]1aef98132010-02-23 18:00:079#include <algorithm>
[email protected]f39f4b3f2010-05-12 17:04:0810#include <list>
[email protected]96449d2c2009-11-25 00:01:3211#include <map>
[email protected]f39f4b3f2010-05-12 17:04:0812#include <string>
13#include <vector>
[email protected]5a6db6c2010-04-22 18:32:0614
15#include "app/gfx/gl/gl_context.h"
[email protected]b9363b22010-06-09 22:06:1516#include "app/gfx/gl/gl_implementation.h"
[email protected]00eb49a2010-08-12 20:46:5717#include "base/at_exit.h"
[email protected]2041cf342010-02-19 03:15:5918#include "base/callback.h"
[email protected]96449d2c2009-11-25 00:01:3219#include "base/scoped_ptr.h"
[email protected]6217d392010-03-25 22:08:3520#include "base/weak_ptr.h"
[email protected]d37231fa2010-04-09 21:16:0221#include "build/build_config.h"
[email protected]96449d2c2009-11-25 00:01:3222#define GLES2_GPU_SERVICE 1
23#include "gpu/command_buffer/common/gles2_cmd_format.h"
24#include "gpu/command_buffer/common/gles2_cmd_utils.h"
[email protected]066849e32010-05-03 19:14:1025#include "gpu/command_buffer/common/id_allocator.h"
[email protected]3916c97e2010-02-25 03:20:5026#include "gpu/command_buffer/service/buffer_manager.h"
[email protected]96449d2c2009-11-25 00:01:3227#include "gpu/command_buffer/service/cmd_buffer_engine.h"
[email protected]3916c97e2010-02-25 03:20:5028#include "gpu/command_buffer/service/context_group.h"
[email protected]a25fa872010-03-25 02:57:5829#include "gpu/command_buffer/service/framebuffer_manager.h"
[email protected]96449d2c2009-11-25 00:01:3230#include "gpu/command_buffer/service/gl_utils.h"
[email protected]ba3176a2009-12-16 18:19:4631#include "gpu/command_buffer/service/gles2_cmd_validation.h"
[email protected]a93bb842010-02-16 23:03:4732#include "gpu/command_buffer/service/program_manager.h"
[email protected]a25fa872010-03-25 02:57:5833#include "gpu/command_buffer/service/renderbuffer_manager.h"
[email protected]a93bb842010-02-16 23:03:4734#include "gpu/command_buffer/service/shader_manager.h"
35#include "gpu/command_buffer/service/texture_manager.h"
[email protected]4e8a5b122010-05-08 22:00:1036#include "gpu/GLES2/gles2_command_buffer.h"
[email protected]3094c2a2010-04-29 21:50:4537#include "third_party/angle/include/GLSLANG/ShaderLang.h"
[email protected]de17df392010-04-23 21:09:4138
[email protected]6217d392010-03-25 22:08:3539#if !defined(GL_DEPTH24_STENCIL8)
40#define GL_DEPTH24_STENCIL8 0x88F0
41#endif
42
[email protected]a7a27ace2009-12-12 00:11:2543namespace gpu {
[email protected]96449d2c2009-11-25 00:01:3244namespace gles2 {
45
[email protected]6217d392010-03-25 22:08:3546class GLES2DecoderImpl;
47
[email protected]07f54fcc2009-12-22 02:46:3048// Check that certain assumptions the code makes are true. There are places in
49// the code where shared memory is passed direclty to GL. Example, glUniformiv,
50// glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
51// a few others) are 32bits. If they are not 32bits the code will have to change
52// to call those GL functions with service side memory and then copy the results
53// to shared memory, converting the sizes.
54COMPILE_ASSERT(sizeof(GLint) == sizeof(uint32), // NOLINT
55 GLint_not_same_size_as_uint32);
56COMPILE_ASSERT(sizeof(GLsizei) == sizeof(uint32), // NOLINT
57 GLint_not_same_size_as_uint32);
[email protected]f7b85372010-02-03 01:11:3758COMPILE_ASSERT(sizeof(GLfloat) == sizeof(float), // NOLINT
59 GLfloat_not_same_size_as_float);
[email protected]07f54fcc2009-12-22 02:46:3060
[email protected]43f28f832010-02-03 02:28:4861// TODO(kbr): the use of this anonymous namespace core dumps the
62// linker on Mac OS X 10.6 when the symbol ordering file is used
63// namespace {
[email protected]96449d2c2009-11-25 00:01:3264
65// Returns the address of the first byte after a struct.
66template <typename T>
67const void* AddressAfterStruct(const T& pod) {
68 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
69}
70
[email protected]07f54fcc2009-12-22 02:46:3071// Returns the address of the frst byte after the struct or NULL if size >
72// immediate_data_size.
[email protected]96449d2c2009-11-25 00:01:3273template <typename RETURN_TYPE, typename COMMAND_TYPE>
[email protected]07f54fcc2009-12-22 02:46:3074RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod,
75 uint32 size,
76 uint32 immediate_data_size) {
77 return (size <= immediate_data_size) ?
78 static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))) :
79 NULL;
[email protected]96449d2c2009-11-25 00:01:3280}
81
[email protected]07f54fcc2009-12-22 02:46:3082// Computes the data size for certain gl commands like glUniform.
[email protected]a76b0052010-03-05 00:33:1883bool ComputeDataSize(
[email protected]96449d2c2009-11-25 00:01:3284 GLuint count,
85 size_t size,
[email protected]a76b0052010-03-05 00:33:1886 unsigned int elements_per_unit,
87 uint32* dst) {
88 uint32 value;
89 if (!SafeMultiplyUint32(count, size, &value)) {
90 return false;
91 }
92 if (!SafeMultiplyUint32(value, elements_per_unit, &value)) {
93 return false;
94 }
95 *dst = value;
96 return true;
[email protected]96449d2c2009-11-25 00:01:3297}
98
99// A struct to hold info about each command.
100struct CommandInfo {
101 int arg_flags; // How to handle the arguments for this command
102 int arg_count; // How many arguments are expected for this command.
103};
104
105// A table of CommandInfo for all the commands.
106const CommandInfo g_command_info[] = {
107 #define GLES2_CMD_OP(name) { \
108 name::kArgFlags, \
109 sizeof(name) / sizeof(CommandBufferEntry) - 1, }, /* NOLINT */ \
110
111 GLES2_COMMAND_LIST(GLES2_CMD_OP)
112
113 #undef GLES2_CMD_OP
114};
115
[email protected]6217d392010-03-25 22:08:35116// This class prevents any GL errors that occur when it is in scope from
117// being reported to the client.
118class ScopedGLErrorSuppressor {
119 public:
120 explicit ScopedGLErrorSuppressor(GLES2DecoderImpl* decoder);
121 ~ScopedGLErrorSuppressor();
122 private:
123 GLES2DecoderImpl* decoder_;
124 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor);
125};
126
127// Temporarily changes a decoder's bound 2D texture and restore it when this
128// object goes out of scope. Also temporarily switches to using active texture
129// unit zero in case the client has changed that to something invalid.
130class ScopedTexture2DBinder {
131 public:
132 ScopedTexture2DBinder(GLES2DecoderImpl* decoder, GLuint id);
133 ~ScopedTexture2DBinder();
134
135 private:
136 GLES2DecoderImpl* decoder_;
137 DISALLOW_COPY_AND_ASSIGN(ScopedTexture2DBinder);
138};
139
140// Temporarily changes a decoder's bound render buffer and restore it when this
141// object goes out of scope.
142class ScopedRenderBufferBinder {
143 public:
144 ScopedRenderBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
145 ~ScopedRenderBufferBinder();
146
147 private:
148 GLES2DecoderImpl* decoder_;
149 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder);
150};
151
152// Temporarily changes a decoder's bound frame buffer and restore it when this
153// object goes out of scope.
154class ScopedFrameBufferBinder {
155 public:
156 ScopedFrameBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
157 ~ScopedFrameBufferBinder();
158
159 private:
160 GLES2DecoderImpl* decoder_;
161 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder);
162};
163
[email protected]2f2d7042010-04-14 21:45:58164// Temporarily switch to a decoder's default GL context, having known default
165// state.
166class ScopedDefaultGLContext {
167 public:
168 explicit ScopedDefaultGLContext(GLES2DecoderImpl* decoder);
169 ~ScopedDefaultGLContext();
170
171 private:
172 GLES2DecoderImpl* decoder_;
173 DISALLOW_COPY_AND_ASSIGN(ScopedDefaultGLContext);
174};
175
[email protected]6217d392010-03-25 22:08:35176// Encapsulates an OpenGL texture.
177class Texture {
178 public:
179 explicit Texture(GLES2DecoderImpl* decoder);
180 ~Texture();
181
182 // Create a new render texture.
183 void Create();
184
185 // Set the initial size and format of a render texture or resize it.
186 bool AllocateStorage(const gfx::Size& size);
187
188 // Copy the contents of the currently bound frame buffer.
189 void Copy(const gfx::Size& size);
190
191 // Destroy the render texture. This must be explicitly called before
192 // destroying this object.
193 void Destroy();
194
195 GLuint id() const {
196 return id_;
197 }
198
[email protected]d37231fa2010-04-09 21:16:02199 gfx::Size size() const {
200 return size_;
201 }
202
[email protected]6217d392010-03-25 22:08:35203 private:
204 GLES2DecoderImpl* decoder_;
205 GLuint id_;
[email protected]d37231fa2010-04-09 21:16:02206 gfx::Size size_;
[email protected]6217d392010-03-25 22:08:35207 DISALLOW_COPY_AND_ASSIGN(Texture);
208};
209
210// Encapsulates an OpenGL render buffer of any format.
211class RenderBuffer {
212 public:
213 explicit RenderBuffer(GLES2DecoderImpl* decoder);
214 ~RenderBuffer();
215
216 // Create a new render buffer.
217 void Create();
218
219 // Set the initial size and format of a render buffer or resize it.
220 bool AllocateStorage(const gfx::Size& size, GLenum format);
221
222 // Destroy the render buffer. This must be explicitly called before destroying
223 // this object.
224 void Destroy();
225
226 GLuint id() const {
227 return id_;
228 }
229
230 private:
231 GLES2DecoderImpl* decoder_;
232 GLuint id_;
233 DISALLOW_COPY_AND_ASSIGN(RenderBuffer);
234};
235
236// Encapsulates an OpenGL frame buffer.
237class FrameBuffer {
238 public:
239 explicit FrameBuffer(GLES2DecoderImpl* decoder);
240 ~FrameBuffer();
241
242 // Create a new frame buffer.
243 void Create();
244
245 // Attach a color render buffer to a frame buffer.
246 void AttachRenderTexture(Texture* texture);
247
[email protected]b9363b22010-06-09 22:06:15248 // Attach a render buffer to a frame buffer. Note that this unbinds any
249 // currently bound frame buffer.
250 void AttachRenderBuffer(GLenum target, RenderBuffer* render_buffer);
[email protected]6217d392010-03-25 22:08:35251
252 // Clear the given attached buffers.
253 void Clear(GLbitfield buffers);
254
255 // Destroy the frame buffer. This must be explicitly called before destroying
256 // this object.
257 void Destroy();
258
259 // See glCheckFramebufferStatusEXT.
260 GLenum CheckStatus();
261
262 GLuint id() const {
263 return id_;
264 }
265
266 private:
267 GLES2DecoderImpl* decoder_;
268 GLuint id_;
269 DISALLOW_COPY_AND_ASSIGN(FrameBuffer);
270};
[email protected]00eb49a2010-08-12 20:46:57271
[email protected]00f893d2010-08-24 18:55:49272void FinalizeShaderTranslator(void* /* dummy */) {
[email protected]00eb49a2010-08-12 20:46:57273 ShFinalize();
274}
275
276bool InitializeShaderTranslator() {
277 static bool initialized = false;
278 if (!initialized && ShInitialize()) {
279 base::AtExitManager::RegisterCallback(&FinalizeShaderTranslator, NULL);
280 initialized = true;
281 }
282 return initialized;
283}
[email protected]43f28f832010-02-03 02:28:48284// } // anonymous namespace.
[email protected]96449d2c2009-11-25 00:01:32285
[email protected]3916c97e2010-02-25 03:20:50286GLES2Decoder::GLES2Decoder(ContextGroup* group)
287 : group_(group),
[email protected]3916c97e2010-02-25 03:20:50288 debug_(false) {
[email protected]96449d2c2009-11-25 00:01:32289}
290
[email protected]3916c97e2010-02-25 03:20:50291GLES2Decoder::~GLES2Decoder() {
292}
293
[email protected]f39f4b3f2010-05-12 17:04:08294class VertexAttribManager {
[email protected]96449d2c2009-11-25 00:01:32295 public:
[email protected]07f54fcc2009-12-22 02:46:30296 // Info about Vertex Attributes. This is used to track what the user currently
297 // has bound on each Vertex Attribute so that checking can be done at
298 // glDrawXXX time.
299 class VertexAttribInfo {
300 public:
[email protected]f39f4b3f2010-05-12 17:04:08301 typedef std::list<VertexAttribInfo*> VertexAttribInfoList;
[email protected]b1122982010-05-17 23:04:24302 struct Vec4 {
303 float v[4];
304 };
[email protected]f39f4b3f2010-05-12 17:04:08305
[email protected]07f54fcc2009-12-22 02:46:30306 VertexAttribInfo()
[email protected]f39f4b3f2010-05-12 17:04:08307 : index_(0),
308 enabled_(false),
309 size_(4),
310 type_(GL_FLOAT),
[email protected]07f54fcc2009-12-22 02:46:30311 offset_(0),
[email protected]b1122982010-05-17 23:04:24312 normalized_(GL_FALSE),
313 gl_stride_(0),
[email protected]f39f4b3f2010-05-12 17:04:08314 real_stride_(16),
315 list_(NULL) {
[email protected]b1122982010-05-17 23:04:24316 value_.v[0] = 0.0f;
317 value_.v[1] = 0.0f;
318 value_.v[2] = 0.0f;
319 value_.v[3] = 1.0f;
[email protected]07f54fcc2009-12-22 02:46:30320 }
[email protected]3916c97e2010-02-25 03:20:50321
[email protected]07f54fcc2009-12-22 02:46:30322 // Returns true if this VertexAttrib can access index.
[email protected]f39f4b3f2010-05-12 17:04:08323 bool CanAccess(GLuint index) const;
[email protected]07f54fcc2009-12-22 02:46:30324
[email protected]3916c97e2010-02-25 03:20:50325 BufferManager::BufferInfo* buffer() const {
[email protected]07f54fcc2009-12-22 02:46:30326 return buffer_;
327 }
328
[email protected]8bf5a3e2010-01-29 04:21:36329 GLsizei offset() const {
330 return offset_;
331 }
332
[email protected]f39f4b3f2010-05-12 17:04:08333 GLuint index() const {
334 return index_;
335 }
336
[email protected]b1122982010-05-17 23:04:24337 GLint size() const {
338 return size_;
339 }
340
341 GLenum type() const {
342 return type_;
343 }
344
345 GLboolean normalized() const {
346 return normalized_;
347 }
348
349 GLsizei gl_stride() const {
350 return gl_stride_;
351 }
352
[email protected]07f54fcc2009-12-22 02:46:30353 void SetInfo(
[email protected]3916c97e2010-02-25 03:20:50354 BufferManager::BufferInfo* buffer,
[email protected]07f54fcc2009-12-22 02:46:30355 GLint size,
356 GLenum type,
[email protected]b1122982010-05-17 23:04:24357 GLboolean normalized,
358 GLsizei gl_stride,
[email protected]07f54fcc2009-12-22 02:46:30359 GLsizei real_stride,
360 GLsizei offset) {
[email protected]8a837bb2010-01-05 00:21:24361 DCHECK_GT(real_stride, 0);
[email protected]07f54fcc2009-12-22 02:46:30362 buffer_ = buffer;
363 size_ = size;
364 type_ = type;
[email protected]b1122982010-05-17 23:04:24365 normalized_ = normalized;
366 gl_stride_ = gl_stride;
[email protected]07f54fcc2009-12-22 02:46:30367 real_stride_ = real_stride;
368 offset_ = offset;
[email protected]3916c97e2010-02-25 03:20:50369 }
370
371 void ClearBuffer() {
372 buffer_ = NULL;
[email protected]07f54fcc2009-12-22 02:46:30373 }
374
[email protected]f39f4b3f2010-05-12 17:04:08375 bool enabled() const {
376 return enabled_;
377 }
378
[email protected]b1122982010-05-17 23:04:24379 void set_value(const Vec4& value) {
380 value_ = value;
381 }
382
383 const Vec4& value() const {
384 return value_;
385 }
386
[email protected]07f54fcc2009-12-22 02:46:30387 private:
[email protected]f39f4b3f2010-05-12 17:04:08388 friend class VertexAttribManager;
389
390 void set_enabled(bool enabled) {
391 enabled_ = enabled;
392 }
393
394 void set_index(GLuint index) {
395 index_ = index;
396 }
397
398 void SetList(VertexAttribInfoList* new_list) {
399 DCHECK(new_list);
400
401 if (list_) {
402 list_->erase(it_);
403 }
404
405 it_ = new_list->insert(new_list->end(), this);
406 list_ = new_list;
407 }
408
409 // The index of this attrib.
410 GLuint index_;
411
[email protected]07f54fcc2009-12-22 02:46:30412 // Whether or not this attribute is enabled.
413 bool enabled_;
414
415 // number of components (1, 2, 3, 4)
416 GLint size_;
417
418 // GL_BYTE, GL_FLOAT, etc. See glVertexAttribPointer.
419 GLenum type_;
420
421 // The offset into the buffer.
422 GLsizei offset_;
423
[email protected]b1122982010-05-17 23:04:24424 GLboolean normalized_;
425
426 // The stride passed to glVertexAttribPointer.
427 GLsizei gl_stride_;
428
[email protected]07f54fcc2009-12-22 02:46:30429 // The stride that will be used to access the buffer. This is the actual
430 // stide, NOT the GL bogus stride. In other words there is never a stride
431 // of 0.
432 GLsizei real_stride_;
433
[email protected]b1122982010-05-17 23:04:24434 // The current value of the attrib.
435 Vec4 value_;
436
[email protected]3916c97e2010-02-25 03:20:50437 // The buffer bound to this attribute.
438 BufferManager::BufferInfo::Ref buffer_;
[email protected]f39f4b3f2010-05-12 17:04:08439
440 // List this info is on.
441 VertexAttribInfoList* list_;
442
443 // Iterator for list this info is on. Enabled/Disabled
444 VertexAttribInfoList::iterator it_;
[email protected]07f54fcc2009-12-22 02:46:30445 };
446
[email protected]f39f4b3f2010-05-12 17:04:08447 typedef std::list<VertexAttribInfo*> VertexAttribInfoList;
448
449 VertexAttribManager()
450 : max_vertex_attribs_(0) {
451 }
452
453 void Initialize(uint32 num_vertex_attribs);
454
455 bool Enable(GLuint index, bool enable);
456
457 const VertexAttribInfoList& GetEnabledVertexAttribInfos() const {
458 return enabled_vertex_attribs_;
459 }
460
461 VertexAttribInfo* GetVertexAttribInfo(GLuint index) {
[email protected]b1122982010-05-17 23:04:24462 if (index < max_vertex_attribs_) {
463 return &vertex_attrib_infos_[index];
464 }
465 return NULL;
[email protected]f39f4b3f2010-05-12 17:04:08466 }
467
468 private:
469 uint32 max_vertex_attribs_;
470
471 // Info for each vertex attribute saved so we can check at glDrawXXX time
472 // if it is safe to draw.
473 scoped_array<VertexAttribInfo> vertex_attrib_infos_;
474
475 // Lists for which vertex attribs are enabled, disabled.
476 VertexAttribInfoList enabled_vertex_attribs_;
477 VertexAttribInfoList disabled_vertex_attribs_;
478};
479
480bool VertexAttribManager::VertexAttribInfo::CanAccess(GLuint index) const {
481 if (!enabled_) {
482 return true;
483 }
484
485 if (!buffer_ || buffer_->IsDeleted()) {
486 return false;
487 }
488
489 // The number of elements that can be accessed.
490 GLsizeiptr buffer_size = buffer_->size();
491 if (offset_ > buffer_size || real_stride_ == 0) {
492 return false;
493 }
494
495 uint32 usable_size = buffer_size - offset_;
496 GLuint num_elements = usable_size / real_stride_ +
497 ((usable_size % real_stride_) >=
498 (GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type_) * size_) ? 1 : 0);
499 return index < num_elements;
500}
501
502
503void VertexAttribManager::Initialize(uint32 max_vertex_attribs) {
504 max_vertex_attribs_ = max_vertex_attribs;
505 vertex_attrib_infos_.reset(
506 new VertexAttribInfo[max_vertex_attribs]);
507 for (uint32 vv = 0; vv < max_vertex_attribs; ++vv) {
508 vertex_attrib_infos_[vv].set_index(vv);
509 vertex_attrib_infos_[vv].SetList(&disabled_vertex_attribs_);
510 }
511}
512
513bool VertexAttribManager::Enable(GLuint index, bool enable) {
514 if (index >= max_vertex_attribs_) {
515 return false;
516 }
517 VertexAttribInfo& info = vertex_attrib_infos_[index];
518 if (info.enabled() != enable) {
519 info.set_enabled(enable);
520 info.SetList(enable ? &enabled_vertex_attribs_ : &disabled_vertex_attribs_);
521 }
522 return true;
523}
524
525// This class implements GLES2Decoder so we don't have to expose all the GLES2
526// cmd stuff to outside this class.
527class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
528 public GLES2Decoder {
529 public:
530 explicit GLES2DecoderImpl(ContextGroup* group);
531
[email protected]96449d2c2009-11-25 00:01:32532 // Overridden from AsyncAPIInterface.
[email protected]f7a64ee2010-02-01 22:24:14533 virtual Error DoCommand(unsigned int command,
[email protected]3916c97e2010-02-25 03:20:50534 unsigned int arg_count,
535 const void* args);
[email protected]96449d2c2009-11-25 00:01:32536
537 // Overridden from AsyncAPIInterface.
538 virtual const char* GetCommandName(unsigned int command_id) const;
539
540 // Overridden from GLES2Decoder.
[email protected]5a6db6c2010-04-22 18:32:06541 virtual bool Initialize(gfx::GLContext* context,
[email protected]6217d392010-03-25 22:08:35542 const gfx::Size& size,
[email protected]d37231fa2010-04-09 21:16:02543 GLES2Decoder* parent,
[email protected]6217d392010-03-25 22:08:35544 uint32 parent_client_texture_id);
[email protected]96449d2c2009-11-25 00:01:32545 virtual void Destroy();
[email protected]6217d392010-03-25 22:08:35546 virtual void ResizeOffscreenFrameBuffer(const gfx::Size& size);
[email protected]c71caa82010-06-02 23:25:45547 virtual bool UpdateOffscreenFrameBufferSize();
[email protected]eb54a562010-01-20 21:55:18548 virtual bool MakeCurrent();
[email protected]56ac89b2010-03-17 21:16:55549 virtual GLES2Util* GetGLES2Util() { return &util_; }
[email protected]66791e382010-07-14 20:48:30550 virtual gfx::GLContext* GetGLContext() { return context_.get(); }
[email protected]43f28f832010-02-03 02:28:48551
552 virtual void SetSwapBuffersCallback(Callback0::Type* callback);
553
[email protected]8e3e0662010-08-23 18:46:30554 // Restores the current state to the user's settings.
555 void RestoreCurrentFramebufferBindings();
556 void RestoreCurrentRenderbufferBindings();
557 void RestoreCurrentTexture2DBindings();
558
[email protected]96449d2c2009-11-25 00:01:32559 private:
[email protected]6217d392010-03-25 22:08:35560 friend class ScopedGLErrorSuppressor;
[email protected]2f2d7042010-04-14 21:45:58561 friend class ScopedDefaultGLContext;
[email protected]6217d392010-03-25 22:08:35562 friend class RenderBuffer;
563 friend class FrameBuffer;
564
[email protected]3916c97e2010-02-25 03:20:50565 // State associated with each texture unit.
566 struct TextureUnit {
567 TextureUnit() : bind_target(GL_TEXTURE_2D) { }
568
569 // The last target that was bound to this texture unit.
570 GLenum bind_target;
571
572 // texture currently bound to this unit's GL_TEXTURE_2D with glBindTexture
573 TextureManager::TextureInfo::Ref bound_texture_2d;
574
575 // texture currently bound to this unit's GL_TEXTURE_CUBE_MAP with
576 // glBindTexture
577 TextureManager::TextureInfo::Ref bound_texture_cube_map;
578 };
579
[email protected]ae51d192010-04-27 00:48:03580 // Helpers for the glGen and glDelete functions.
581 bool GenTexturesHelper(GLsizei n, const GLuint* client_ids);
582 void DeleteTexturesHelper(GLsizei n, const GLuint* client_ids);
583 bool GenBuffersHelper(GLsizei n, const GLuint* client_ids);
584 void DeleteBuffersHelper(GLsizei n, const GLuint* client_ids);
585 bool GenFramebuffersHelper(GLsizei n, const GLuint* client_ids);
586 void DeleteFramebuffersHelper(GLsizei n, const GLuint* client_ids);
587 bool GenRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
588 void DeleteRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
[email protected]a93bb842010-02-16 23:03:47589
[email protected]3916c97e2010-02-25 03:20:50590 // TODO(gman): Cache these pointers?
[email protected]3916c97e2010-02-25 03:20:50591 BufferManager* buffer_manager() {
592 return group_->buffer_manager();
593 }
594
[email protected]a25fa872010-03-25 02:57:58595 RenderbufferManager* renderbuffer_manager() {
596 return group_->renderbuffer_manager();
597 }
598
599 FramebufferManager* framebuffer_manager() {
600 return group_->framebuffer_manager();
601 }
602
[email protected]3916c97e2010-02-25 03:20:50603 ProgramManager* program_manager() {
604 return group_->program_manager();
605 }
606
607 ShaderManager* shader_manager() {
608 return group_->shader_manager();
609 }
610
611 TextureManager* texture_manager() {
612 return group_->texture_manager();
613 }
614
[email protected]a93bb842010-02-16 23:03:47615 // Creates a TextureInfo for the given texture.
[email protected]ae51d192010-04-27 00:48:03616 TextureManager::TextureInfo* CreateTextureInfo(
617 GLuint client_id, GLuint service_id) {
618 return texture_manager()->CreateTextureInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47619 }
620
621 // Gets the texture info for the given texture. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03622 TextureManager::TextureInfo* GetTextureInfo(GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:50623 TextureManager::TextureInfo* info =
[email protected]ae51d192010-04-27 00:48:03624 texture_manager()->GetTextureInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:50625 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]a93bb842010-02-16 23:03:47626 }
627
628 // Deletes the texture info for the given texture.
[email protected]ae51d192010-04-27 00:48:03629 void RemoveTextureInfo(GLuint client_id) {
630 texture_manager()->RemoveTextureInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:50631 }
[email protected]a93bb842010-02-16 23:03:47632
[email protected]d37231fa2010-04-09 21:16:02633 // Get the size (in pixels) of the currently bound frame buffer (either FBO
634 // or regular back buffer).
[email protected]8e3e0662010-08-23 18:46:30635 gfx::Size GetBoundReadFrameBufferSize();
[email protected]d37231fa2010-04-09 21:16:02636
[email protected]a93bb842010-02-16 23:03:47637 // Wrapper for CompressedTexImage2D commands.
638 error::Error DoCompressedTexImage2D(
639 GLenum target,
640 GLint level,
641 GLenum internal_format,
642 GLsizei width,
643 GLsizei height,
644 GLint border,
645 GLsizei image_size,
646 const void* data);
647
[email protected]cadde4a2010-07-31 17:10:43648 // Wrapper for CompressedTexSubImage2D.
649 void DoCompressedTexSubImage2D(
650 GLenum target,
651 GLint level,
652 GLint xoffset,
653 GLint yoffset,
654 GLsizei width,
655 GLsizei height,
656 GLenum format,
657 GLsizei imageSize,
658 const void * data);
659
660 // Wrapper for CopyTexImage2D.
661 void DoCopyTexImage2D(
662 GLenum target,
663 GLint level,
664 GLenum internal_format,
665 GLint x,
666 GLint y,
667 GLsizei width,
668 GLsizei height,
669 GLint border);
670
671 // Wrapper for CopyTexSubImage2D.
672 void DoCopyTexSubImage2D(
673 GLenum target,
674 GLint level,
675 GLint xoffset,
676 GLint yoffset,
677 GLint x,
678 GLint y,
679 GLsizei width,
680 GLsizei height);
681
[email protected]a93bb842010-02-16 23:03:47682 // Wrapper for TexImage2D commands.
683 error::Error DoTexImage2D(
684 GLenum target,
685 GLint level,
686 GLenum internal_format,
687 GLsizei width,
688 GLsizei height,
689 GLint border,
690 GLenum format,
691 GLenum type,
692 const void* pixels,
693 uint32 pixels_size);
694
[email protected]cadde4a2010-07-31 17:10:43695 // Wrapper for TexSubImage2D.
696 void DoTexSubImage2D(
697 GLenum target,
698 GLint level,
699 GLint xoffset,
700 GLint yoffset,
701 GLsizei width,
702 GLsizei height,
703 GLenum format,
704 GLenum type,
705 const void * data);
706
[email protected]a93bb842010-02-16 23:03:47707 // Creates a ProgramInfo for the given program.
[email protected]ae51d192010-04-27 00:48:03708 void CreateProgramInfo(GLuint client_id, GLuint service_id) {
709 program_manager()->CreateProgramInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47710 }
711
[email protected]07f54fcc2009-12-22 02:46:30712 // Gets the program info for the given program. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03713 ProgramManager::ProgramInfo* GetProgramInfo(GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:50714 ProgramManager::ProgramInfo* info =
[email protected]ae51d192010-04-27 00:48:03715 program_manager()->GetProgramInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:50716 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]1d32bc82010-01-13 22:06:46717 }
[email protected]07f54fcc2009-12-22 02:46:30718
[email protected]6b8cf1a2010-05-06 16:13:58719 // Gets the program info for the given program. If it's not a program
720 // generates a GL error. Returns NULL if not program.
721 ProgramManager::ProgramInfo* GetProgramInfoNotShader(
722 GLuint client_id, const char* function_name) {
723 ProgramManager::ProgramInfo* info = GetProgramInfo(client_id);
724 if (!info) {
725 if (GetShaderInfo(client_id)) {
726 SetGLError(GL_INVALID_OPERATION,
727 (std::string(function_name) +
728 ": shader passed for program").c_str());
729 } else {
730 SetGLError(GL_INVALID_VALUE,
731 (std::string(function_name) + ": unknown program").c_str());
732 }
733 }
734 return info;
735 }
736
737
[email protected]07f54fcc2009-12-22 02:46:30738 // Deletes the program info for the given program.
[email protected]ae51d192010-04-27 00:48:03739 void RemoveProgramInfo(GLuint client_id) {
740 program_manager()->RemoveProgramInfo(client_id);
[email protected]1d32bc82010-01-13 22:06:46741 }
[email protected]07f54fcc2009-12-22 02:46:30742
[email protected]45bf5152010-02-12 00:11:31743 // Creates a ShaderInfo for the given shader.
[email protected]7cea56d92010-04-28 17:21:38744 void CreateShaderInfo(GLuint client_id,
745 GLuint service_id,
746 GLenum shader_type) {
747 shader_manager()->CreateShaderInfo(client_id, service_id, shader_type);
[email protected]45bf5152010-02-12 00:11:31748 }
749
750 // Gets the shader info for the given shader. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03751 ShaderManager::ShaderInfo* GetShaderInfo(GLuint client_id) {
752 ShaderManager::ShaderInfo* info =
753 shader_manager()->GetShaderInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:50754 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]45bf5152010-02-12 00:11:31755 }
756
[email protected]6b8cf1a2010-05-06 16:13:58757 // Gets the shader info for the given shader. If it's not a shader generates a
758 // GL error. Returns NULL if not shader.
759 ShaderManager::ShaderInfo* GetShaderInfoNotProgram(
760 GLuint client_id, const char* function_name) {
761 ShaderManager::ShaderInfo* info = GetShaderInfo(client_id);
762 if (!info) {
763 if (GetProgramInfo(client_id)) {
764 SetGLError(
765 GL_INVALID_OPERATION,
766 (std::string(function_name) +
767 ": program passed for shader").c_str());
768 } else {
769 SetGLError(GL_INVALID_VALUE,
770 (std::string(function_name) + ": unknown shader").c_str());
771 }
772 }
773 return info;
774 }
775
[email protected]45bf5152010-02-12 00:11:31776 // Deletes the shader info for the given shader.
[email protected]ae51d192010-04-27 00:48:03777 void RemoveShaderInfo(GLuint client_id) {
778 shader_manager()->RemoveShaderInfo(client_id);
[email protected]45bf5152010-02-12 00:11:31779 }
780
[email protected]a93bb842010-02-16 23:03:47781 // Creates a buffer info for the given buffer.
[email protected]ae51d192010-04-27 00:48:03782 void CreateBufferInfo(GLuint client_id, GLuint service_id) {
783 return buffer_manager()->CreateBufferInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47784 }
785
[email protected]07f54fcc2009-12-22 02:46:30786 // Gets the buffer info for the given buffer.
[email protected]ae51d192010-04-27 00:48:03787 BufferManager::BufferInfo* GetBufferInfo(GLuint client_id) {
788 BufferManager::BufferInfo* info =
789 buffer_manager()->GetBufferInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:50790 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]1d32bc82010-01-13 22:06:46791 }
[email protected]07f54fcc2009-12-22 02:46:30792
[email protected]a93bb842010-02-16 23:03:47793 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
794 // on glDeleteBuffers so we can make sure the user does not try to render
795 // with deleted buffers.
[email protected]ae51d192010-04-27 00:48:03796 void RemoveBufferInfo(GLuint client_id);
[email protected]a93bb842010-02-16 23:03:47797
[email protected]a25fa872010-03-25 02:57:58798 // Creates a framebuffer info for the given framebuffer.
[email protected]ae51d192010-04-27 00:48:03799 void CreateFramebufferInfo(GLuint client_id, GLuint service_id) {
800 return framebuffer_manager()->CreateFramebufferInfo(client_id, service_id);
[email protected]a25fa872010-03-25 02:57:58801 }
802
803 // Gets the framebuffer info for the given framebuffer.
804 FramebufferManager::FramebufferInfo* GetFramebufferInfo(
[email protected]ae51d192010-04-27 00:48:03805 GLuint client_id) {
[email protected]a25fa872010-03-25 02:57:58806 FramebufferManager::FramebufferInfo* info =
[email protected]ae51d192010-04-27 00:48:03807 framebuffer_manager()->GetFramebufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58808 return (info && !info->IsDeleted()) ? info : NULL;
809 }
810
811 // Removes the framebuffer info for the given framebuffer.
[email protected]ae51d192010-04-27 00:48:03812 void RemoveFramebufferInfo(GLuint client_id) {
813 framebuffer_manager()->RemoveFramebufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58814 }
815
816 // Creates a renderbuffer info for the given renderbuffer.
[email protected]ae51d192010-04-27 00:48:03817 void CreateRenderbufferInfo(GLuint client_id, GLuint service_id) {
818 return renderbuffer_manager()->CreateRenderbufferInfo(
819 client_id, service_id);
[email protected]a25fa872010-03-25 02:57:58820 }
821
822 // Gets the renderbuffer info for the given renderbuffer.
823 RenderbufferManager::RenderbufferInfo* GetRenderbufferInfo(
[email protected]ae51d192010-04-27 00:48:03824 GLuint client_id) {
[email protected]a25fa872010-03-25 02:57:58825 RenderbufferManager::RenderbufferInfo* info =
[email protected]ae51d192010-04-27 00:48:03826 renderbuffer_manager()->GetRenderbufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58827 return (info && !info->IsDeleted()) ? info : NULL;
828 }
829
830 // Removes the renderbuffer info for the given renderbuffer.
[email protected]ae51d192010-04-27 00:48:03831 void RemoveRenderbufferInfo(GLuint client_id) {
832 renderbuffer_manager()->RemoveRenderbufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58833 }
834
[email protected]558847a2010-03-24 07:02:54835 error::Error GetAttribLocationHelper(
836 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
837 const std::string& name_str);
838
839 error::Error GetUniformLocationHelper(
840 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
841 const std::string& name_str);
842
[email protected]3916c97e2010-02-25 03:20:50843 // Helper for glShaderSource.
844 error::Error ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:03845 GLuint client_id, const char* data, uint32 data_size);
[email protected]07f54fcc2009-12-22 02:46:30846
[email protected]3a2e7c7b2010-08-06 01:12:28847 // Clears any uncleared render buffers attached to the given frame buffer.
[email protected]8e3e0662010-08-23 18:46:30848 void ClearUnclearedRenderbuffers(
849 GLenum target, FramebufferManager::FramebufferInfo* info);
[email protected]3a2e7c7b2010-08-06 01:12:28850
851 // Remembers the state of some capabilities.
852 void SetCapabilityState(GLenum cap, bool enabled);
853
[email protected]939e7362010-05-13 20:49:10854 // Checks if the current program exists and is valid. If not generates the
855 // appropriate GL error. Returns true if the current program is in a usable
856 // state.
857 bool CheckCurrentProgram(const char* function_name);
858
859 // Checks if the current program exists and is valid and that location is not
860 // -1. If the current program is not valid generates the appropriate GL
861 // error. Returns true if the current program is in a usable state and
862 // location is not -1.
863 bool CheckCurrentProgramForUniform(GLint location, const char* function_name);
864
865 // Gets the type of a uniform for a location in the current program. Sets GL
866 // errors if the current program is not valid. Returns true if the current
867 // program is valid and the location exists.
868 bool GetUniformTypeByLocation(
869 GLint location, const char* function_name, GLenum* type);
870
[email protected]b273e432010-04-12 17:23:58871 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
872 bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
873
[email protected]96449d2c2009-11-25 00:01:32874 // Wrapper for glCreateProgram
[email protected]ae51d192010-04-27 00:48:03875 bool CreateProgramHelper(GLuint client_id);
[email protected]96449d2c2009-11-25 00:01:32876
877 // Wrapper for glCreateShader
[email protected]ae51d192010-04-27 00:48:03878 bool CreateShaderHelper(GLenum type, GLuint client_id);
[email protected]96449d2c2009-11-25 00:01:32879
[email protected]3916c97e2010-02-25 03:20:50880 // Wrapper for glActiveTexture
881 void DoActiveTexture(GLenum texture_unit);
882
[email protected]ae51d192010-04-27 00:48:03883 // Wrapper for glAttachShader
884 void DoAttachShader(GLuint client_program_id, GLint client_shader_id);
885
[email protected]96449d2c2009-11-25 00:01:32886 // Wrapper for glBindBuffer since we need to track the current targets.
887 void DoBindBuffer(GLenum target, GLuint buffer);
888
[email protected]86093972010-03-11 00:13:56889 // Wrapper for glBindFramebuffer since we need to track the current targets.
890 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
891
892 // Wrapper for glBindRenderbuffer since we need to track the current targets.
893 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
894
[email protected]a93bb842010-02-16 23:03:47895 // Wrapper for glBindTexture since we need to track the current targets.
896 void DoBindTexture(GLenum target, GLuint texture);
897
[email protected]8e3e0662010-08-23 18:46:30898 // Wrapper for glBlitFramebufferEXT.
899 void DoBlitFramebufferEXT(
900 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
901 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
902 GLbitfield mask, GLenum filter);
903
[email protected]36cef8ce2010-03-16 07:34:45904 // Wrapper for glBufferData.
[email protected]0c86dbf2010-03-05 08:14:11905 void DoBufferData(
906 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage);
907
[email protected]36cef8ce2010-03-16 07:34:45908 // Wrapper for glBufferSubData.
[email protected]0c86dbf2010-03-05 08:14:11909 void DoBufferSubData(
910 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
911
[email protected]36cef8ce2010-03-16 07:34:45912 // Wrapper for glCheckFramebufferStatus
913 GLenum DoCheckFramebufferStatus(GLenum target);
914
[email protected]3a2e7c7b2010-08-06 01:12:28915 // Wrappers for clear and mask settings functions.
916 void DoClearColor(
917 GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
918 void DoClearDepthf(GLclampf depth);
919 void DoClearStencil(GLint s);
920 void DoColorMask(
921 GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
922 void DoDepthMask(GLboolean depth);
923 void DoStencilMask(GLuint mask);
924 void DoStencilMaskSeparate(GLenum face, GLuint mask);
925
[email protected]45bf5152010-02-12 00:11:31926 // Wrapper for glCompileShader.
927 void DoCompileShader(GLuint shader);
928
[email protected]066849e32010-05-03 19:14:10929 // Helper for DeleteSharedIds commands.
930 void DoDeleteSharedIds(GLuint namespace_id, GLsizei n, const GLuint* ids);
931
[email protected]ae51d192010-04-27 00:48:03932 // Wrapper for glDetachShader
933 void DoDetachShader(GLuint client_program_id, GLint client_shader_id);
934
[email protected]07f54fcc2009-12-22 02:46:30935 // Wrapper for glDrawArrays.
936 void DoDrawArrays(GLenum mode, GLint first, GLsizei count);
937
[email protected]3a2e7c7b2010-08-06 01:12:28938 // Wrapper for glDisable
939 void DoDisable(GLenum cap);
940
[email protected]07f54fcc2009-12-22 02:46:30941 // Wrapper for glDisableVertexAttribArray.
942 void DoDisableVertexAttribArray(GLuint index);
943
[email protected]3a2e7c7b2010-08-06 01:12:28944 // Wrapper for glEnable
945 void DoEnable(GLenum cap);
946
[email protected]07f54fcc2009-12-22 02:46:30947 // Wrapper for glEnableVertexAttribArray.
948 void DoEnableVertexAttribArray(GLuint index);
949
[email protected]36cef8ce2010-03-16 07:34:45950 // Wrapper for glFramebufferRenderbufffer.
951 void DoFramebufferRenderbuffer(
952 GLenum target, GLenum attachment, GLenum renderbuffertarget,
953 GLuint renderbuffer);
954
955 // Wrapper for glFramebufferTexture2D.
956 void DoFramebufferTexture2D(
957 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
958 GLint level);
959
[email protected]a93bb842010-02-16 23:03:47960 // Wrapper for glGenerateMipmap
961 void DoGenerateMipmap(GLenum target);
962
[email protected]066849e32010-05-03 19:14:10963 // Helper for GenSharedIds commands.
964 void DoGenSharedIds(
965 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids);
966
[email protected]b273e432010-04-12 17:23:58967 // Wrapper for DoGetBooleanv.
968 void DoGetBooleanv(GLenum pname, GLboolean* params);
969
970 // Wrapper for DoGetFloatv.
971 void DoGetFloatv(GLenum pname, GLfloat* params);
972
[email protected]36cef8ce2010-03-16 07:34:45973 // Wrapper for glGetFramebufferAttachmentParameteriv.
974 void DoGetFramebufferAttachmentParameteriv(
975 GLenum target, GLenum attachment, GLenum pname, GLint* params);
976
[email protected]a0c3e972010-04-21 00:49:13977 // Wrapper for glGetIntegerv.
[email protected]b273e432010-04-12 17:23:58978 void DoGetIntegerv(GLenum pname, GLint* params);
979
[email protected]29a9eb52010-04-13 09:04:23980 // Gets the max value in a range in a buffer.
981 GLuint DoGetMaxValueInBuffer(
982 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset);
983
[email protected]a0c3e972010-04-21 00:49:13984 // Wrapper for glGetProgramiv.
985 void DoGetProgramiv(
986 GLuint program_id, GLenum pname, GLint* params);
987
[email protected]36cef8ce2010-03-16 07:34:45988 // Wrapper for glRenderbufferParameteriv.
989 void DoGetRenderbufferParameteriv(
990 GLenum target, GLenum pname, GLint* params);
991
[email protected]ddd968b82010-03-02 00:44:29992 // Wrapper for glGetShaderiv
993 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
994
[email protected]b1122982010-05-17 23:04:24995 // Wrappers for glGetVertexAttrib.
996 void DoGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params);
997 void DoGetVertexAttribiv(GLuint index, GLenum pname, GLint *params);
998
[email protected]1958e0e2010-04-22 05:17:15999 // Wrappers for glIsXXX functions.
1000 bool DoIsBuffer(GLuint client_id);
1001 bool DoIsFramebuffer(GLuint client_id);
1002 bool DoIsProgram(GLuint client_id);
1003 bool DoIsRenderbuffer(GLuint client_id);
1004 bool DoIsShader(GLuint client_id);
1005 bool DoIsTexture(GLuint client_id);
1006
[email protected]07f54fcc2009-12-22 02:46:301007 // Wrapper for glLinkProgram
1008 void DoLinkProgram(GLuint program);
1009
[email protected]066849e32010-05-03 19:14:101010 // Helper for RegisterSharedIds.
1011 void DoRegisterSharedIds(GLuint namespace_id, GLsizei n, const GLuint* ids);
1012
[email protected]36cef8ce2010-03-16 07:34:451013 // Wrapper for glRenderbufferStorage.
1014 void DoRenderbufferStorage(
[email protected]ae51d192010-04-27 00:48:031015 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
[email protected]36cef8ce2010-03-16 07:34:451016
[email protected]8e3e0662010-08-23 18:46:301017 // Wrapper for glRenderbufferStorageMultisampleEXT.
1018 void DoRenderbufferStorageMultisample(
1019 GLenum target, GLsizei samples, GLenum internalformat,
1020 GLsizei width, GLsizei height);
1021
[email protected]b273e432010-04-12 17:23:581022 // Wrapper for glReleaseShaderCompiler.
1023 void DoReleaseShaderCompiler() { }
1024
[email protected]3916c97e2010-02-25 03:20:501025 // Wrappers for glTexParameter functions.
1026 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
1027 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
1028 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
1029 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
1030
1031 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1032 // spec only these 2 functions can be used to set sampler uniforms.
1033 void DoUniform1i(GLint location, GLint v0);
[email protected]939e7362010-05-13 20:49:101034 void DoUniform1iv(GLint location, GLsizei count, const GLint* value);
1035
1036 // Wrappers for glUniformfv because some drivers don't correctly accept
1037 // bool uniforms.
1038 void DoUniform1fv(GLint location, GLsizei count, const GLfloat* value);
1039 void DoUniform2fv(GLint location, GLsizei count, const GLfloat* value);
1040 void DoUniform3fv(GLint location, GLsizei count, const GLfloat* value);
1041 void DoUniform4fv(GLint location, GLsizei count, const GLfloat* value);
[email protected]3916c97e2010-02-25 03:20:501042
[email protected]b1122982010-05-17 23:04:241043 // Wrappers for glVertexAttrib??
1044 void DoVertexAttrib1f(GLuint index, GLfloat v0);
1045 void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
1046 void DoVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
1047 void DoVertexAttrib4f(
1048 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
1049 void DoVertexAttrib1fv(GLuint index, const GLfloat *v);
1050 void DoVertexAttrib2fv(GLuint index, const GLfloat *v);
1051 void DoVertexAttrib3fv(GLuint index, const GLfloat *v);
1052 void DoVertexAttrib4fv(GLuint index, const GLfloat *v);
1053
[email protected]07f54fcc2009-12-22 02:46:301054 // Wrapper for glUseProgram
1055 void DoUseProgram(GLuint program);
1056
[email protected]ae51d192010-04-27 00:48:031057 // Wrapper for glValidateProgram.
1058 void DoValidateProgram(GLuint program_client_id);
1059
[email protected]4e8a5b122010-05-08 22:00:101060 // Gets the number of values that will be returned by glGetXXX. Returns
1061 // false if pname is unknown.
1062 bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
1063
[email protected]96449d2c2009-11-25 00:01:321064 // Gets the GLError through our wrapper.
1065 GLenum GetGLError();
1066
1067 // Sets our wrapper for the GLError.
[email protected]8eee29c2010-04-29 03:38:291068 void SetGLError(GLenum error, const char* msg);
[email protected]96449d2c2009-11-25 00:01:321069
[email protected]07f54fcc2009-12-22 02:46:301070 // Copies the real GL errors to the wrapper. This is so we can
1071 // make sure there are no native GL errors before calling some GL function
1072 // so that on return we know any error generated was for that specific
1073 // command.
1074 void CopyRealGLErrorsToWrapper();
1075
[email protected]6217d392010-03-25 22:08:351076 // Clear all real GL errors. This is to prevent the client from seeing any
1077 // errors caused by GL calls that it was not responsible for issuing.
1078 void ClearRealGLErrors();
1079
[email protected]07f54fcc2009-12-22 02:46:301080 // Checks if the current program and vertex attributes are valid for drawing.
1081 bool IsDrawValid(GLuint max_vertex_accessed);
1082
[email protected]b1122982010-05-17 23:04:241083 // Returns true if attrib0 was simulated.
1084 bool SimulateAttrib0(GLuint max_vertex_accessed);
1085 void RestoreStateForSimulatedAttrib0();
1086
[email protected]ef526492010-06-02 23:12:251087 // Returns true if textures were set.
1088 bool SetBlackTextureForNonRenderableTextures();
[email protected]3916c97e2010-02-25 03:20:501089 void RestoreStateForNonRenderableTextures();
1090
[email protected]07f54fcc2009-12-22 02:46:301091 // Gets the buffer id for a given target.
[email protected]3916c97e2010-02-25 03:20:501092 BufferManager::BufferInfo* GetBufferInfoForTarget(GLenum target) {
[email protected]07f54fcc2009-12-22 02:46:301093 DCHECK(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER);
[email protected]3916c97e2010-02-25 03:20:501094 BufferManager::BufferInfo* info = target == GL_ARRAY_BUFFER ?
1095 bound_array_buffer_ : bound_element_array_buffer_;
1096 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]07f54fcc2009-12-22 02:46:301097 }
1098
[email protected]a93bb842010-02-16 23:03:471099 // Gets the texture id for a given target.
[email protected]3916c97e2010-02-25 03:20:501100 TextureManager::TextureInfo* GetTextureInfoForTarget(GLenum target) {
1101 TextureUnit& unit = texture_units_[active_texture_unit_];
1102 TextureManager::TextureInfo* info = NULL;
[email protected]a93bb842010-02-16 23:03:471103 switch (target) {
1104 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:501105 info = unit.bound_texture_2d;
1106 break;
[email protected]a93bb842010-02-16 23:03:471107 case GL_TEXTURE_CUBE_MAP:
1108 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1109 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1110 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1111 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1112 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1113 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
[email protected]3916c97e2010-02-25 03:20:501114 info = unit.bound_texture_cube_map;
1115 break;
[email protected]1aef98132010-02-23 18:00:071116 // Note: If we ever support TEXTURE_RECTANGLE as a target, be sure to
1117 // track |texture_| with the currently bound TEXTURE_RECTANGLE texture,
1118 // because |texture_| is used by the FBO rendering mechanism for readback
1119 // to the bits that get sent to the browser.
[email protected]a93bb842010-02-16 23:03:471120 default:
1121 NOTREACHED();
[email protected]3916c97e2010-02-25 03:20:501122 return NULL;
[email protected]a93bb842010-02-16 23:03:471123 }
[email protected]3916c97e2010-02-25 03:20:501124 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]a93bb842010-02-16 23:03:471125 }
1126
[email protected]8e3e0662010-08-23 18:46:301127 // Gets the framebuffer info for a particular target.
1128 FramebufferManager::FramebufferInfo* GetFramebufferInfoForTarget(
1129 GLenum target) {
1130 FramebufferManager::FramebufferInfo* info = NULL;
1131 switch (target) {
1132 case GL_FRAMEBUFFER:
1133 case GL_DRAW_FRAMEBUFFER:
1134 info = bound_draw_framebuffer_;
1135 break;
1136 case GL_READ_FRAMEBUFFER:
1137 info = bound_read_framebuffer_;
1138 break;
1139 default:
1140 NOTREACHED();
1141 break;
1142 }
1143 return (info && !info->IsDeleted()) ? info : NULL;
1144 }
1145
[email protected]f7b85372010-02-03 01:11:371146 // Validates the program and location for a glGetUniform call and returns
1147 // a SizeResult setup to receive the result. Returns true if glGetUniform
1148 // should be called.
1149 bool GetUniformSetup(
1150 GLuint program, GLint location,
1151 uint32 shm_id, uint32 shm_offset,
[email protected]939e7362010-05-13 20:49:101152 error::Error* error, GLuint* service_id, void** result,
1153 GLenum* result_type);
[email protected]f7b85372010-02-03 01:11:371154
[email protected]96449d2c2009-11-25 00:01:321155 // Generate a member function prototype for each command in an automated and
1156 // typesafe way.
1157 #define GLES2_CMD_OP(name) \
[email protected]f7a64ee2010-02-01 22:24:141158 Error Handle ## name( \
[email protected]b9849abf2009-11-25 19:13:191159 uint32 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:321160 const gles2::name& args); \
1161
1162 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1163
1164 #undef GLES2_CMD_OP
1165
[email protected]2f2d7042010-04-14 21:45:581166 // The GL context this decoder renders to on behalf of the client.
[email protected]66791e382010-07-14 20:48:301167 scoped_ptr<gfx::GLContext> context_;
[email protected]d37231fa2010-04-09 21:16:021168
[email protected]2f2d7042010-04-14 21:45:581169 // A GLContext that is kept in its default state. It is used to perform
1170 // operations that should not be dependent on client set GLContext state, like
1171 // clearing a render buffer when it is created.
1172 // TODO(apatrick): Decoders in the same ContextGroup could potentially share
1173 // the same default GL context.
[email protected]5a6db6c2010-04-22 18:32:061174 scoped_ptr<gfx::GLContext> default_context_;
[email protected]2f2d7042010-04-14 21:45:581175
[email protected]6217d392010-03-25 22:08:351176 // A parent decoder can access this decoders saved offscreen frame buffer.
1177 // The parent pointer is reset if the parent is destroyed.
1178 base::WeakPtr<GLES2DecoderImpl> parent_;
1179
1180 // Width and height to which an offscreen frame buffer should be resized on
1181 // the next call to SwapBuffers.
[email protected]d37231fa2010-04-09 21:16:021182 gfx::Size pending_offscreen_size_;
[email protected]6217d392010-03-25 22:08:351183
[email protected]96449d2c2009-11-25 00:01:321184 // Current GL error bits.
1185 uint32 error_bits_;
1186
[email protected]96449d2c2009-11-25 00:01:321187 // Util to help with GL.
1188 GLES2Util util_;
1189
1190 // pack alignment as last set by glPixelStorei
1191 GLint pack_alignment_;
1192
1193 // unpack alignment as last set by glPixelStorei
1194 GLint unpack_alignment_;
1195
1196 // The currently bound array buffer. If this is 0 it is illegal to call
1197 // glVertexAttribPointer.
[email protected]3916c97e2010-02-25 03:20:501198 BufferManager::BufferInfo::Ref bound_array_buffer_;
[email protected]96449d2c2009-11-25 00:01:321199
1200 // The currently bound element array buffer. If this is 0 it is illegal
1201 // to call glDrawElements.
[email protected]3916c97e2010-02-25 03:20:501202 BufferManager::BufferInfo::Ref bound_element_array_buffer_;
[email protected]07f54fcc2009-12-22 02:46:301203
[email protected]f39f4b3f2010-05-12 17:04:081204 // Class that manages vertex attribs.
1205 VertexAttribManager vertex_attrib_manager_;
[email protected]07f54fcc2009-12-22 02:46:301206
[email protected]b1122982010-05-17 23:04:241207 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1208 GLuint attrib_0_buffer_id_;
1209
1210 // The value currently in attrib_0.
1211 VertexAttribManager::VertexAttribInfo::Vec4 attrib_0_value_;
1212
1213 // The size of attrib 0.
1214 GLsizei attrib_0_size_;
1215
[email protected]3916c97e2010-02-25 03:20:501216 // Current active texture by 0 - n index.
1217 // In other words, if we call glActiveTexture(GL_TEXTURE2) this value would
1218 // be 2.
1219 GLuint active_texture_unit_;
[email protected]07f54fcc2009-12-22 02:46:301220
[email protected]3916c97e2010-02-25 03:20:501221 // Which textures are bound to texture units through glActiveTexture.
1222 scoped_array<TextureUnit> texture_units_;
[email protected]a93bb842010-02-16 23:03:471223
[email protected]3a2e7c7b2010-08-06 01:12:281224 // state saved for clearing so we can clear render buffers and then
1225 // restore to these values.
1226 GLclampf clear_red_;
1227 GLclampf clear_green_;
1228 GLclampf clear_blue_;
1229 GLclampf clear_alpha_;
1230 GLboolean mask_red_;
1231 GLboolean mask_green_;
1232 GLboolean mask_blue_;
1233 GLboolean mask_alpha_;
1234 GLint clear_stencil_;
1235 GLuint mask_stencil_front_;
1236 GLuint mask_stencil_back_;
1237 GLclampf clear_depth_;
1238 GLboolean mask_depth_;
1239 bool enable_scissor_test_;
1240
[email protected]1d32bc82010-01-13 22:06:461241 // The program in use by glUseProgram
[email protected]3916c97e2010-02-25 03:20:501242 ProgramManager::ProgramInfo::Ref current_program_;
[email protected]07f54fcc2009-12-22 02:46:301243
[email protected]8e3e0662010-08-23 18:46:301244 // The currently bound framebuffers
1245 FramebufferManager::FramebufferInfo::Ref bound_read_framebuffer_;
1246 FramebufferManager::FramebufferInfo::Ref bound_draw_framebuffer_;
[email protected]86093972010-03-11 00:13:561247
1248 // The currently bound renderbuffer
[email protected]051b1372010-04-12 02:42:081249 RenderbufferManager::RenderbufferInfo::Ref bound_renderbuffer_;
[email protected]86093972010-03-11 00:13:561250
[email protected]96449d2c2009-11-25 00:01:321251 bool anti_aliased_;
1252
[email protected]b9363b22010-06-09 22:06:151253 // The offscreen frame buffer that the client renders to. With EGL, the
1254 // depth and stencil buffers are separate. With regular GL there is a single
1255 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1256 // offscreen_target_stencil_render_buffer_ is unused.
[email protected]6217d392010-03-25 22:08:351257 scoped_ptr<FrameBuffer> offscreen_target_frame_buffer_;
1258 scoped_ptr<Texture> offscreen_target_color_texture_;
[email protected]b9363b22010-06-09 22:06:151259 scoped_ptr<RenderBuffer> offscreen_target_depth_render_buffer_;
1260 scoped_ptr<RenderBuffer> offscreen_target_stencil_render_buffer_;
[email protected]6217d392010-03-25 22:08:351261
1262 // The copy that is saved when SwapBuffers is called.
1263 scoped_ptr<Texture> offscreen_saved_color_texture_;
1264
[email protected]43f28f832010-02-03 02:28:481265 scoped_ptr<Callback0::Type> swap_buffers_callback_;
1266
[email protected]8eee29c2010-04-29 03:38:291267 // The last error message set.
1268 std::string last_error_;
1269
[email protected]b1d2dcb2010-05-17 19:24:181270 bool use_shader_translator_;
[email protected]f517cc842010-08-25 19:13:401271 ShHandle vertex_compiler_;
1272 ShHandle fragment_compiler_;
[email protected]b1d2dcb2010-05-17 19:24:181273
[email protected]9438b012010-06-15 22:55:051274 // Cached from the context group.
1275 const Validators* validators_;
1276
[email protected]876f6fee2010-08-02 23:10:321277 // Supported extensions.
1278 bool depth24_stencil8_oes_supported_;
1279
[email protected]96449d2c2009-11-25 00:01:321280 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
1281};
1282
[email protected]6217d392010-03-25 22:08:351283ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(GLES2DecoderImpl* decoder)
1284 : decoder_(decoder) {
1285 decoder_->CopyRealGLErrorsToWrapper();
1286}
1287
1288ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
1289 decoder_->ClearRealGLErrors();
1290}
1291
1292ScopedTexture2DBinder::ScopedTexture2DBinder(GLES2DecoderImpl* decoder,
1293 GLuint id)
1294 : decoder_(decoder) {
1295 ScopedGLErrorSuppressor suppressor(decoder_);
1296
1297 // TODO(apatrick): Check if there are any other states that need to be reset
1298 // before binding a new texture.
1299 glActiveTexture(GL_TEXTURE0);
1300 glBindTexture(GL_TEXTURE_2D, id);
1301}
1302
1303ScopedTexture2DBinder::~ScopedTexture2DBinder() {
1304 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301305 decoder_->RestoreCurrentTexture2DBindings();
[email protected]6217d392010-03-25 22:08:351306}
1307
1308ScopedRenderBufferBinder::ScopedRenderBufferBinder(GLES2DecoderImpl* decoder,
1309 GLuint id)
1310 : decoder_(decoder) {
1311 ScopedGLErrorSuppressor suppressor(decoder_);
1312 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
1313}
1314
1315ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
1316 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301317 decoder_->RestoreCurrentRenderbufferBindings();
[email protected]6217d392010-03-25 22:08:351318}
1319
1320ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
1321 GLuint id)
1322 : decoder_(decoder) {
1323 ScopedGLErrorSuppressor suppressor(decoder_);
1324 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
1325}
1326
1327ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
1328 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301329 decoder_->RestoreCurrentFramebufferBindings();
[email protected]6217d392010-03-25 22:08:351330}
1331
[email protected]2f2d7042010-04-14 21:45:581332ScopedDefaultGLContext::ScopedDefaultGLContext(GLES2DecoderImpl* decoder)
1333 : decoder_(decoder) {
1334 decoder_->default_context_->MakeCurrent();
1335}
1336
1337ScopedDefaultGLContext::~ScopedDefaultGLContext() {
1338 decoder_->context_->MakeCurrent();
1339}
1340
[email protected]6217d392010-03-25 22:08:351341Texture::Texture(GLES2DecoderImpl* decoder)
1342 : decoder_(decoder),
1343 id_(0) {
1344}
1345
1346Texture::~Texture() {
1347 // This does not destroy the render texture because that would require that
1348 // the associated GL context was current. Just check that it was explicitly
1349 // destroyed.
1350 DCHECK_EQ(id_, 0u);
1351}
1352
1353void Texture::Create() {
1354 ScopedGLErrorSuppressor suppressor(decoder_);
1355 Destroy();
1356 glGenTextures(1, &id_);
1357}
1358
1359bool Texture::AllocateStorage(const gfx::Size& size) {
1360 DCHECK_NE(id_, 0u);
1361 ScopedGLErrorSuppressor suppressor(decoder_);
1362 ScopedTexture2DBinder binder(decoder_, id_);
1363 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1364 glTexParameteri(
1365 GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1366 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1367 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
[email protected]6217d392010-03-25 22:08:351368
1369 glTexImage2D(GL_TEXTURE_2D,
1370 0, // mip level
1371 GL_RGBA,
1372 size.width(),
1373 size.height(),
1374 0, // border
1375 GL_RGBA,
1376 GL_UNSIGNED_BYTE,
1377 NULL);
1378
[email protected]d37231fa2010-04-09 21:16:021379 size_ = size;
1380
[email protected]6217d392010-03-25 22:08:351381 return glGetError() == GL_NO_ERROR;
1382}
1383
1384void Texture::Copy(const gfx::Size& size) {
1385 DCHECK_NE(id_, 0u);
1386 ScopedGLErrorSuppressor suppressor(decoder_);
1387 ScopedTexture2DBinder binder(decoder_, id_);
1388 glCopyTexImage2D(GL_TEXTURE_2D,
1389 0, // level
1390 GL_RGBA,
1391 0, 0,
1392 size.width(),
1393 size.height(),
1394 0); // border
1395}
1396
1397void Texture::Destroy() {
1398 if (id_ != 0) {
1399 ScopedGLErrorSuppressor suppressor(decoder_);
1400 glDeleteTextures(1, &id_);
1401 id_ = 0;
1402 }
1403}
1404
1405RenderBuffer::RenderBuffer(GLES2DecoderImpl* decoder)
1406 : decoder_(decoder),
1407 id_(0) {
1408}
1409
1410RenderBuffer::~RenderBuffer() {
1411 // This does not destroy the render buffer because that would require that
1412 // the associated GL context was current. Just check that it was explicitly
1413 // destroyed.
1414 DCHECK_EQ(id_, 0u);
1415}
1416
1417void RenderBuffer::Create() {
1418 ScopedGLErrorSuppressor suppressor(decoder_);
1419 Destroy();
1420 glGenRenderbuffersEXT(1, &id_);
1421}
1422
1423bool RenderBuffer::AllocateStorage(const gfx::Size& size, GLenum format) {
1424 ScopedGLErrorSuppressor suppressor(decoder_);
1425 ScopedRenderBufferBinder binder(decoder_, id_);
1426 glRenderbufferStorageEXT(GL_RENDERBUFFER,
1427 format,
1428 size.width(),
1429 size.height());
1430 return glGetError() == GL_NO_ERROR;
1431}
1432
1433void RenderBuffer::Destroy() {
1434 if (id_ != 0) {
1435 ScopedGLErrorSuppressor suppressor(decoder_);
1436 glDeleteRenderbuffersEXT(1, &id_);
1437 id_ = 0;
1438 }
1439}
1440
1441FrameBuffer::FrameBuffer(GLES2DecoderImpl* decoder)
1442 : decoder_(decoder),
1443 id_(0) {
1444}
1445
1446FrameBuffer::~FrameBuffer() {
1447 // This does not destroy the frame buffer because that would require that
1448 // the associated GL context was current. Just check that it was explicitly
1449 // destroyed.
1450 DCHECK_EQ(id_, 0u);
1451}
1452
1453void FrameBuffer::Create() {
1454 ScopedGLErrorSuppressor suppressor(decoder_);
1455 Destroy();
1456 glGenFramebuffersEXT(1, &id_);
1457}
1458
1459void FrameBuffer::AttachRenderTexture(Texture* texture) {
1460 DCHECK_NE(id_, 0u);
1461 ScopedGLErrorSuppressor suppressor(decoder_);
1462 ScopedFrameBufferBinder binder(decoder_, id_);
1463 GLuint attach_id = texture ? texture->id() : 0;
1464 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
1465 GL_COLOR_ATTACHMENT0,
1466 GL_TEXTURE_2D,
1467 attach_id,
1468 0);
1469}
1470
[email protected]b9363b22010-06-09 22:06:151471void FrameBuffer::AttachRenderBuffer(GLenum target,
1472 RenderBuffer* render_buffer) {
[email protected]6217d392010-03-25 22:08:351473 DCHECK_NE(id_, 0u);
1474 ScopedGLErrorSuppressor suppressor(decoder_);
1475 ScopedFrameBufferBinder binder(decoder_, id_);
1476 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
1477 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
[email protected]b9363b22010-06-09 22:06:151478 target,
[email protected]6217d392010-03-25 22:08:351479 GL_RENDERBUFFER,
1480 attach_id);
1481}
1482
1483void FrameBuffer::Clear(GLbitfield buffers) {
1484 ScopedGLErrorSuppressor suppressor(decoder_);
1485 ScopedFrameBufferBinder binder(decoder_, id_);
1486 glClear(buffers);
1487}
1488
1489void FrameBuffer::Destroy() {
1490 if (id_ != 0) {
1491 ScopedGLErrorSuppressor suppressor(decoder_);
1492 glDeleteFramebuffersEXT(1, &id_);
1493 id_ = 0;
1494 }
1495}
1496
1497GLenum FrameBuffer::CheckStatus() {
1498 DCHECK_NE(id_, 0u);
1499 ScopedGLErrorSuppressor suppressor(decoder_);
1500 ScopedFrameBufferBinder binder(decoder_, id_);
1501 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
1502}
1503
[email protected]3916c97e2010-02-25 03:20:501504GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
1505 return new GLES2DecoderImpl(group);
[email protected]96449d2c2009-11-25 00:01:321506}
1507
[email protected]3916c97e2010-02-25 03:20:501508GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
1509 : GLES2Decoder(group),
[email protected]96449d2c2009-11-25 00:01:321510 error_bits_(0),
1511 util_(0), // TODO(gman): Set to actual num compress texture formats.
1512 pack_alignment_(4),
1513 unpack_alignment_(4),
[email protected]b1122982010-05-17 23:04:241514 attrib_0_buffer_id_(0),
1515 attrib_0_size_(0),
[email protected]3916c97e2010-02-25 03:20:501516 active_texture_unit_(0),
[email protected]3a2e7c7b2010-08-06 01:12:281517 clear_red_(0),
1518 clear_green_(0),
1519 clear_blue_(0),
1520 clear_alpha_(0),
1521 mask_red_(true),
1522 mask_green_(true),
1523 mask_blue_(true),
1524 mask_alpha_(true),
1525 clear_stencil_(0),
1526 mask_stencil_front_(-1),
1527 mask_stencil_back_(-1),
1528 clear_depth_(1.0f),
1529 mask_depth_(true),
1530 enable_scissor_test_(false),
[email protected]b1d2dcb2010-05-17 19:24:181531 anti_aliased_(false),
[email protected]9438b012010-06-15 22:55:051532 use_shader_translator_(true),
[email protected]5236b752010-07-27 18:02:231533 vertex_compiler_(NULL),
1534 fragment_compiler_(NULL),
[email protected]876f6fee2010-08-02 23:10:321535 validators_(group->validators()),
1536 depth24_stencil8_oes_supported_(false) {
[email protected]b1122982010-05-17 23:04:241537 attrib_0_value_.v[0] = 0.0f;
1538 attrib_0_value_.v[1] = 0.0f;
1539 attrib_0_value_.v[2] = 0.0f;
1540 attrib_0_value_.v[3] = 1.0f;
[email protected]b9363b22010-06-09 22:06:151541
1542 // The shader translator is not needed for EGL because it already uses the
1543 // GLSL ES syntax. It is translated for the unit tests because
1544 // GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes the empty
1545 // string to CompileShader and this is not a valid shader. TODO(apatrick):
1546 // fix this test.
1547 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 ||
1548 gfx::GetGLImplementation() == gfx::kGLImplementationMockGL) {
1549 use_shader_translator_ = false;
1550 }
[email protected]96449d2c2009-11-25 00:01:321551}
1552
[email protected]5a6db6c2010-04-22 18:32:061553bool GLES2DecoderImpl::Initialize(gfx::GLContext* context,
[email protected]6217d392010-03-25 22:08:351554 const gfx::Size& size,
[email protected]d37231fa2010-04-09 21:16:021555 GLES2Decoder* parent,
[email protected]6217d392010-03-25 22:08:351556 uint32 parent_client_texture_id) {
[email protected]4bedba72010-04-20 22:08:541557 DCHECK(context);
[email protected]66791e382010-07-14 20:48:301558 DCHECK(!context_.get());
1559
1560 // Take ownership of the GLContext.
1561 context_.reset(context);
[email protected]d37231fa2010-04-09 21:16:021562
[email protected]2f2d7042010-04-14 21:45:581563 // Create a GL context that is kept in a default state and shares a namespace
1564 // with the main GL context.
[email protected]66791e382010-07-14 20:48:301565 default_context_.reset(gfx::GLContext::CreateOffscreenGLContext(
1566 context_.get()));
[email protected]4bedba72010-04-20 22:08:541567 if (!default_context_.get()) {
[email protected]2f2d7042010-04-14 21:45:581568 Destroy();
1569 return false;
1570 }
1571
[email protected]6217d392010-03-25 22:08:351572 // Keep only a weak pointer to the parent so we don't unmap its client
[email protected]d37231fa2010-04-09 21:16:021573 // frame buffer after it has been destroyed.
[email protected]6217d392010-03-25 22:08:351574 if (parent)
1575 parent_ = static_cast<GLES2DecoderImpl*>(parent)->AsWeakPtr();
1576
[email protected]246a70452010-03-05 21:53:501577 if (!MakeCurrent()) {
1578 Destroy();
1579 return false;
[email protected]eb54a562010-01-20 21:55:181580 }
1581
[email protected]246a70452010-03-05 21:53:501582 CHECK_GL_ERROR();
1583
1584 if (!group_->Initialize()) {
1585 Destroy();
1586 return false;
1587 }
1588
[email protected]f39f4b3f2010-05-12 17:04:081589 vertex_attrib_manager_.Initialize(group_->max_vertex_attribs());
[email protected]876f6fee2010-08-02 23:10:321590
1591 // Check supported extensions.
1592 depth24_stencil8_oes_supported_ =
1593 context_->HasExtension("GL_OES_packed_depth_stencil");
1594
[email protected]b1122982010-05-17 23:04:241595 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
1596 // OpenGL ES 2.0 does not have this issue.
1597 glEnableVertexAttribArray(0);
1598 glGenBuffersARB(1, &attrib_0_buffer_id_);
1599 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
1600 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
1601 glBindBuffer(GL_ARRAY_BUFFER, 0);
[email protected]f39f4b3f2010-05-12 17:04:081602
[email protected]246a70452010-03-05 21:53:501603 texture_units_.reset(
1604 new TextureUnit[group_->max_texture_units()]);
[email protected]1958e0e2010-04-22 05:17:151605 for (uint32 tt = 0; tt < group_->max_texture_units(); ++tt) {
[email protected]00f893d2010-08-24 18:55:491606 glActiveTexture(GL_TEXTURE0 + tt);
1607 // Do cube map first because we want the last bind to be 2D.
1608 TextureManager::TextureInfo* info =
[email protected]1958e0e2010-04-22 05:17:151609 texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
[email protected]00f893d2010-08-24 18:55:491610 texture_units_[tt].bound_texture_cube_map = info;
1611 glBindTexture(GL_TEXTURE_CUBE_MAP, info->service_id());
1612 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
1613 texture_units_[tt].bound_texture_2d = info;
1614 glBindTexture(GL_TEXTURE_2D, info->service_id());
[email protected]1958e0e2010-04-22 05:17:151615 }
[email protected]00f893d2010-08-24 18:55:491616 glActiveTexture(GL_TEXTURE0);
[email protected]246a70452010-03-05 21:53:501617 CHECK_GL_ERROR();
1618
[email protected]d37231fa2010-04-09 21:16:021619 if (context_->IsOffscreen()) {
[email protected]6217d392010-03-25 22:08:351620 // Create the target frame buffer. This is the one that the client renders
1621 // directly to.
1622 offscreen_target_frame_buffer_.reset(new FrameBuffer(this));
1623 offscreen_target_frame_buffer_->Create();
1624 offscreen_target_color_texture_.reset(new Texture(this));
1625 offscreen_target_color_texture_->Create();
[email protected]b9363b22010-06-09 22:06:151626 offscreen_target_depth_render_buffer_.reset(
[email protected]6217d392010-03-25 22:08:351627 new RenderBuffer(this));
[email protected]b9363b22010-06-09 22:06:151628 offscreen_target_depth_render_buffer_->Create();
1629 offscreen_target_stencil_render_buffer_.reset(
1630 new RenderBuffer(this));
1631 offscreen_target_stencil_render_buffer_->Create();
[email protected]6217d392010-03-25 22:08:351632
1633 // Create the saved offscreen texture. The target frame buffer is copied
1634 // here when SwapBuffers is called.
1635 offscreen_saved_color_texture_.reset(new Texture(this));
1636 offscreen_saved_color_texture_->Create();
1637
[email protected]6217d392010-03-25 22:08:351638 // Map the ID of the saved offscreen texture into the parent so that
1639 // it can reference it.
1640 if (parent_) {
1641 GLuint service_id = offscreen_saved_color_texture_->id();
[email protected]6217d392010-03-25 22:08:351642 TextureManager::TextureInfo* info =
[email protected]ae51d192010-04-27 00:48:031643 parent_->CreateTextureInfo(parent_client_texture_id, service_id);
[email protected]6217d392010-03-25 22:08:351644 parent_->texture_manager()->SetInfoTarget(info, GL_TEXTURE_2D);
1645 }
1646
1647 // Allocate the render buffers at their initial size and check the status
1648 // of the frame buffers is okay.
[email protected]d37231fa2010-04-09 21:16:021649 pending_offscreen_size_ = size;
[email protected]6217d392010-03-25 22:08:351650 if (!UpdateOffscreenFrameBufferSize()) {
1651 DLOG(ERROR) << "Could not allocate offscreen buffer storage.";
1652 Destroy();
1653 return false;
1654 }
1655
1656 // Bind to the new default frame buffer (the offscreen target frame buffer).
1657 // This should now be associated with ID zero.
1658 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
1659 }
1660
[email protected]76a0ee102010-04-07 21:03:041661 // OpenGL ES 2.0 implicitly enables the desktop GL capability
1662 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
1663 // isn't well documented; it was discovered in the Khronos OpenGL ES
1664 // mailing list archives.
[email protected]b9363b22010-06-09 22:06:151665 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
1666 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
1667 }
[email protected]de17df392010-04-23 21:09:411668
[email protected]f517cc842010-08-25 19:13:401669 if (use_shader_translator_) {
1670 if (!InitializeShaderTranslator()) {
1671 DLOG(ERROR) << "Could not initialize shader translator.";
1672 Destroy();
1673 return false;
1674 }
[email protected]5236b752010-07-27 18:02:231675
[email protected]f517cc842010-08-25 19:13:401676 TBuiltInResource resources;
1677 resources.maxVertexAttribs = group_->max_vertex_attribs();
1678 resources.maxVertexUniformVectors =
1679 group_->max_vertex_uniform_vectors();
1680 resources.maxVaryingVectors = group_->max_varying_vectors();
1681 resources.maxVertexTextureImageUnits =
1682 group_->max_vertex_texture_image_units();
1683 resources.maxCombinedTextureImageUnits = group_->max_texture_units();
1684 resources.maxTextureImageUnits = group_->max_texture_image_units();
1685 resources.maxFragmentUniformVectors =
1686 group_->max_fragment_uniform_vectors();
1687 resources.maxDrawBuffers = 1;
1688 vertex_compiler_ = ShConstructCompiler(EShLangVertex, EShSpecGLES2,
1689 &resources);
1690 if (vertex_compiler_ == NULL) {
1691 DLOG(ERROR) << "Could not create vertex shader translator.";
1692 Destroy();
1693 return false;
1694 }
1695 fragment_compiler_ = ShConstructCompiler(EShLangFragment, EShSpecGLES2,
1696 &resources);
1697 if (fragment_compiler_ == NULL) {
1698 DLOG(ERROR) << "Could not create fragment shader translator.";
1699 Destroy();
1700 return false;
1701 }
[email protected]de17df392010-04-23 21:09:411702 }
[email protected]76a0ee102010-04-07 21:03:041703
[email protected]246a70452010-03-05 21:53:501704 return true;
[email protected]96449d2c2009-11-25 00:01:321705}
1706
[email protected]ae51d192010-04-27 00:48:031707bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
[email protected]a93bb842010-02-16 23:03:471708 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:031709 if (GetBufferInfo(client_ids[ii])) {
1710 return false;
1711 }
1712 }
1713 scoped_array<GLuint> service_ids(new GLuint[n]);
1714 glGenBuffersARB(n, service_ids.get());
1715 for (GLsizei ii = 0; ii < n; ++ii) {
1716 CreateBufferInfo(client_ids[ii], service_ids[ii]);
1717 }
1718 return true;
1719}
1720
1721bool GLES2DecoderImpl::GenFramebuffersHelper(
1722 GLsizei n, const GLuint* client_ids) {
1723 for (GLsizei ii = 0; ii < n; ++ii) {
1724 if (GetFramebufferInfo(client_ids[ii])) {
1725 return false;
1726 }
1727 }
1728 scoped_array<GLuint> service_ids(new GLuint[n]);
1729 glGenFramebuffersEXT(n, service_ids.get());
1730 for (GLsizei ii = 0; ii < n; ++ii) {
1731 CreateFramebufferInfo(client_ids[ii], service_ids[ii]);
1732 }
1733 return true;
1734}
1735
1736bool GLES2DecoderImpl::GenRenderbuffersHelper(
1737 GLsizei n, const GLuint* client_ids) {
1738 for (GLsizei ii = 0; ii < n; ++ii) {
1739 if (GetRenderbufferInfo(client_ids[ii])) {
1740 return false;
1741 }
1742 }
1743 scoped_array<GLuint> service_ids(new GLuint[n]);
1744 glGenRenderbuffersEXT(n, service_ids.get());
1745 for (GLsizei ii = 0; ii < n; ++ii) {
1746 CreateRenderbufferInfo(client_ids[ii], service_ids[ii]);
1747 }
1748 return true;
1749}
1750
1751bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
1752 for (GLsizei ii = 0; ii < n; ++ii) {
1753 if (GetTextureInfo(client_ids[ii])) {
1754 return false;
1755 }
1756 }
1757 scoped_array<GLuint> service_ids(new GLuint[n]);
1758 glGenTextures(n, service_ids.get());
1759 for (GLsizei ii = 0; ii < n; ++ii) {
1760 CreateTextureInfo(client_ids[ii], service_ids[ii]);
1761 }
1762 return true;
1763}
1764
1765void GLES2DecoderImpl::DeleteBuffersHelper(
1766 GLsizei n, const GLuint* client_ids) {
1767 for (GLsizei ii = 0; ii < n; ++ii) {
1768 BufferManager::BufferInfo* info = GetBufferInfo(client_ids[ii]);
1769 if (info) {
1770 GLuint service_id = info->service_id();
1771 glDeleteBuffersARB(1, &service_id);
1772 RemoveBufferInfo(client_ids[ii]);
1773 }
[email protected]a93bb842010-02-16 23:03:471774 }
[email protected]07f54fcc2009-12-22 02:46:301775}
1776
[email protected]ae51d192010-04-27 00:48:031777void GLES2DecoderImpl::DeleteFramebuffersHelper(
1778 GLsizei n, const GLuint* client_ids) {
[email protected]a25fa872010-03-25 02:57:581779 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:031780 FramebufferManager::FramebufferInfo* info =
1781 GetFramebufferInfo(client_ids[ii]);
1782 if (info) {
1783 GLuint service_id = info->service_id();
1784 glDeleteFramebuffersEXT(1, &service_id);
1785 RemoveFramebufferInfo(client_ids[ii]);
1786 }
[email protected]a25fa872010-03-25 02:57:581787 }
[email protected]07f54fcc2009-12-22 02:46:301788}
1789
[email protected]ae51d192010-04-27 00:48:031790void GLES2DecoderImpl::DeleteRenderbuffersHelper(
1791 GLsizei n, const GLuint* client_ids) {
[email protected]a25fa872010-03-25 02:57:581792 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:031793 RenderbufferManager::RenderbufferInfo* info =
1794 GetRenderbufferInfo(client_ids[ii]);
1795 if (info) {
1796 GLuint service_id = info->service_id();
1797 glDeleteRenderbuffersEXT(1, &service_id);
1798 RemoveRenderbufferInfo(client_ids[ii]);
1799 }
[email protected]a25fa872010-03-25 02:57:581800 }
[email protected]07f54fcc2009-12-22 02:46:301801}
1802
[email protected]ae51d192010-04-27 00:48:031803void GLES2DecoderImpl::DeleteTexturesHelper(
1804 GLsizei n, const GLuint* client_ids) {
[email protected]a93bb842010-02-16 23:03:471805 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:031806 TextureManager::TextureInfo* info = GetTextureInfo(client_ids[ii]);
1807 if (info) {
1808 GLuint service_id = info->service_id();
1809 glDeleteTextures(1, &service_id);
1810 RemoveTextureInfo(client_ids[ii]);
1811 }
[email protected]a93bb842010-02-16 23:03:471812 }
[email protected]07f54fcc2009-12-22 02:46:301813}
1814
[email protected]43f28f832010-02-03 02:28:481815// } // anonymous namespace
[email protected]96449d2c2009-11-25 00:01:321816
[email protected]eb54a562010-01-20 21:55:181817bool GLES2DecoderImpl::MakeCurrent() {
[email protected]66791e382010-07-14 20:48:301818 return context_.get() ? context_->MakeCurrent() : false;
[email protected]eb54a562010-01-20 21:55:181819}
1820
[email protected]8e3e0662010-08-23 18:46:301821void GLES2DecoderImpl::RestoreCurrentRenderbufferBindings() {
1822 glBindRenderbufferEXT(
1823 GL_RENDERBUFFER,
1824 bound_renderbuffer_ ? bound_renderbuffer_->service_id() : 0);
1825}
1826
1827static void RebindCurrentFramebuffer(
1828 GLenum target,
1829 FramebufferManager::FramebufferInfo* info,
1830 FrameBuffer* offscreen_frame_buffer) {
1831 GLuint framebuffer_id = info ? info->service_id() : 0;
1832 if (framebuffer_id == 0 && offscreen_frame_buffer) {
1833 framebuffer_id = offscreen_frame_buffer->id();
1834 }
1835 glBindFramebufferEXT(target, framebuffer_id);
1836}
1837
1838void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
1839 if (!group_->extension_flags().ext_framebuffer_multisample) {
1840 RebindCurrentFramebuffer(
1841 GL_FRAMEBUFFER,
1842 bound_draw_framebuffer_.get(),
1843 offscreen_target_frame_buffer_.get());
1844 } else {
1845 RebindCurrentFramebuffer(
1846 GL_READ_FRAMEBUFFER_EXT,
1847 bound_read_framebuffer_.get(),
1848 offscreen_target_frame_buffer_.get());
1849 RebindCurrentFramebuffer(
1850 GL_DRAW_FRAMEBUFFER_EXT,
1851 bound_draw_framebuffer_.get(),
1852 offscreen_target_frame_buffer_.get());
1853 }
1854}
1855
1856void GLES2DecoderImpl::RestoreCurrentTexture2DBindings() {
1857 GLES2DecoderImpl::TextureUnit& info = texture_units_[0];
1858 GLuint last_id;
1859 if (info.bound_texture_2d) {
1860 last_id = info.bound_texture_2d->service_id();
1861 } else {
1862 last_id = 0;
1863 }
1864
1865 glBindTexture(GL_TEXTURE_2D, last_id);
1866 glActiveTexture(GL_TEXTURE0 + active_texture_unit_);
1867}
1868
1869gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
1870 if (bound_read_framebuffer_ != 0) {
[email protected]d37231fa2010-04-09 21:16:021871 int width = 0;
1872 int height = 0;
[email protected]246a70452010-03-05 21:53:501873
[email protected]8e3e0662010-08-23 18:46:301874 GLenum target = group_->extension_flags().ext_framebuffer_multisample ?
1875 GL_READ_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
1876
[email protected]d37231fa2010-04-09 21:16:021877 // Assume we have to have COLOR_ATTACHMENT0. Should we check for depth and
1878 // stencil.
1879 GLint fb_type = 0;
1880 glGetFramebufferAttachmentParameterivEXT(
[email protected]8e3e0662010-08-23 18:46:301881 target,
[email protected]d37231fa2010-04-09 21:16:021882 GL_COLOR_ATTACHMENT0,
1883 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE,
1884 &fb_type);
1885 switch (fb_type) {
1886 case GL_RENDERBUFFER:
1887 {
1888 GLint renderbuffer_id = 0;
1889 glGetFramebufferAttachmentParameterivEXT(
[email protected]8e3e0662010-08-23 18:46:301890 target,
[email protected]d37231fa2010-04-09 21:16:021891 GL_COLOR_ATTACHMENT0,
1892 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
1893 &renderbuffer_id);
1894 if (renderbuffer_id != 0) {
1895 glGetRenderbufferParameterivEXT(
1896 GL_RENDERBUFFER,
1897 GL_RENDERBUFFER_WIDTH,
1898 &width);
1899 glGetRenderbufferParameterivEXT(
1900 GL_RENDERBUFFER,
1901 GL_RENDERBUFFER_HEIGHT,
1902 &height);
1903 }
1904 break;
1905 }
1906 case GL_TEXTURE:
1907 {
1908 GLint texture_id = 0;
1909 glGetFramebufferAttachmentParameterivEXT(
[email protected]8e3e0662010-08-23 18:46:301910 target,
[email protected]d37231fa2010-04-09 21:16:021911 GL_COLOR_ATTACHMENT0,
1912 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
1913 &texture_id);
1914 if (texture_id != 0) {
[email protected]ae51d192010-04-27 00:48:031915 GLuint client_id = 0;
1916 if (texture_manager()->GetClientId(texture_id, &client_id)) {
1917 TextureManager::TextureInfo* texture_info =
1918 GetTextureInfo(client_id);
1919 if (texture_info) {
1920 GLint level = 0;
1921 GLint face = 0;
1922 glGetFramebufferAttachmentParameterivEXT(
[email protected]8e3e0662010-08-23 18:46:301923 target,
[email protected]ae51d192010-04-27 00:48:031924 GL_COLOR_ATTACHMENT0,
1925 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL,
1926 &level);
1927 glGetFramebufferAttachmentParameterivEXT(
[email protected]8e3e0662010-08-23 18:46:301928 target,
[email protected]ae51d192010-04-27 00:48:031929 GL_COLOR_ATTACHMENT0,
1930 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE,
1931 &face);
1932 texture_info->GetLevelSize(
1933 face ? face : GL_TEXTURE_2D, level, &width, &height);
1934 }
[email protected]d37231fa2010-04-09 21:16:021935 }
1936 }
1937 break;
1938 }
1939 default:
1940 // unknown so assume width and height are zero.
1941 break;
[email protected]246a70452010-03-05 21:53:501942 }
1943
[email protected]d37231fa2010-04-09 21:16:021944 return gfx::Size(width, height);
1945 } else if (offscreen_target_color_texture_.get()) {
1946 return offscreen_target_color_texture_->size();
[email protected]6217d392010-03-25 22:08:351947 } else {
[email protected]d37231fa2010-04-09 21:16:021948 return context_->GetSize();
[email protected]d37231fa2010-04-09 21:16:021949 }
[email protected]246a70452010-03-05 21:53:501950}
1951
[email protected]6217d392010-03-25 22:08:351952bool GLES2DecoderImpl::UpdateOffscreenFrameBufferSize() {
[email protected]d37231fa2010-04-09 21:16:021953 if (offscreen_target_color_texture_->size() == pending_offscreen_size_)
[email protected]6217d392010-03-25 22:08:351954 return true;
1955
1956 // Reallocate the offscreen target buffers.
[email protected]d37231fa2010-04-09 21:16:021957 if (!offscreen_target_color_texture_->AllocateStorage(
1958 pending_offscreen_size_)) {
[email protected]6217d392010-03-25 22:08:351959 return false;
1960 }
1961
[email protected]876f6fee2010-08-02 23:10:321962 // GLES2 may only allow a combination of 16-bit depth buffers and / or 8-bit
1963 // stencil buffer. A packed 24/8 bit depth stencil buffer is preferred.
1964 // ANGLE only supports the latter, i.e. is does not support core GLES2 in
1965 // this respect. So we check for packed depth stencil support.
1966 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
1967 !depth24_stencil8_oes_supported_) {
[email protected]b9363b22010-06-09 22:06:151968 if (!offscreen_target_depth_render_buffer_->AllocateStorage(
1969 pending_offscreen_size_, GL_DEPTH_COMPONENT16)) {
1970 return false;
1971 }
1972
1973 if (!offscreen_target_stencil_render_buffer_->AllocateStorage(
1974 pending_offscreen_size_, GL_STENCIL_INDEX8)) {
1975 return false;
1976 }
1977 } else {
1978 if (!offscreen_target_depth_render_buffer_->AllocateStorage(
1979 pending_offscreen_size_, GL_DEPTH24_STENCIL8)) {
1980 return false;
1981 }
[email protected]6217d392010-03-25 22:08:351982 }
1983
[email protected]2f2d7042010-04-14 21:45:581984 // Attach the offscreen target buffers to the target frame buffer.
[email protected]6217d392010-03-25 22:08:351985 offscreen_target_frame_buffer_->AttachRenderTexture(
1986 offscreen_target_color_texture_.get());
[email protected]b9363b22010-06-09 22:06:151987 offscreen_target_frame_buffer_->AttachRenderBuffer(
1988 GL_DEPTH_ATTACHMENT,
1989 offscreen_target_depth_render_buffer_.get());
[email protected]876f6fee2010-08-02 23:10:321990 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
1991 !depth24_stencil8_oes_supported_) {
[email protected]b9363b22010-06-09 22:06:151992 offscreen_target_frame_buffer_->AttachRenderBuffer(
1993 GL_STENCIL_ATTACHMENT,
1994 offscreen_target_stencil_render_buffer_.get());
1995 } else {
1996 offscreen_target_frame_buffer_->AttachRenderBuffer(
1997 GL_STENCIL_ATTACHMENT,
1998 offscreen_target_depth_render_buffer_.get());
1999 }
[email protected]6217d392010-03-25 22:08:352000 if (offscreen_target_frame_buffer_->CheckStatus() !=
2001 GL_FRAMEBUFFER_COMPLETE) {
2002 return false;
2003 }
2004
[email protected]b9363b22010-06-09 22:06:152005 // TODO(apatrick): Fix this once ANGLE supports shared contexts.
[email protected]2f2d7042010-04-14 21:45:582006 // Clear offscreen frame buffer to its initial state. Use default GL context
2007 // to ensure clear is not affected by client set state.
[email protected]b9363b22010-06-09 22:06:152008 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
[email protected]2f2d7042010-04-14 21:45:582009 ScopedDefaultGLContext scoped_context(this);
[email protected]b9363b22010-06-09 22:06:152010 glBindFramebufferEXT(GL_FRAMEBUFFER,
[email protected]2f2d7042010-04-14 21:45:582011 offscreen_target_frame_buffer_->id());
2012 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
[email protected]b9363b22010-06-09 22:06:152013 glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
[email protected]2f2d7042010-04-14 21:45:582014
2015 if (glGetError() != GL_NO_ERROR)
2016 return false;
2017 }
[email protected]2f2d7042010-04-14 21:45:582018
[email protected]6217d392010-03-25 22:08:352019 if (parent_) {
[email protected]e566b955d2010-06-22 19:26:512020 // Adjust the saved offscreen color texture (only accessible to parent).
[email protected]d37231fa2010-04-09 21:16:022021 offscreen_saved_color_texture_->AllocateStorage(pending_offscreen_size_);
2022
[email protected]2f2d7042010-04-14 21:45:582023 // Update the info about the offscreen saved color texture in the parent.
2024 // The reference to the parent is a weak pointer and will become null if the
2025 // parent is later destroyed.
[email protected]6217d392010-03-25 22:08:352026 GLuint service_id = offscreen_saved_color_texture_->id();
[email protected]8d25d042010-06-16 19:48:142027 GLuint client_id;
2028 CHECK(parent_->texture_manager()->GetClientId(service_id, &client_id));
2029 TextureManager::TextureInfo* info = parent_->GetTextureInfo(client_id);
[email protected]6217d392010-03-25 22:08:352030 DCHECK(info);
2031
[email protected]ef526492010-06-02 23:12:252032 texture_manager()->SetLevelInfo(
2033 info,
2034 GL_TEXTURE_2D,
2035 0, // level
2036 GL_RGBA,
2037 pending_offscreen_size_.width(),
2038 pending_offscreen_size_.height(),
2039 1, // depth
2040 0, // border
2041 GL_RGBA,
2042 GL_UNSIGNED_BYTE);
[email protected]6217d392010-03-25 22:08:352043
[email protected]0c8c9d22010-06-25 17:36:392044 // Attach the saved offscreen color texture to a frame buffer so we can
2045 // clear it with glClear.
2046 offscreen_target_frame_buffer_->AttachRenderTexture(
2047 offscreen_saved_color_texture_.get());
2048 if (offscreen_target_frame_buffer_->CheckStatus() !=
2049 GL_FRAMEBUFFER_COMPLETE) {
[email protected]e566b955d2010-06-22 19:26:512050 return false;
[email protected]0c8c9d22010-06-25 17:36:392051 }
[email protected]e566b955d2010-06-22 19:26:512052
[email protected]0c8c9d22010-06-25 17:36:392053 // TODO(apatrick): Fix this once ANGLE supports shared contexts.
2054 // Clear the saved offscreen color texture. Use default GL context
2055 // to ensure clear is not affected by client set state.
2056 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2057 ScopedDefaultGLContext scoped_context(this);
2058 glBindFramebufferEXT(GL_FRAMEBUFFER,
2059 offscreen_target_frame_buffer_->id());
2060 glClear(GL_COLOR_BUFFER_BIT);
2061 glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
2062
2063 if (glGetError() != GL_NO_ERROR)
2064 return false;
2065 }
2066
2067 // Re-attach the offscreen render texture to the target frame buffer.
2068 offscreen_target_frame_buffer_->AttachRenderTexture(
2069 offscreen_target_color_texture_.get());
2070 }
[email protected]e566b955d2010-06-22 19:26:512071
[email protected]6217d392010-03-25 22:08:352072 return true;
2073}
2074
[email protected]43f28f832010-02-03 02:28:482075void GLES2DecoderImpl::SetSwapBuffersCallback(Callback0::Type* callback) {
2076 swap_buffers_callback_.reset(callback);
2077}
2078
[email protected]96449d2c2009-11-25 00:01:322079void GLES2DecoderImpl::Destroy() {
[email protected]5236b752010-07-27 18:02:232080 if (vertex_compiler_ != NULL) {
2081 ShDestruct(vertex_compiler_);
2082 vertex_compiler_ = NULL;
2083 }
2084 if (fragment_compiler_ != NULL) {
2085 ShDestruct(fragment_compiler_);
2086 fragment_compiler_ = NULL;
2087 }
[email protected]5236b752010-07-27 18:02:232088
[email protected]66791e382010-07-14 20:48:302089 if (context_.get()) {
[email protected]4bedba72010-04-20 22:08:542090 MakeCurrent();
[email protected]6217d392010-03-25 22:08:352091
[email protected]b1122982010-05-17 23:04:242092 if (attrib_0_buffer_id_) {
2093 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
2094 }
2095
[email protected]4bedba72010-04-20 22:08:542096 // Remove the saved frame buffer mapping from the parent decoder. The
2097 // parent pointer is a weak pointer so it will be null if the parent has
2098 // already been destroyed.
2099 if (parent_) {
2100 // First check the texture has been mapped into the parent. This might not
2101 // be the case if initialization failed midway through.
2102 GLuint service_id = offscreen_saved_color_texture_->id();
[email protected]ae51d192010-04-27 00:48:032103 GLuint client_id = 0;
2104 if (parent_->texture_manager()->GetClientId(service_id, &client_id)) {
2105 parent_->texture_manager()->RemoveTextureInfo(client_id);
[email protected]4bedba72010-04-20 22:08:542106 }
[email protected]6217d392010-03-25 22:08:352107 }
[email protected]6217d392010-03-25 22:08:352108
[email protected]4bedba72010-04-20 22:08:542109 if (offscreen_target_frame_buffer_.get()) {
2110 offscreen_target_frame_buffer_->Destroy();
2111 offscreen_target_frame_buffer_.reset();
2112 }
[email protected]6217d392010-03-25 22:08:352113
[email protected]4bedba72010-04-20 22:08:542114 if (offscreen_target_color_texture_.get()) {
2115 offscreen_target_color_texture_->Destroy();
2116 offscreen_target_color_texture_.reset();
2117 }
[email protected]6217d392010-03-25 22:08:352118
[email protected]b9363b22010-06-09 22:06:152119 if (offscreen_target_depth_render_buffer_.get()) {
2120 offscreen_target_depth_render_buffer_->Destroy();
2121 offscreen_target_depth_render_buffer_.reset();
2122 }
2123
2124 if (offscreen_target_stencil_render_buffer_.get()) {
2125 offscreen_target_stencil_render_buffer_->Destroy();
2126 offscreen_target_stencil_render_buffer_.reset();
[email protected]4bedba72010-04-20 22:08:542127 }
[email protected]6217d392010-03-25 22:08:352128
[email protected]4bedba72010-04-20 22:08:542129 if (offscreen_saved_color_texture_.get()) {
2130 offscreen_saved_color_texture_->Destroy();
2131 offscreen_saved_color_texture_.reset();
2132 }
[email protected]66791e382010-07-14 20:48:302133
2134 context_->Destroy();
2135 context_.reset();
[email protected]d37231fa2010-04-09 21:16:022136 }
[email protected]2f2d7042010-04-14 21:45:582137
2138 if (default_context_.get()) {
2139 default_context_->Destroy();
2140 default_context_.reset();
2141 }
[email protected]96449d2c2009-11-25 00:01:322142}
2143
[email protected]6217d392010-03-25 22:08:352144void GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
2145 // We can't resize the render buffers immediately because there might be a
2146 // partial frame rendered into them and we don't want the tail end of that
2147 // rendered into the reallocated storage. Defer until the next SwapBuffers.
[email protected]d37231fa2010-04-09 21:16:022148 pending_offscreen_size_ = size;
[email protected]6217d392010-03-25 22:08:352149}
2150
[email protected]96449d2c2009-11-25 00:01:322151const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
2152 if (command_id > kStartPoint && command_id < kNumCommands) {
2153 return gles2::GetCommandName(static_cast<CommandId>(command_id));
2154 }
2155 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
2156}
2157
2158// Decode command with its arguments, and call the corresponding GL function.
2159// Note: args is a pointer to the command buffer. As such, it could be changed
2160// by a (malicious) client at any time, so if validation has to happen, it
2161// should operate on a copy of them.
[email protected]f7a64ee2010-02-01 22:24:142162error::Error GLES2DecoderImpl::DoCommand(
[email protected]96449d2c2009-11-25 00:01:322163 unsigned int command,
2164 unsigned int arg_count,
2165 const void* cmd_data) {
[email protected]f7a64ee2010-02-01 22:24:142166 error::Error result = error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192167 if (debug()) {
2168 // TODO(gman): Change output to something useful for NaCl.
[email protected]f39f4b3f2010-05-12 17:04:082169 DLOG(INFO) << "cmd: " << GetCommandName(command);
[email protected]b9849abf2009-11-25 19:13:192170 }
[email protected]96449d2c2009-11-25 00:01:322171 unsigned int command_index = command - kStartPoint - 1;
2172 if (command_index < arraysize(g_command_info)) {
2173 const CommandInfo& info = g_command_info[command_index];
2174 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
2175 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
2176 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
[email protected]b9849abf2009-11-25 19:13:192177 uint32 immediate_data_size =
2178 (arg_count - info_arg_count) * sizeof(CommandBufferEntry); // NOLINT
[email protected]96449d2c2009-11-25 00:01:322179 switch (command) {
2180 #define GLES2_CMD_OP(name) \
2181 case name::kCmdId: \
[email protected]b9849abf2009-11-25 19:13:192182 result = Handle ## name( \
2183 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:322184 *static_cast<const name*>(cmd_data)); \
[email protected]b9849abf2009-11-25 19:13:192185 break; \
[email protected]96449d2c2009-11-25 00:01:322186
2187 GLES2_COMMAND_LIST(GLES2_CMD_OP)
[email protected]96449d2c2009-11-25 00:01:322188 #undef GLES2_CMD_OP
[email protected]bf0985e2009-12-17 03:04:382189 }
2190 if (debug()) {
[email protected]07f54fcc2009-12-22 02:46:302191 GLenum error;
2192 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]bf0985e2009-12-17 03:04:382193 // TODO(gman): Change output to something useful for NaCl.
[email protected]8eee29c2010-04-29 03:38:292194 SetGLError(error, NULL);
[email protected]f39f4b3f2010-05-12 17:04:082195 DLOG(INFO) << "GL ERROR: " << error
2196 << " : " << GetCommandName(command);
[email protected]b9849abf2009-11-25 19:13:192197 }
[email protected]96449d2c2009-11-25 00:01:322198 }
2199 } else {
[email protected]f7a64ee2010-02-01 22:24:142200 result = error::kInvalidArguments;
[email protected]96449d2c2009-11-25 00:01:322201 }
[email protected]b9849abf2009-11-25 19:13:192202 } else {
2203 result = DoCommonCommand(command, arg_count, cmd_data);
[email protected]96449d2c2009-11-25 00:01:322204 }
[email protected]b9849abf2009-11-25 19:13:192205 return result;
[email protected]96449d2c2009-11-25 00:01:322206}
2207
[email protected]ae51d192010-04-27 00:48:032208void GLES2DecoderImpl::RemoveBufferInfo(GLuint client_id) {
2209 buffer_manager()->RemoveBufferInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:502210}
2211
[email protected]ae51d192010-04-27 00:48:032212bool GLES2DecoderImpl::CreateProgramHelper(GLuint client_id) {
2213 if (GetProgramInfo(client_id)) {
2214 return false;
2215 }
[email protected]96449d2c2009-11-25 00:01:322216 GLuint service_id = glCreateProgram();
[email protected]ae51d192010-04-27 00:48:032217 if (service_id != 0) {
2218 CreateProgramInfo(client_id, service_id);
[email protected]96449d2c2009-11-25 00:01:322219 }
[email protected]ae51d192010-04-27 00:48:032220 return true;
[email protected]96449d2c2009-11-25 00:01:322221}
2222
[email protected]ae51d192010-04-27 00:48:032223bool GLES2DecoderImpl::CreateShaderHelper(GLenum type, GLuint client_id) {
2224 if (GetShaderInfo(client_id)) {
2225 return false;
[email protected]96449d2c2009-11-25 00:01:322226 }
[email protected]ae51d192010-04-27 00:48:032227 GLuint service_id = glCreateShader(type);
2228 if (service_id != 0) {
[email protected]7cea56d92010-04-28 17:21:382229 CreateShaderInfo(client_id, service_id, type);
[email protected]ae51d192010-04-27 00:48:032230 }
2231 return true;
[email protected]96449d2c2009-11-25 00:01:322232}
2233
[email protected]3916c97e2010-02-25 03:20:502234void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
[email protected]36cef8ce2010-03-16 07:34:452235 GLuint texture_index = texture_unit - GL_TEXTURE0;
2236 if (texture_index > group_->max_texture_units()) {
[email protected]8eee29c2010-04-29 03:38:292237 SetGLError(GL_INVALID_ENUM, "glActiveTexture: texture_unit out of range.");
[email protected]3916c97e2010-02-25 03:20:502238 return;
2239 }
[email protected]36cef8ce2010-03-16 07:34:452240 active_texture_unit_ = texture_index;
2241 glActiveTexture(texture_unit);
[email protected]3916c97e2010-02-25 03:20:502242}
2243
[email protected]051b1372010-04-12 02:42:082244void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:502245 BufferManager::BufferInfo* info = NULL;
[email protected]051b1372010-04-12 02:42:082246 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:032247 if (client_id != 0) {
2248 info = GetBufferInfo(client_id);
2249 if (!info) {
2250 // It's a new id so make a buffer info for it.
2251 glGenBuffersARB(1, &service_id);
2252 CreateBufferInfo(client_id, service_id);
2253 info = GetBufferInfo(client_id);
[email protected]066849e32010-05-03 19:14:102254 IdAllocator* id_allocator =
2255 group_->GetIdAllocator(id_namespaces::kBuffers);
2256 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:032257 }
[email protected]051b1372010-04-12 02:42:082258 }
[email protected]ae51d192010-04-27 00:48:032259 if (info) {
[email protected]4e8a5b122010-05-08 22:00:102260 if (!buffer_manager()->SetTarget(info, target)) {
[email protected]8eee29c2010-04-29 03:38:292261 SetGLError(GL_INVALID_OPERATION,
2262 "glBindBuffer: buffer bound to more than 1 target");
[email protected]a93bb842010-02-16 23:03:472263 return;
2264 }
[email protected]ae51d192010-04-27 00:48:032265 service_id = info->service_id();
[email protected]a93bb842010-02-16 23:03:472266 }
[email protected]96449d2c2009-11-25 00:01:322267 switch (target) {
2268 case GL_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:502269 bound_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:322270 break;
2271 case GL_ELEMENT_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:502272 bound_element_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:322273 break;
2274 default:
[email protected]a93bb842010-02-16 23:03:472275 NOTREACHED(); // Validation should prevent us getting here.
[email protected]96449d2c2009-11-25 00:01:322276 break;
2277 }
[email protected]051b1372010-04-12 02:42:082278 glBindBuffer(target, service_id);
[email protected]96449d2c2009-11-25 00:01:322279}
2280
[email protected]051b1372010-04-12 02:42:082281void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
2282 FramebufferManager::FramebufferInfo* info = NULL;
2283 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:032284 if (client_id != 0) {
2285 info = GetFramebufferInfo(client_id);
[email protected]051b1372010-04-12 02:42:082286 if (!info) {
[email protected]ae51d192010-04-27 00:48:032287 // It's a new id so make a framebuffer info for it.
2288 glGenFramebuffersEXT(1, &service_id);
2289 CreateFramebufferInfo(client_id, service_id);
2290 info = GetFramebufferInfo(client_id);
[email protected]066849e32010-05-03 19:14:102291 IdAllocator* id_allocator =
2292 group_->GetIdAllocator(id_namespaces::kFramebuffers);
2293 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:032294 } else {
2295 service_id = info->service_id();
[email protected]051b1372010-04-12 02:42:082296 }
2297 }
[email protected]8e3e0662010-08-23 18:46:302298
2299 if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) {
2300 bound_draw_framebuffer_ = info;
2301 }
2302 if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) {
2303 bound_read_framebuffer_ = info;
2304 }
[email protected]6217d392010-03-25 22:08:352305
2306 // When rendering to an offscreen frame buffer, instead of unbinding from
2307 // the current frame buffer, bind to the offscreen target frame buffer.
[email protected]051b1372010-04-12 02:42:082308 if (info == NULL && offscreen_target_frame_buffer_.get())
2309 service_id = offscreen_target_frame_buffer_->id();
[email protected]6217d392010-03-25 22:08:352310
[email protected]051b1372010-04-12 02:42:082311 glBindFramebufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:562312}
2313
[email protected]051b1372010-04-12 02:42:082314void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
2315 RenderbufferManager::RenderbufferInfo* info = NULL;
2316 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:032317 if (client_id != 0) {
2318 info = GetRenderbufferInfo(client_id);
[email protected]051b1372010-04-12 02:42:082319 if (!info) {
[email protected]ae51d192010-04-27 00:48:032320 // It's a new id so make a renderbuffer info for it.
2321 glGenRenderbuffersEXT(1, &service_id);
2322 CreateRenderbufferInfo(client_id, service_id);
[email protected]066849e32010-05-03 19:14:102323 info = GetRenderbufferInfo(client_id);
2324 IdAllocator* id_allocator =
2325 group_->GetIdAllocator(id_namespaces::kRenderbuffers);
2326 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:032327 } else {
2328 service_id = info->service_id();
[email protected]051b1372010-04-12 02:42:082329 }
2330 }
2331 bound_renderbuffer_ = info;
2332 glBindRenderbufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:562333}
2334
[email protected]051b1372010-04-12 02:42:082335void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:032336 TextureManager::TextureInfo* info = NULL;
[email protected]051b1372010-04-12 02:42:082337 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:032338 if (client_id != 0) {
2339 info = GetTextureInfo(client_id);
2340 if (!info) {
2341 // It's a new id so make a texture info for it.
2342 glGenTextures(1, &service_id);
2343 CreateTextureInfo(client_id, service_id);
2344 info = GetTextureInfo(client_id);
[email protected]066849e32010-05-03 19:14:102345 IdAllocator* id_allocator =
2346 group_->GetIdAllocator(id_namespaces::kTextures);
2347 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:032348 }
2349 } else {
2350 info = texture_manager()->GetDefaultTextureInfo(target);
[email protected]051b1372010-04-12 02:42:082351 }
[email protected]ae51d192010-04-27 00:48:032352
[email protected]1958e0e2010-04-22 05:17:152353 // Check the texture exists
2354 // Check that we are not trying to bind it to a different target.
[email protected]ae51d192010-04-27 00:48:032355 if (info->target() != 0 && info->target() != target) {
[email protected]8eee29c2010-04-29 03:38:292356 SetGLError(GL_INVALID_OPERATION,
2357 "glBindTexture: texture bound to more than 1 target.");
[email protected]1958e0e2010-04-22 05:17:152358 return;
2359 }
2360 if (info->target() == 0) {
2361 texture_manager()->SetInfoTarget(info, target);
[email protected]a93bb842010-02-16 23:03:472362 }
[email protected]ae51d192010-04-27 00:48:032363 glBindTexture(target, info->service_id());
[email protected]3916c97e2010-02-25 03:20:502364 TextureUnit& unit = texture_units_[active_texture_unit_];
2365 unit.bind_target = target;
[email protected]a93bb842010-02-16 23:03:472366 switch (target) {
2367 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:502368 unit.bound_texture_2d = info;
[email protected]a93bb842010-02-16 23:03:472369 break;
2370 case GL_TEXTURE_CUBE_MAP:
[email protected]3916c97e2010-02-25 03:20:502371 unit.bound_texture_cube_map = info;
[email protected]a93bb842010-02-16 23:03:472372 break;
2373 default:
2374 NOTREACHED(); // Validation should prevent us getting here.
2375 break;
2376 }
2377}
2378
[email protected]07f54fcc2009-12-22 02:46:302379void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
[email protected]f39f4b3f2010-05-12 17:04:082380 if (vertex_attrib_manager_.Enable(index, false)) {
[email protected]b1122982010-05-17 23:04:242381 if (index != 0) {
2382 glDisableVertexAttribArray(index);
2383 }
[email protected]07f54fcc2009-12-22 02:46:302384 } else {
[email protected]8eee29c2010-04-29 03:38:292385 SetGLError(GL_INVALID_VALUE,
2386 "glDisableVertexAttribArray: index out of range");
[email protected]07f54fcc2009-12-22 02:46:302387 }
2388}
2389
2390void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
[email protected]f39f4b3f2010-05-12 17:04:082391 if (vertex_attrib_manager_.Enable(index, true)) {
[email protected]07f54fcc2009-12-22 02:46:302392 glEnableVertexAttribArray(index);
2393 } else {
[email protected]8eee29c2010-04-29 03:38:292394 SetGLError(GL_INVALID_VALUE,
2395 "glEnableVertexAttribArray: index out of range");
[email protected]07f54fcc2009-12-22 02:46:302396 }
2397}
2398
[email protected]a93bb842010-02-16 23:03:472399void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
[email protected]3916c97e2010-02-25 03:20:502400 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]ef526492010-06-02 23:12:252401 if (!info || !texture_manager()->MarkMipmapsGenerated(info)) {
[email protected]8eee29c2010-04-29 03:38:292402 SetGLError(GL_INVALID_OPERATION,
2403 "glGenerateMipmaps: Can not generate mips for npot textures");
[email protected]a93bb842010-02-16 23:03:472404 return;
2405 }
2406 glGenerateMipmapEXT(target);
[email protected]a93bb842010-02-16 23:03:472407}
2408
[email protected]b273e432010-04-12 17:23:582409bool GLES2DecoderImpl::GetHelper(
2410 GLenum pname, GLint* params, GLsizei* num_written) {
[email protected]b273e432010-04-12 17:23:582411 DCHECK(num_written);
[email protected]b9363b22010-06-09 22:06:152412 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2413 switch (pname) {
[email protected]b273e432010-04-12 17:23:582414 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
2415 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102416 if (params) {
2417 *params = GL_RGBA; // TODO(gman): get correct format.
2418 }
[email protected]b273e432010-04-12 17:23:582419 return true;
2420 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2421 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102422 if (params) {
2423 *params = GL_UNSIGNED_BYTE; // TODO(gman): get correct type.
2424 }
[email protected]b273e432010-04-12 17:23:582425 return true;
2426 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
2427 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102428 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:482429 *params = group_->max_fragment_uniform_vectors();
[email protected]4e8a5b122010-05-08 22:00:102430 }
[email protected]b273e432010-04-12 17:23:582431 return true;
2432 case GL_MAX_VARYING_VECTORS:
2433 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102434 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:482435 *params = group_->max_varying_vectors();
[email protected]4e8a5b122010-05-08 22:00:102436 }
[email protected]b273e432010-04-12 17:23:582437 return true;
2438 case GL_MAX_VERTEX_UNIFORM_VECTORS:
2439 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102440 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:482441 *params = group_->max_vertex_uniform_vectors();
[email protected]4e8a5b122010-05-08 22:00:102442 }
[email protected]b273e432010-04-12 17:23:582443 return true;
[email protected]b9363b22010-06-09 22:06:152444 }
2445 }
2446 switch (pname) {
[email protected]656dcaad2010-05-07 17:18:372447 case GL_COMPRESSED_TEXTURE_FORMATS:
2448 *num_written = 0;
2449 // We don't support compressed textures.
2450 return true;
[email protected]b273e432010-04-12 17:23:582451 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
2452 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102453 if (params) {
2454 *params = 0; // We don't support compressed textures.
2455 }
[email protected]b273e432010-04-12 17:23:582456 return true;
2457 case GL_NUM_SHADER_BINARY_FORMATS:
2458 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102459 if (params) {
2460 *params = 0; // We don't support binary shader formats.
2461 }
[email protected]b273e432010-04-12 17:23:582462 return true;
2463 case GL_SHADER_BINARY_FORMATS:
2464 *num_written = 0;
2465 return true; // We don't support binary shader format.s
2466 case GL_SHADER_COMPILER:
2467 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102468 if (params) {
2469 *params = GL_TRUE;
2470 }
[email protected]b273e432010-04-12 17:23:582471 return true;
[email protected]6b8cf1a2010-05-06 16:13:582472 case GL_ARRAY_BUFFER_BINDING:
2473 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102474 if (params) {
2475 if (bound_array_buffer_) {
2476 GLuint client_id = 0;
2477 buffer_manager()->GetClientId(bound_array_buffer_->service_id(),
2478 &client_id);
2479 *params = client_id;
2480 } else {
2481 *params = 0;
2482 }
[email protected]6b8cf1a2010-05-06 16:13:582483 }
2484 return true;
2485 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
2486 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102487 if (params) {
2488 if (bound_element_array_buffer_) {
2489 GLuint client_id = 0;
2490 buffer_manager()->GetClientId(
2491 bound_element_array_buffer_->service_id(),
2492 &client_id);
2493 *params = client_id;
2494 } else {
2495 *params = 0;
2496 }
[email protected]6b8cf1a2010-05-06 16:13:582497 }
2498 return true;
2499 case GL_FRAMEBUFFER_BINDING:
[email protected]8e3e0662010-08-23 18:46:302500 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
[email protected]6b8cf1a2010-05-06 16:13:582501 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102502 if (params) {
[email protected]8e3e0662010-08-23 18:46:302503 if (bound_draw_framebuffer_) {
[email protected]4e8a5b122010-05-08 22:00:102504 GLuint client_id = 0;
2505 framebuffer_manager()->GetClientId(
[email protected]8e3e0662010-08-23 18:46:302506 bound_draw_framebuffer_->service_id(), &client_id);
2507 *params = client_id;
2508 } else {
2509 *params = 0;
2510 }
2511 }
2512 return true;
2513 case GL_READ_FRAMEBUFFER_BINDING:
2514 *num_written = 1;
2515 if (params) {
2516 if (bound_read_framebuffer_) {
2517 GLuint client_id = 0;
2518 framebuffer_manager()->GetClientId(
2519 bound_read_framebuffer_->service_id(), &client_id);
[email protected]4e8a5b122010-05-08 22:00:102520 *params = client_id;
2521 } else {
2522 *params = 0;
2523 }
[email protected]6b8cf1a2010-05-06 16:13:582524 }
2525 return true;
2526 case GL_RENDERBUFFER_BINDING:
2527 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102528 if (params) {
2529 if (bound_renderbuffer_) {
2530 GLuint client_id = 0;
2531 renderbuffer_manager()->GetClientId(
2532 bound_renderbuffer_->service_id(), &client_id);
2533 *params = client_id;
2534 } else {
2535 *params = 0;
2536 }
[email protected]6b8cf1a2010-05-06 16:13:582537 }
2538 return true;
2539 case GL_CURRENT_PROGRAM:
2540 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102541 if (params) {
2542 if (current_program_) {
2543 GLuint client_id = 0;
2544 program_manager()->GetClientId(
2545 current_program_->service_id(), &client_id);
2546 *params = client_id;
2547 } else {
2548 *params = 0;
2549 }
[email protected]6b8cf1a2010-05-06 16:13:582550 }
2551 return true;
[email protected]4e8a5b122010-05-08 22:00:102552 case GL_TEXTURE_BINDING_2D:
2553 *num_written = 1;
2554 if (params) {
[email protected]6b8cf1a2010-05-06 16:13:582555 TextureUnit& unit = texture_units_[active_texture_unit_];
2556 if (unit.bound_texture_2d) {
2557 GLuint client_id = 0;
2558 texture_manager()->GetClientId(
2559 unit.bound_texture_2d->service_id(), &client_id);
2560 *params = client_id;
2561 } else {
2562 *params = 0;
2563 }
[email protected]6b8cf1a2010-05-06 16:13:582564 }
[email protected]4e8a5b122010-05-08 22:00:102565 return true;
2566 case GL_TEXTURE_BINDING_CUBE_MAP:
2567 *num_written = 1;
2568 if (params) {
[email protected]6b8cf1a2010-05-06 16:13:582569 TextureUnit& unit = texture_units_[active_texture_unit_];
2570 if (unit.bound_texture_cube_map) {
2571 GLuint client_id = 0;
2572 texture_manager()->GetClientId(
2573 unit.bound_texture_cube_map->service_id(), &client_id);
2574 *params = client_id;
2575 } else {
2576 *params = 0;
2577 }
[email protected]6b8cf1a2010-05-06 16:13:582578 }
[email protected]4e8a5b122010-05-08 22:00:102579 return true;
[email protected]b273e432010-04-12 17:23:582580 default:
[email protected]4e8a5b122010-05-08 22:00:102581 *num_written = util_.GLGetNumValuesReturned(pname);
2582 if (params) {
2583 glGetIntegerv(pname, params);
2584 }
2585 return true;
[email protected]b273e432010-04-12 17:23:582586 }
2587}
2588
[email protected]4e8a5b122010-05-08 22:00:102589bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
2590 GLenum pname, GLsizei* num_values) {
2591 return GetHelper(pname, NULL, num_values);
2592}
2593
[email protected]b273e432010-04-12 17:23:582594void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
2595 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:102596 GLsizei num_written = 0;
2597 if (GetHelper(pname, NULL, &num_written)) {
2598 scoped_array<GLint> values(new GLint[num_written]);
2599 GetHelper(pname, values.get(), &num_written);
[email protected]b273e432010-04-12 17:23:582600 for (GLsizei ii = 0; ii < num_written; ++ii) {
2601 params[ii] = static_cast<GLboolean>(values[ii]);
2602 }
2603 } else {
2604 glGetBooleanv(pname, params);
2605 }
2606}
2607
2608void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
2609 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:102610 GLsizei num_written = 0;
2611 if (GetHelper(pname, NULL, &num_written)) {
2612 scoped_array<GLint> values(new GLint[num_written]);
2613 GetHelper(pname, values.get(), &num_written);
[email protected]b273e432010-04-12 17:23:582614 for (GLsizei ii = 0; ii < num_written; ++ii) {
2615 params[ii] = static_cast<GLfloat>(values[ii]);
2616 }
2617 } else {
2618 glGetFloatv(pname, params);
2619 }
2620}
2621
2622void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
2623 DCHECK(params);
2624 GLsizei num_written;
2625 if (!GetHelper(pname, params, &num_written)) {
2626 glGetIntegerv(pname, params);
2627 }
2628}
2629
[email protected]a0c3e972010-04-21 00:49:132630void GLES2DecoderImpl::DoGetProgramiv(
2631 GLuint program_id, GLenum pname, GLint* params) {
[email protected]6b8cf1a2010-05-06 16:13:582632 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
2633 program_id, "glGetProgramiv");
[email protected]a0c3e972010-04-21 00:49:132634 if (!info) {
[email protected]a0c3e972010-04-21 00:49:132635 return;
2636 }
2637 info->GetProgramiv(pname, params);
2638}
2639
[email protected]558847a2010-03-24 07:02:542640error::Error GLES2DecoderImpl::HandleBindAttribLocation(
2641 uint32 immediate_data_size, const gles2::BindAttribLocation& c) {
[email protected]6b8cf1a2010-05-06 16:13:582642 GLuint program = static_cast<GLuint>(c.program);
2643 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
2644 program, "glBindAttribLocation");
[email protected]ae51d192010-04-27 00:48:032645 if (!info) {
[email protected]558847a2010-03-24 07:02:542646 return error::kNoError;
2647 }
2648 GLuint index = static_cast<GLuint>(c.index);
2649 uint32 name_size = c.data_size;
2650 const char* name = GetSharedMemoryAs<const char*>(
2651 c.name_shm_id, c.name_shm_offset, name_size);
2652 if (name == NULL) {
2653 return error::kOutOfBounds;
2654 }
2655 String name_str(name, name_size);
[email protected]ae51d192010-04-27 00:48:032656 glBindAttribLocation(info->service_id(), index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:542657 return error::kNoError;
2658}
2659
2660error::Error GLES2DecoderImpl::HandleBindAttribLocationImmediate(
2661 uint32 immediate_data_size, const gles2::BindAttribLocationImmediate& c) {
[email protected]6b8cf1a2010-05-06 16:13:582662 GLuint program = static_cast<GLuint>(c.program);
2663 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
2664 program, "glBindAttribLocation");
[email protected]ae51d192010-04-27 00:48:032665 if (!info) {
[email protected]558847a2010-03-24 07:02:542666 return error::kNoError;
2667 }
2668 GLuint index = static_cast<GLuint>(c.index);
2669 uint32 name_size = c.data_size;
2670 const char* name = GetImmediateDataAs<const char*>(
2671 c, name_size, immediate_data_size);
2672 if (name == NULL) {
2673 return error::kOutOfBounds;
2674 }
2675 String name_str(name, name_size);
[email protected]ae51d192010-04-27 00:48:032676 glBindAttribLocation(info->service_id(), index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:542677 return error::kNoError;
2678}
2679
2680error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
2681 uint32 immediate_data_size, const gles2::BindAttribLocationBucket& c) {
[email protected]6b8cf1a2010-05-06 16:13:582682 GLuint program = static_cast<GLuint>(c.program);
2683 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
2684 program, "glBindAttribLocation");
[email protected]ae51d192010-04-27 00:48:032685 if (!info) {
[email protected]558847a2010-03-24 07:02:542686 return error::kNoError;
2687 }
2688 GLuint index = static_cast<GLuint>(c.index);
2689 Bucket* bucket = GetBucket(c.name_bucket_id);
2690 if (!bucket || bucket->size() == 0) {
2691 return error::kInvalidArguments;
2692 }
2693 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:182694 if (!bucket->GetAsString(&name_str)) {
2695 return error::kInvalidArguments;
2696 }
[email protected]ae51d192010-04-27 00:48:032697 glBindAttribLocation(info->service_id(), index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:542698 return error::kNoError;
2699}
2700
[email protected]f7a64ee2010-02-01 22:24:142701error::Error GLES2DecoderImpl::HandleDeleteShader(
[email protected]ba3176a2009-12-16 18:19:462702 uint32 immediate_data_size, const gles2::DeleteShader& c) {
[email protected]ae51d192010-04-27 00:48:032703 GLuint client_id = c.shader;
2704 if (client_id) {
2705 ShaderManager::ShaderInfo* info = GetShaderInfo(client_id);
2706 if (info) {
2707 glDeleteShader(info->service_id());
2708 RemoveShaderInfo(client_id);
2709 } else {
[email protected]8eee29c2010-04-29 03:38:292710 SetGLError(GL_INVALID_VALUE, "glDeleteShader: unknown shader");
[email protected]ae51d192010-04-27 00:48:032711 }
[email protected]96449d2c2009-11-25 00:01:322712 }
[email protected]f7a64ee2010-02-01 22:24:142713 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322714}
2715
[email protected]f7a64ee2010-02-01 22:24:142716error::Error GLES2DecoderImpl::HandleDeleteProgram(
[email protected]ba3176a2009-12-16 18:19:462717 uint32 immediate_data_size, const gles2::DeleteProgram& c) {
[email protected]ae51d192010-04-27 00:48:032718 GLuint client_id = c.program;
2719 if (client_id) {
2720 ProgramManager::ProgramInfo* info = GetProgramInfo(client_id);
2721 if (info) {
2722 glDeleteProgram(info->service_id());
2723 RemoveProgramInfo(client_id);
2724 } else {
[email protected]8eee29c2010-04-29 03:38:292725 SetGLError(GL_INVALID_VALUE, "glDeleteProgram: unknown program");
[email protected]ae51d192010-04-27 00:48:032726 }
[email protected]96449d2c2009-11-25 00:01:322727 }
[email protected]f7a64ee2010-02-01 22:24:142728 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322729}
2730
[email protected]066849e32010-05-03 19:14:102731void GLES2DecoderImpl::DoDeleteSharedIds(
2732 GLuint namespace_id, GLsizei n, const GLuint* ids) {
2733 IdAllocator* id_allocator = group_->GetIdAllocator(namespace_id);
2734 for (GLsizei ii = 0; ii < n; ++ii) {
2735 id_allocator->FreeID(ids[ii]);
2736 }
2737}
2738
2739error::Error GLES2DecoderImpl::HandleDeleteSharedIds(
2740 uint32 immediate_data_size, const gles2::DeleteSharedIds& c) {
2741 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
2742 GLsizei n = static_cast<GLsizei>(c.n);
2743 uint32 data_size;
2744 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
2745 return error::kOutOfBounds;
2746 }
2747 const GLuint* ids = GetSharedMemoryAs<const GLuint*>(
2748 c.ids_shm_id, c.ids_shm_offset, data_size);
2749 if (n < 0) {
2750 SetGLError(GL_INVALID_VALUE, "DeleteSharedIds: n < 0");
2751 return error::kNoError;
2752 }
2753 if (ids == NULL) {
2754 return error::kOutOfBounds;
2755 }
2756 DoDeleteSharedIds(namespace_id, n, ids);
2757 return error::kNoError;
2758}
2759
2760void GLES2DecoderImpl::DoGenSharedIds(
2761 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids) {
2762 IdAllocator* id_allocator = group_->GetIdAllocator(namespace_id);
2763 if (id_offset == 0) {
2764 for (GLsizei ii = 0; ii < n; ++ii) {
2765 ids[ii] = id_allocator->AllocateID();
2766 }
2767 } else {
2768 for (GLsizei ii = 0; ii < n; ++ii) {
2769 ids[ii] = id_allocator->AllocateIDAtOrAbove(id_offset);
2770 id_offset = ids[ii] + 1;
2771 }
2772 }
2773}
2774
2775error::Error GLES2DecoderImpl::HandleGenSharedIds(
2776 uint32 immediate_data_size, const gles2::GenSharedIds& c) {
2777 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
2778 GLuint id_offset = static_cast<GLuint>(c.id_offset);
2779 GLsizei n = static_cast<GLsizei>(c.n);
2780 uint32 data_size;
2781 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
2782 return error::kOutOfBounds;
2783 }
2784 GLuint* ids = GetSharedMemoryAs<GLuint*>(
2785 c.ids_shm_id, c.ids_shm_offset, data_size);
2786 if (n < 0) {
2787 SetGLError(GL_INVALID_VALUE, "GenSharedIds: n < 0");
2788 return error::kNoError;
2789 }
2790 if (ids == NULL) {
2791 return error::kOutOfBounds;
2792 }
2793 DoGenSharedIds(namespace_id, id_offset, n, ids);
2794 return error::kNoError;
2795}
2796
2797void GLES2DecoderImpl::DoRegisterSharedIds(
2798 GLuint namespace_id, GLsizei n, const GLuint* ids) {
2799 IdAllocator* id_allocator = group_->GetIdAllocator(namespace_id);
2800 for (GLsizei ii = 0; ii < n; ++ii) {
2801 if (!id_allocator->MarkAsUsed(ids[ii])) {
2802 for (GLsizei jj = 0; jj < ii; ++jj) {
2803 id_allocator->FreeID(ids[jj]);
2804 }
2805 SetGLError(
2806 GL_INVALID_VALUE,
2807 "RegisterSharedIds: attempt to register id that already exists");
2808 return;
2809 }
2810 }
2811}
2812
2813error::Error GLES2DecoderImpl::HandleRegisterSharedIds(
2814 uint32 immediate_data_size, const gles2::RegisterSharedIds& c) {
2815 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
2816 GLsizei n = static_cast<GLsizei>(c.n);
2817 uint32 data_size;
2818 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
2819 return error::kOutOfBounds;
2820 }
2821 GLuint* ids = GetSharedMemoryAs<GLuint*>(
2822 c.ids_shm_id, c.ids_shm_offset, data_size);
2823 if (n < 0) {
2824 SetGLError(GL_INVALID_VALUE, "RegisterSharedIds: n < 0");
2825 return error::kNoError;
2826 }
2827 if (ids == NULL) {
2828 return error::kOutOfBounds;
2829 }
2830 DoRegisterSharedIds(namespace_id, n, ids);
2831 return error::kNoError;
2832}
2833
[email protected]07f54fcc2009-12-22 02:46:302834void GLES2DecoderImpl::DoDrawArrays(
2835 GLenum mode, GLint first, GLsizei count) {
[email protected]d81e8c52010-06-07 17:58:322836 // We have to check this here because the prototype for glDrawArrays
2837 // is GLint not GLsizei.
2838 if (first < 0) {
2839 SetGLError(GL_INVALID_ENUM, "glDrawArrays: first < 0");
2840 return;
2841 }
[email protected]6c788fb72010-08-26 02:16:312842
2843 if (count == 0) {
2844 return;
2845 }
2846
[email protected]07f54fcc2009-12-22 02:46:302847 if (IsDrawValid(first + count - 1)) {
[email protected]b1122982010-05-17 23:04:242848 bool simulated_attrib_0 = SimulateAttrib0(first + count - 1);
[email protected]ef526492010-06-02 23:12:252849 bool textures_set = SetBlackTextureForNonRenderableTextures();
[email protected]07f54fcc2009-12-22 02:46:302850 glDrawArrays(mode, first, count);
[email protected]ef526492010-06-02 23:12:252851 if (textures_set) {
[email protected]3916c97e2010-02-25 03:20:502852 RestoreStateForNonRenderableTextures();
2853 }
[email protected]b1122982010-05-17 23:04:242854 if (simulated_attrib_0) {
2855 RestoreStateForSimulatedAttrib0();
2856 }
[email protected]07f54fcc2009-12-22 02:46:302857 }
2858}
2859
[email protected]36cef8ce2010-03-16 07:34:452860void GLES2DecoderImpl::DoFramebufferRenderbuffer(
2861 GLenum target, GLenum attachment, GLenum renderbuffertarget,
[email protected]ae51d192010-04-27 00:48:032862 GLuint client_renderbuffer_id) {
[email protected]8e3e0662010-08-23 18:46:302863 FramebufferManager::FramebufferInfo* framebuffer_info =
2864 GetFramebufferInfoForTarget(target);
2865 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:292866 SetGLError(GL_INVALID_OPERATION,
2867 "glFramebufferRenderbuffer: no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:452868 return;
2869 }
[email protected]ae51d192010-04-27 00:48:032870 GLuint service_id = 0;
[email protected]3a2e7c7b2010-08-06 01:12:282871 RenderbufferManager::RenderbufferInfo* info = NULL;
[email protected]ae51d192010-04-27 00:48:032872 if (client_renderbuffer_id) {
[email protected]3a2e7c7b2010-08-06 01:12:282873 info = GetRenderbufferInfo(client_renderbuffer_id);
[email protected]ae51d192010-04-27 00:48:032874 if (!info) {
[email protected]8eee29c2010-04-29 03:38:292875 SetGLError(GL_INVALID_OPERATION,
2876 "glFramebufferRenderbuffer: unknown renderbuffer");
[email protected]ae51d192010-04-27 00:48:032877 return;
2878 }
2879 service_id = info->service_id();
2880 }
2881 glFramebufferRenderbufferEXT(
2882 target, attachment, renderbuffertarget, service_id);
[email protected]3a2e7c7b2010-08-06 01:12:282883 if (service_id == 0 ||
2884 glCheckFramebufferStatusEXT(target) == GL_FRAMEBUFFER_COMPLETE) {
[email protected]8e3e0662010-08-23 18:46:302885 framebuffer_info->AttachRenderbuffer(attachment, info);
[email protected]3a2e7c7b2010-08-06 01:12:282886 if (info) {
[email protected]8e3e0662010-08-23 18:46:302887 ClearUnclearedRenderbuffers(target, framebuffer_info);
[email protected]3a2e7c7b2010-08-06 01:12:282888 }
2889 }
2890}
2891
2892void GLES2DecoderImpl::SetCapabilityState(GLenum cap, bool enabled) {
2893 switch (cap) {
2894 case GL_SCISSOR_TEST:
2895 enable_scissor_test_ = enabled;
2896 break;
2897 default:
2898 break;
2899 }
2900}
2901
2902void GLES2DecoderImpl::DoDisable(GLenum cap) {
2903 SetCapabilityState(cap, false);
2904 glDisable(cap);
2905}
2906
2907void GLES2DecoderImpl::DoEnable(GLenum cap) {
2908 SetCapabilityState(cap, true);
2909 glEnable(cap);
2910}
2911
2912void GLES2DecoderImpl::DoClearColor(
2913 GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {
2914 clear_red_ = red;
2915 clear_green_ = green;
2916 clear_blue_ = blue;
2917 clear_alpha_ = alpha;
2918 glClearColor(red, green, blue, alpha);
2919}
2920
2921void GLES2DecoderImpl::DoClearDepthf(GLclampf depth) {
2922 clear_depth_ = depth;
2923 glClearDepth(depth);
2924}
2925
2926void GLES2DecoderImpl::DoClearStencil(GLint s) {
2927 clear_stencil_ = s;
2928 glClearStencil(s);
2929}
2930
2931void GLES2DecoderImpl::DoColorMask(
2932 GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {
2933 mask_red_ = red;
2934 mask_green_ = green;
2935 mask_blue_ = blue;
2936 mask_alpha_ = alpha;
2937 glColorMask(red, green, blue, alpha);
2938}
2939
2940void GLES2DecoderImpl::DoDepthMask(GLboolean depth) {
2941 mask_depth_ = depth;
2942 glDepthMask(depth);
2943}
2944
2945void GLES2DecoderImpl::DoStencilMask(GLuint mask) {
2946 mask_stencil_front_ = mask;
2947 mask_stencil_back_ = mask;
2948 glStencilMask(mask);
2949}
2950
2951void GLES2DecoderImpl::DoStencilMaskSeparate(GLenum face, GLuint mask) {
2952 if (face == GL_FRONT) {
2953 mask_stencil_front_ = mask;
2954 } else {
2955 mask_stencil_back_ = mask;
2956 }
2957 glStencilMaskSeparate(face, mask);
2958}
2959
2960// NOTE: There's an assumption here that Texture attachments
2961// are cleared because they are textures so we only need to clear
2962// the renderbuffers.
2963void GLES2DecoderImpl::ClearUnclearedRenderbuffers(
[email protected]8e3e0662010-08-23 18:46:302964 GLenum target, FramebufferManager::FramebufferInfo* info) {
2965 if (target == GL_READ_FRAMEBUFFER_EXT) {
2966 // TODO(gman): bind this to the DRAW point, clear then bind back to READ
2967 }
[email protected]3a2e7c7b2010-08-06 01:12:282968 GLbitfield clear_bits = 0;
2969 if (info->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0)) {
2970 glClearColor(0, 0, 0, 0);
2971 glColorMask(true, true, true, true);
2972 clear_bits |= GL_COLOR_BUFFER_BIT;
2973 }
2974
2975 if (info->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) ||
2976 info->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
2977 glClearStencil(0);
2978 glStencilMask(-1);
2979 clear_bits |= GL_STENCIL_BUFFER_BIT;
2980 }
2981
2982 if (info->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
2983 info->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
2984 glClearDepth(1.0f);
2985 glDepthMask(true);
2986 clear_bits |= GL_DEPTH_BUFFER_BIT;
2987 }
2988
2989 glDisable(GL_SCISSOR_TEST);
2990 glClear(clear_bits);
2991
2992 info->MarkAttachedRenderbuffersAsCleared();
2993
2994 // reset clear color
2995 glClearColor(clear_red_, clear_green_, clear_blue_, clear_alpha_);
2996 glColorMask(mask_red_, mask_green_, mask_blue_, mask_alpha_);
2997 glClearStencil(clear_stencil_);
2998 glStencilMaskSeparate(GL_FRONT, mask_stencil_front_);
2999 glStencilMaskSeparate(GL_BACK, mask_stencil_back_);
3000 glClearDepth(clear_depth_);
3001 glDepthMask(mask_depth_);
3002 if (enable_scissor_test_) {
3003 glEnable(GL_SCISSOR_TEST);
3004 }
[email protected]8e3e0662010-08-23 18:46:303005
3006 if (target == GL_READ_FRAMEBUFFER_EXT) {
3007 // TODO(gman): rebind draw.
3008 }
[email protected]36cef8ce2010-03-16 07:34:453009}
3010
3011GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
[email protected]8e3e0662010-08-23 18:46:303012 FramebufferManager::FramebufferInfo* info =
3013 GetFramebufferInfoForTarget(target);
3014 if (!info) {
[email protected]36cef8ce2010-03-16 07:34:453015 return GL_FRAMEBUFFER_COMPLETE;
3016 }
3017 return glCheckFramebufferStatusEXT(target);
3018}
3019
3020void GLES2DecoderImpl::DoFramebufferTexture2D(
[email protected]ae51d192010-04-27 00:48:033021 GLenum target, GLenum attachment, GLenum textarget,
3022 GLuint client_texture_id, GLint level) {
[email protected]8e3e0662010-08-23 18:46:303023 FramebufferManager::FramebufferInfo* framebuffer_info =
3024 GetFramebufferInfoForTarget(target);
3025 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:293026 SetGLError(GL_INVALID_OPERATION,
3027 "glFramebufferTexture2D: no framebuffer bound.");
[email protected]36cef8ce2010-03-16 07:34:453028 return;
3029 }
[email protected]ae51d192010-04-27 00:48:033030 GLuint service_id = 0;
[email protected]3a2e7c7b2010-08-06 01:12:283031 TextureManager::TextureInfo* info = NULL;
[email protected]ae51d192010-04-27 00:48:033032 if (client_texture_id) {
[email protected]3a2e7c7b2010-08-06 01:12:283033 info = GetTextureInfo(client_texture_id);
[email protected]ae51d192010-04-27 00:48:033034 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293035 SetGLError(GL_INVALID_OPERATION,
3036 "glFramebufferTexture2D: unknown texture");
[email protected]ae51d192010-04-27 00:48:033037 return;
3038 }
3039 service_id = info->service_id();
3040 }
3041 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
[email protected]3a2e7c7b2010-08-06 01:12:283042 if (service_id != 0 &&
3043 glCheckFramebufferStatusEXT(target) == GL_FRAMEBUFFER_COMPLETE) {
[email protected]8e3e0662010-08-23 18:46:303044 ClearUnclearedRenderbuffers(target, framebuffer_info);
[email protected]3a2e7c7b2010-08-06 01:12:283045 }
[email protected]36cef8ce2010-03-16 07:34:453046}
3047
3048void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
3049 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
[email protected]8e3e0662010-08-23 18:46:303050 FramebufferManager::FramebufferInfo* framebuffer_info =
3051 GetFramebufferInfoForTarget(target);
3052 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:293053 SetGLError(GL_INVALID_OPERATION,
3054 "glFramebufferAttachmentParameteriv: no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:453055 return;
3056 }
3057 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
[email protected]74c1ec42010-08-12 01:55:573058 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
3059 GLint type = 0;
3060 GLuint client_id = 0;
3061 glGetFramebufferAttachmentParameterivEXT(
3062 target, attachment, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &type);
3063 switch (type) {
3064 case GL_RENDERBUFFER: {
3065 renderbuffer_manager()->GetClientId(*params, &client_id);
3066 break;
3067 }
3068 case GL_TEXTURE: {
3069 texture_manager()->GetClientId(*params, &client_id);
3070 break;
3071 }
3072 default:
3073 break;
3074 }
3075 *params = client_id;
3076 }
[email protected]36cef8ce2010-03-16 07:34:453077}
3078
3079void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
3080 GLenum target, GLenum pname, GLint* params) {
[email protected]051b1372010-04-12 02:42:083081 if (!bound_renderbuffer_) {
[email protected]8eee29c2010-04-29 03:38:293082 SetGLError(GL_INVALID_OPERATION,
3083 "glGetRenderbufferParameteriv: no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:453084 return;
3085 }
[email protected]b71f52c2010-06-18 22:20:203086 if (pname == GL_RENDERBUFFER_INTERNAL_FORMAT) {
3087 *params = bound_renderbuffer_->internal_format();
3088 return;
3089 }
[email protected]36cef8ce2010-03-16 07:34:453090 glGetRenderbufferParameterivEXT(target, pname, params);
3091}
3092
[email protected]8e3e0662010-08-23 18:46:303093void GLES2DecoderImpl::DoBlitFramebufferEXT(
3094 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
3095 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
3096 GLbitfield mask, GLenum filter) {
3097 if (!group_->extension_flags().ext_framebuffer_multisample) {
3098 SetGLError(GL_INVALID_OPERATION,
3099 "glBlitFramebufferEXT: function not available");
3100 }
3101 glBlitFramebufferEXT(
3102 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
3103}
3104
3105void GLES2DecoderImpl::DoRenderbufferStorageMultisample(
3106 GLenum target, GLsizei samples, GLenum internalformat,
3107 GLsizei width, GLsizei height) {
3108 if (!group_->extension_flags().ext_framebuffer_multisample) {
3109 SetGLError(GL_INVALID_OPERATION,
3110 "glRenderbufferStorageMultisampleEXT: function not available");
3111 return;
3112 }
3113 bound_renderbuffer_->set_internal_format(internalformat);
3114
3115 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
3116 switch (internalformat) {
3117 case GL_DEPTH_COMPONENT16:
3118 internalformat = GL_DEPTH_COMPONENT;
3119 break;
3120 case GL_RGBA4:
3121 case GL_RGB5_A1:
3122 internalformat = GL_RGBA;
3123 break;
3124 case GL_RGB565:
3125 internalformat = GL_RGB;
3126 break;
3127 }
3128 }
3129
3130 glRenderbufferStorageMultisampleEXT(
3131 target, samples, internalformat, width, height);
3132 // TODO(gman) should not set internal format unless this succeeds
3133}
3134
[email protected]36cef8ce2010-03-16 07:34:453135void GLES2DecoderImpl::DoRenderbufferStorage(
3136 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
[email protected]051b1372010-04-12 02:42:083137 if (!bound_renderbuffer_) {
[email protected]8eee29c2010-04-29 03:38:293138 SetGLError(GL_INVALID_OPERATION,
3139 "glGetRenderbufferStorage: no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:453140 return;
3141 }
[email protected]b71f52c2010-06-18 22:20:203142 bound_renderbuffer_->set_internal_format(internalformat);
[email protected]876f6fee2010-08-02 23:10:323143
3144 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
3145 switch (internalformat) {
3146 case GL_DEPTH_COMPONENT16:
3147 internalformat = GL_DEPTH_COMPONENT;
3148 break;
3149 case GL_RGBA4:
3150 case GL_RGB5_A1:
3151 internalformat = GL_RGBA;
3152 break;
3153 case GL_RGB565:
3154 internalformat = GL_RGB;
3155 break;
3156 }
[email protected]b71f52c2010-06-18 22:20:203157 }
[email protected]876f6fee2010-08-02 23:10:323158
[email protected]36cef8ce2010-03-16 07:34:453159 glRenderbufferStorageEXT(target, internalformat, width, height);
[email protected]8e3e0662010-08-23 18:46:303160 // TODO(gman) should not set internal format unless this succeeds
[email protected]36cef8ce2010-03-16 07:34:453161}
3162
[email protected]07f54fcc2009-12-22 02:46:303163void GLES2DecoderImpl::DoLinkProgram(GLuint program) {
[email protected]6b8cf1a2010-05-06 16:13:583164 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3165 program, "glLinkProgram");
[email protected]a93bb842010-02-16 23:03:473166 if (!info) {
[email protected]a93bb842010-02-16 23:03:473167 return;
3168 }
[email protected]d81e8c52010-06-07 17:58:323169 if (!info->CanLink()) {
[email protected]d81e8c52010-06-07 17:58:323170 return;
3171 }
[email protected]ae51d192010-04-27 00:48:033172 glLinkProgram(info->service_id());
[email protected]6b8cf1a2010-05-06 16:13:583173 GLint success = 0;
3174 glGetProgramiv(info->service_id(), GL_LINK_STATUS, &success);
3175 if (success) {
[email protected]a93bb842010-02-16 23:03:473176 info->Update();
[email protected]6b8cf1a2010-05-06 16:13:583177 } else {
3178 info->Reset();
[email protected]07f54fcc2009-12-22 02:46:303179 }
3180};
3181
[email protected]3916c97e2010-02-25 03:20:503182void GLES2DecoderImpl::DoTexParameterf(
3183 GLenum target, GLenum pname, GLfloat param) {
3184 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]07f54fcc2009-12-22 02:46:303185 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293186 SetGLError(GL_INVALID_VALUE, "glTexParameterf: unknown texture");
[email protected]07f54fcc2009-12-22 02:46:303187 } else {
[email protected]ef526492010-06-02 23:12:253188 texture_manager()->SetParameter(info, pname, static_cast<GLint>(param));
[email protected]3916c97e2010-02-25 03:20:503189 glTexParameterf(target, pname, param);
[email protected]07f54fcc2009-12-22 02:46:303190 }
3191}
3192
[email protected]3916c97e2010-02-25 03:20:503193void GLES2DecoderImpl::DoTexParameteri(
3194 GLenum target, GLenum pname, GLint param) {
3195 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
3196 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293197 SetGLError(GL_INVALID_VALUE, "glTexParameteri: unknown texture");
[email protected]3916c97e2010-02-25 03:20:503198 } else {
[email protected]ef526492010-06-02 23:12:253199 texture_manager()->SetParameter(info, pname, param);
[email protected]3916c97e2010-02-25 03:20:503200 glTexParameteri(target, pname, param);
3201 }
3202}
3203
3204void GLES2DecoderImpl::DoTexParameterfv(
3205 GLenum target, GLenum pname, const GLfloat* params) {
3206 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
3207 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293208 SetGLError(GL_INVALID_VALUE, "glTexParameterfv: unknown texture");
[email protected]3916c97e2010-02-25 03:20:503209 } else {
[email protected]ef526492010-06-02 23:12:253210 texture_manager()->SetParameter(
3211 info, pname, *reinterpret_cast<const GLint*>(params));
[email protected]3916c97e2010-02-25 03:20:503212 glTexParameterfv(target, pname, params);
3213 }
3214}
3215
3216void GLES2DecoderImpl::DoTexParameteriv(
3217 GLenum target, GLenum pname, const GLint* params) {
3218 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
3219 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293220 SetGLError(GL_INVALID_VALUE, "glTexParameteriv: unknown texture");
[email protected]3916c97e2010-02-25 03:20:503221 } else {
[email protected]ef526492010-06-02 23:12:253222 texture_manager()->SetParameter(info, pname, *params);
[email protected]3916c97e2010-02-25 03:20:503223 glTexParameteriv(target, pname, params);
3224 }
3225}
3226
[email protected]939e7362010-05-13 20:49:103227bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
[email protected]3916c97e2010-02-25 03:20:503228 if (!current_program_ || current_program_->IsDeleted()) {
[email protected]939e7362010-05-13 20:49:103229 // The program does not exist.
3230 SetGLError(GL_INVALID_OPERATION,
3231 (std::string(function_name) + ": no program in use").c_str());
3232 return false;
3233 }
3234 if (!current_program_->IsValid()) {
3235 SetGLError(GL_INVALID_OPERATION,
3236 (std::string(function_name) + ": program not linked").c_str());
3237 return false;
3238 }
3239 return true;
3240}
3241
3242bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
3243 GLint location, const char* function_name) {
3244 if (!CheckCurrentProgram(function_name)) {
3245 return false;
3246 }
3247 return location != -1;
3248}
3249
3250bool GLES2DecoderImpl::GetUniformTypeByLocation(
3251 GLint location, const char* function_name, GLenum* type) {
3252 if (!CheckCurrentProgramForUniform(location, function_name)) {
3253 return false;
3254 }
3255 if (!current_program_->GetUniformTypeByLocation(location, type)) {
3256 SetGLError(GL_INVALID_OPERATION,
3257 (std::string(function_name) + ": program not linked").c_str());
3258 return false;
3259 }
3260 return true;
3261}
3262
3263
3264void GLES2DecoderImpl::DoUniform1i(GLint location, GLint v0) {
3265 if (!CheckCurrentProgramForUniform(location, "glUniform1i")) {
[email protected]3916c97e2010-02-25 03:20:503266 return;
3267 }
3268 current_program_->SetSamplers(location, 1, &v0);
3269 glUniform1i(location, v0);
3270}
3271
3272void GLES2DecoderImpl::DoUniform1iv(
3273 GLint location, GLsizei count, const GLint *value) {
[email protected]939e7362010-05-13 20:49:103274 if (!CheckCurrentProgramForUniform(location, "glUniform1iv")) {
[email protected]3916c97e2010-02-25 03:20:503275 return;
3276 }
3277 current_program_->SetSamplers(location, count, value);
3278 glUniform1iv(location, count, value);
3279}
3280
[email protected]939e7362010-05-13 20:49:103281void GLES2DecoderImpl::DoUniform1fv(
3282 GLint location, GLsizei count, const GLfloat* value) {
3283 GLenum type;
3284 if (!GetUniformTypeByLocation(location, "glUniform1fv", &type)) {
3285 return;
3286 }
3287 if (type == GL_BOOL) {
3288 scoped_array<GLint> temp(new GLint[count]);
3289 for (GLsizei ii = 0; ii < count; ++ii) {
3290 temp[ii] = static_cast<GLint>(value[ii]);
3291 }
3292 DoUniform1iv(location, count, temp.get());
3293 } else {
3294 glUniform1fv(location, count, value);
3295 }
3296}
3297
3298void GLES2DecoderImpl::DoUniform2fv(
3299 GLint location, GLsizei count, const GLfloat* value) {
3300 GLenum type;
3301 if (!GetUniformTypeByLocation(location, "glUniform2fv", &type)) {
3302 return;
3303 }
3304 if (type == GL_BOOL_VEC2) {
3305 GLsizei num_values = count * 2;
3306 scoped_array<GLint> temp(new GLint[num_values]);
3307 for (GLsizei ii = 0; ii < num_values; ++ii) {
3308 temp[ii] = static_cast<GLint>(value[ii]);
3309 }
3310 glUniform2iv(location, count, temp.get());
3311 } else {
3312 glUniform2fv(location, count, value);
3313 }
3314}
3315
3316void GLES2DecoderImpl::DoUniform3fv(
3317 GLint location, GLsizei count, const GLfloat* value) {
3318 GLenum type;
3319 if (!GetUniformTypeByLocation(location, "glUniform3fv", &type)) {
3320 return;
3321 }
3322 if (type == GL_BOOL_VEC3) {
3323 GLsizei num_values = count * 3;
3324 scoped_array<GLint> temp(new GLint[num_values]);
3325 for (GLsizei ii = 0; ii < num_values; ++ii) {
3326 temp[ii] = static_cast<GLint>(value[ii]);
3327 }
3328 glUniform3iv(location, count, temp.get());
3329 } else {
3330 glUniform3fv(location, count, value);
3331 }
3332}
3333
3334void GLES2DecoderImpl::DoUniform4fv(
3335 GLint location, GLsizei count, const GLfloat* value) {
3336 GLenum type;
3337 if (!GetUniformTypeByLocation(location, "glUniform4fv", &type)) {
3338 return;
3339 }
3340 if (type == GL_BOOL_VEC4) {
3341 GLsizei num_values = count * 4;
3342 scoped_array<GLint> temp(new GLint[num_values]);
3343 for (GLsizei ii = 0; ii < num_values; ++ii) {
3344 temp[ii] = static_cast<GLint>(value[ii]);
3345 }
3346 glUniform4iv(location, count, temp.get());
3347 } else {
3348 glUniform4fv(location, count, value);
3349 }
3350}
3351
[email protected]3916c97e2010-02-25 03:20:503352void GLES2DecoderImpl::DoUseProgram(GLuint program) {
[email protected]ae51d192010-04-27 00:48:033353 GLuint service_id = 0;
[email protected]3916c97e2010-02-25 03:20:503354 ProgramManager::ProgramInfo* info = NULL;
3355 if (program) {
[email protected]6b8cf1a2010-05-06 16:13:583356 info = GetProgramInfoNotShader(program, "glUseProgram");
[email protected]3916c97e2010-02-25 03:20:503357 if (!info) {
[email protected]ae51d192010-04-27 00:48:033358 return;
3359 }
3360 if (!info->IsValid()) {
[email protected]3916c97e2010-02-25 03:20:503361 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]8eee29c2010-04-29 03:38:293362 SetGLError(GL_INVALID_OPERATION, "glUseProgram: program not linked");
[email protected]3916c97e2010-02-25 03:20:503363 return;
3364 }
[email protected]ae51d192010-04-27 00:48:033365 service_id = info->service_id();
[email protected]3916c97e2010-02-25 03:20:503366 }
3367 current_program_ = info;
[email protected]ae51d192010-04-27 00:48:033368 glUseProgram(service_id);
[email protected]3916c97e2010-02-25 03:20:503369}
3370
[email protected]96449d2c2009-11-25 00:01:323371GLenum GLES2DecoderImpl::GetGLError() {
3372 // Check the GL error first, then our wrapped error.
3373 GLenum error = glGetError();
3374 if (error == GL_NO_ERROR && error_bits_ != 0) {
[email protected]03f882a2010-01-08 20:46:373375 for (uint32 mask = 1; mask != 0; mask = mask << 1) {
[email protected]96449d2c2009-11-25 00:01:323376 if ((error_bits_ & mask) != 0) {
[email protected]ddd968b82010-03-02 00:44:293377 error = GLES2Util::GLErrorBitToGLError(mask);
[email protected]96449d2c2009-11-25 00:01:323378 break;
3379 }
3380 }
3381 }
3382
3383 if (error != GL_NO_ERROR) {
3384 // There was an error, clear the corresponding wrapped error.
[email protected]ddd968b82010-03-02 00:44:293385 error_bits_ &= ~GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:323386 }
3387 return error;
3388}
3389
[email protected]8eee29c2010-04-29 03:38:293390void GLES2DecoderImpl::SetGLError(GLenum error, const char* msg) {
3391 if (msg) {
3392 last_error_ = msg;
3393 DLOG(ERROR) << last_error_;
3394 }
[email protected]ddd968b82010-03-02 00:44:293395 error_bits_ |= GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:323396}
3397
[email protected]07f54fcc2009-12-22 02:46:303398void GLES2DecoderImpl::CopyRealGLErrorsToWrapper() {
3399 GLenum error;
3400 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]8eee29c2010-04-29 03:38:293401 SetGLError(error, NULL);
[email protected]07f54fcc2009-12-22 02:46:303402 }
3403}
3404
[email protected]6217d392010-03-25 22:08:353405void GLES2DecoderImpl::ClearRealGLErrors() {
3406 GLenum error;
3407 while ((error = glGetError()) != GL_NO_ERROR) {
3408 NOTREACHED() << "GL error " << error << " was unhandled.";
3409 }
3410}
3411
[email protected]ef526492010-06-02 23:12:253412bool GLES2DecoderImpl::SetBlackTextureForNonRenderableTextures() {
[email protected]3916c97e2010-02-25 03:20:503413 DCHECK(current_program_);
3414 DCHECK(!current_program_->IsDeleted());
[email protected]ef526492010-06-02 23:12:253415 // Only check if there are some unrenderable textures.
3416 if (!texture_manager()->HaveUnrenderableTextures()) {
3417 return false;
3418 }
3419 bool textures_set = false;
[email protected]3916c97e2010-02-25 03:20:503420 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
3421 current_program_->sampler_indices();
3422 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
3423 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
3424 current_program_->GetUniformInfo(sampler_indices[ii]);
3425 DCHECK(uniform_info);
3426 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
3427 GLuint texture_unit_index = uniform_info->texture_units[jj];
3428 if (texture_unit_index < group_->max_texture_units()) {
3429 TextureUnit& texture_unit = texture_units_[texture_unit_index];
3430 TextureManager::TextureInfo* texture_info =
3431 uniform_info->type == GL_SAMPLER_2D ?
3432 texture_unit.bound_texture_2d :
3433 texture_unit.bound_texture_cube_map;
[email protected]7488d962010-07-16 02:41:583434 if (!texture_info || !texture_info->CanRender(texture_manager())) {
[email protected]ef526492010-06-02 23:12:253435 textures_set = true;
[email protected]3916c97e2010-02-25 03:20:503436 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
3437 glBindTexture(
3438 uniform_info->type == GL_SAMPLER_2D ? GL_TEXTURE_2D :
3439 GL_TEXTURE_CUBE_MAP,
[email protected]00f893d2010-08-24 18:55:493440 texture_manager()->black_texture_id(uniform_info->type));
[email protected]3916c97e2010-02-25 03:20:503441 }
3442 }
3443 // else: should this be an error?
3444 }
3445 }
[email protected]ef526492010-06-02 23:12:253446 return textures_set;
[email protected]3916c97e2010-02-25 03:20:503447}
3448
3449void GLES2DecoderImpl::RestoreStateForNonRenderableTextures() {
3450 DCHECK(current_program_);
3451 DCHECK(!current_program_->IsDeleted());
3452 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
3453 current_program_->sampler_indices();
3454 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
3455 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
3456 current_program_->GetUniformInfo(sampler_indices[ii]);
3457 DCHECK(uniform_info);
3458 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
3459 GLuint texture_unit_index = uniform_info->texture_units[jj];
3460 if (texture_unit_index < group_->max_texture_units()) {
3461 TextureUnit& texture_unit = texture_units_[texture_unit_index];
3462 TextureManager::TextureInfo* texture_info =
3463 uniform_info->type == GL_SAMPLER_2D ?
3464 texture_unit.bound_texture_2d :
3465 texture_unit.bound_texture_cube_map;
[email protected]7488d962010-07-16 02:41:583466 if (!texture_info || !texture_info->CanRender(texture_manager())) {
[email protected]3916c97e2010-02-25 03:20:503467 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
3468 // Get the texture info that was previously bound here.
3469 texture_info = texture_unit.bind_target == GL_TEXTURE_2D ?
3470 texture_unit.bound_texture_2d :
3471 texture_unit.bound_texture_cube_map;
3472 glBindTexture(texture_unit.bind_target,
[email protected]ae51d192010-04-27 00:48:033473 texture_info ? texture_info->service_id() : 0);
[email protected]3916c97e2010-02-25 03:20:503474 }
3475 }
3476 }
3477 }
3478 // Set the active texture back to whatever the user had it as.
3479 glActiveTexture(GL_TEXTURE0 + active_texture_unit_);
[email protected]07f54fcc2009-12-22 02:46:303480}
3481
3482bool GLES2DecoderImpl::IsDrawValid(GLuint max_vertex_accessed) {
[email protected]689fa1c52010-06-09 18:35:033483 // NOTE: We specifically do not check current_program->IsValid() because
3484 // it could never be invalid since glUseProgram would have failed. While
3485 // glLinkProgram could later mark the program as invalid the previous
3486 // valid program will still function if it is still the current program.
3487 if (!current_program_ || current_program_->IsDeleted()) {
[email protected]3916c97e2010-02-25 03:20:503488 // The program does not exist.
3489 // But GL says no ERROR.
3490 return false;
3491 }
[email protected]f39f4b3f2010-05-12 17:04:083492 // Validate all attribs currently enabled. If they are used by the current
3493 // program then check that they have enough elements to handle the draw call.
3494 // If they are not used by the current program check that they have a buffer
3495 // assigned.
3496 const VertexAttribManager::VertexAttribInfoList& infos =
3497 vertex_attrib_manager_.GetEnabledVertexAttribInfos();
3498 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
3499 infos.begin(); it != infos.end(); ++it) {
3500 const VertexAttribManager::VertexAttribInfo* info = *it;
3501 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
3502 current_program_->GetAttribInfoByLocation(info->index());
3503 if (attrib_info) {
3504 // This attrib is used in the current program.
3505 if (!info->CanAccess(max_vertex_accessed)) {
3506 SetGLError(GL_INVALID_OPERATION,
3507 "glDrawXXX: attempt to access out of range vertices");
3508 return false;
3509 }
3510 } else {
3511 // This attrib is not used in the current program.
3512 if (!info->buffer() || info->buffer()->IsDeleted()) {
3513 SetGLError(
3514 GL_INVALID_OPERATION,
3515 "glDrawXXX: attempt to render with no buffer attached to enabled "
3516 "attrib");
3517 return false;
3518 }
[email protected]1d32bc82010-01-13 22:06:463519 }
[email protected]07f54fcc2009-12-22 02:46:303520 }
[email protected]3916c97e2010-02-25 03:20:503521 return true;
[email protected]b1122982010-05-17 23:04:243522}
3523
3524bool GLES2DecoderImpl::SimulateAttrib0(GLuint max_vertex_accessed) {
[email protected]876f6fee2010-08-02 23:10:323525 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
3526 return false;
3527
[email protected]b1122982010-05-17 23:04:243528 const VertexAttribManager::VertexAttribInfo* info =
3529 vertex_attrib_manager_.GetVertexAttribInfo(0);
3530 // If it's enabled or it's not used then we don't need to do anything.
3531 if (info->enabled() || !current_program_->GetAttribInfoByLocation(0)) {
3532 return false;
3533 }
3534
3535 typedef VertexAttribManager::VertexAttribInfo::Vec4 Vec4;
3536
3537 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
3538
3539 // Make a buffer with a single repeated vec4 value enough to
3540 // simulate the constant value that is supposed to be here.
3541 // This is required to emulate GLES2 on GL.
3542 GLsizei num_vertices = max_vertex_accessed + 1;
3543 GLsizei size_needed = num_vertices * sizeof(Vec4); // NOLINT
3544 if (size_needed > attrib_0_size_ ||
3545 info->value().v[0] != attrib_0_value_.v[0] ||
3546 info->value().v[1] != attrib_0_value_.v[1] ||
3547 info->value().v[2] != attrib_0_value_.v[2] ||
3548 info->value().v[3] != attrib_0_value_.v[3]) {
3549 scoped_array<Vec4> temp(new Vec4[num_vertices]);
3550 for (GLsizei ii = 0; ii < num_vertices; ++ii) {
3551 temp[ii] = info->value();
3552 }
3553 glBufferData(
3554 GL_ARRAY_BUFFER,
3555 size_needed,
3556 &temp[0].v[0],
3557 GL_DYNAMIC_DRAW);
3558 attrib_0_value_ = info->value();
3559 attrib_0_size_ = size_needed;
3560 }
3561
3562 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
3563
3564 return true;
[email protected]b1122982010-05-17 23:04:243565}
3566
3567void GLES2DecoderImpl::RestoreStateForSimulatedAttrib0() {
3568 const VertexAttribManager::VertexAttribInfo* info =
3569 vertex_attrib_manager_.GetVertexAttribInfo(0);
3570 const void* ptr = reinterpret_cast<const void*>(info->offset());
3571 BufferManager::BufferInfo* buffer_info = info->buffer();
3572 glBindBuffer(GL_ARRAY_BUFFER, buffer_info ? buffer_info->service_id() : 0);
3573 glVertexAttribPointer(
3574 0, info->size(), info->type(), info->normalized(), info->gl_stride(),
3575 ptr);
3576 glBindBuffer(GL_ARRAY_BUFFER,
3577 bound_array_buffer_ ? bound_array_buffer_->service_id() : 0);
3578}
[email protected]07f54fcc2009-12-22 02:46:303579
[email protected]f7a64ee2010-02-01 22:24:143580error::Error GLES2DecoderImpl::HandleDrawElements(
[email protected]b9849abf2009-11-25 19:13:193581 uint32 immediate_data_size, const gles2::DrawElements& c) {
[email protected]3916c97e2010-02-25 03:20:503582 if (!bound_element_array_buffer_ ||
3583 bound_element_array_buffer_->IsDeleted()) {
[email protected]8eee29c2010-04-29 03:38:293584 SetGLError(GL_INVALID_OPERATION,
3585 "glDrawElements: No element array buffer bound");
3586 return error::kNoError;
3587 }
3588
3589 GLenum mode = c.mode;
3590 GLsizei count = c.count;
3591 GLenum type = c.type;
3592 int32 offset = c.index_offset;
3593 if (count < 0) {
3594 SetGLError(GL_INVALID_VALUE, "glDrawElements: count < 0");
3595 return error::kNoError;
3596 }
3597 if (offset < 0) {
3598 SetGLError(GL_INVALID_VALUE, "glDrawElements: offset < 0");
3599 return error::kNoError;
3600 }
[email protected]9438b012010-06-15 22:55:053601 if (!validators_->draw_mode.IsValid(mode)) {
[email protected]8eee29c2010-04-29 03:38:293602 SetGLError(GL_INVALID_ENUM, "glDrawElements: mode GL_INVALID_ENUM");
3603 return error::kNoError;
3604 }
[email protected]9438b012010-06-15 22:55:053605 if (!validators_->index_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:293606 SetGLError(GL_INVALID_ENUM, "glDrawElements: type GL_INVALID_ENUM");
3607 return error::kNoError;
3608 }
3609
[email protected]6c788fb72010-08-26 02:16:313610 if (count == 0) {
3611 return error::kNoError;
3612 }
3613
[email protected]8eee29c2010-04-29 03:38:293614 GLuint max_vertex_accessed;
3615 if (!bound_element_array_buffer_->GetMaxValueForRange(
3616 offset, count, type, &max_vertex_accessed)) {
3617 SetGLError(GL_INVALID_OPERATION,
3618 "glDrawElements: range out of bounds for buffer");
3619 return error::kNoError;
3620 }
3621
3622 if (IsDrawValid(max_vertex_accessed)) {
[email protected]b1122982010-05-17 23:04:243623 bool simulated_attrib_0 = SimulateAttrib0(max_vertex_accessed);
[email protected]ef526492010-06-02 23:12:253624 bool textures_set = SetBlackTextureForNonRenderableTextures();
[email protected]8eee29c2010-04-29 03:38:293625 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
3626 glDrawElements(mode, count, type, indices);
[email protected]ef526492010-06-02 23:12:253627 if (textures_set) {
[email protected]8eee29c2010-04-29 03:38:293628 RestoreStateForNonRenderableTextures();
[email protected]ba3176a2009-12-16 18:19:463629 }
[email protected]b1122982010-05-17 23:04:243630 if (simulated_attrib_0) {
3631 RestoreStateForSimulatedAttrib0();
3632 }
[email protected]96449d2c2009-11-25 00:01:323633 }
[email protected]f7a64ee2010-02-01 22:24:143634 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323635}
3636
[email protected]29a9eb52010-04-13 09:04:233637GLuint GLES2DecoderImpl::DoGetMaxValueInBuffer(
3638 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
3639 GLuint max_vertex_accessed = 0;
3640 BufferManager::BufferInfo* info = GetBufferInfo(buffer_id);
[email protected]8eee29c2010-04-29 03:38:293641 if (!info) {
[email protected]ae51d192010-04-27 00:48:033642 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]8eee29c2010-04-29 03:38:293643 SetGLError(GL_INVALID_VALUE,
3644 "GetMaxValueInBuffer: unknown buffer");
[email protected]29a9eb52010-04-13 09:04:233645 } else {
3646 if (!info->GetMaxValueForRange(offset, count, type, &max_vertex_accessed)) {
[email protected]ae51d192010-04-27 00:48:033647 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]8eee29c2010-04-29 03:38:293648 SetGLError(GL_INVALID_OPERATION,
3649 "GetMaxValueInBuffer: range out of bounds for buffer");
[email protected]29a9eb52010-04-13 09:04:233650 }
3651 }
3652 return max_vertex_accessed;
3653}
3654
[email protected]96449d2c2009-11-25 00:01:323655// Calls glShaderSource for the various versions of the ShaderSource command.
3656// Assumes that data / data_size points to a piece of memory that is in range
3657// of whatever context it came from (shared memory, immediate memory, bucket
3658// memory.)
[email protected]45bf5152010-02-12 00:11:313659error::Error GLES2DecoderImpl::ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:033660 GLuint client_id, const char* data, uint32 data_size) {
[email protected]6b8cf1a2010-05-06 16:13:583661 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
3662 client_id, "glShaderSource");
[email protected]45bf5152010-02-12 00:11:313663 if (!info) {
[email protected]45bf5152010-02-12 00:11:313664 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323665 }
[email protected]45bf5152010-02-12 00:11:313666 // Note: We don't actually call glShaderSource here. We wait until
3667 // the call to glCompileShader.
3668 info->Update(std::string(data, data + data_size));
[email protected]f7a64ee2010-02-01 22:24:143669 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323670}
3671
[email protected]f7a64ee2010-02-01 22:24:143672error::Error GLES2DecoderImpl::HandleShaderSource(
[email protected]b9849abf2009-11-25 19:13:193673 uint32 immediate_data_size, const gles2::ShaderSource& c) {
[email protected]96449d2c2009-11-25 00:01:323674 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:313675 const char* data = GetSharedMemoryAs<const char*>(
[email protected]96449d2c2009-11-25 00:01:323676 c.data_shm_id, c.data_shm_offset, data_size);
[email protected]ba3176a2009-12-16 18:19:463677 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:143678 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:323679 }
[email protected]ae51d192010-04-27 00:48:033680 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]96449d2c2009-11-25 00:01:323681}
3682
[email protected]f7a64ee2010-02-01 22:24:143683error::Error GLES2DecoderImpl::HandleShaderSourceImmediate(
[email protected]b9849abf2009-11-25 19:13:193684 uint32 immediate_data_size, const gles2::ShaderSourceImmediate& c) {
[email protected]96449d2c2009-11-25 00:01:323685 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:313686 const char* data = GetImmediateDataAs<const char*>(
[email protected]07f54fcc2009-12-22 02:46:303687 c, data_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:463688 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:143689 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:323690 }
[email protected]ae51d192010-04-27 00:48:033691 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]45bf5152010-02-12 00:11:313692}
3693
[email protected]558847a2010-03-24 07:02:543694error::Error GLES2DecoderImpl::HandleShaderSourceBucket(
3695 uint32 immediate_data_size, const gles2::ShaderSourceBucket& c) {
[email protected]558847a2010-03-24 07:02:543696 Bucket* bucket = GetBucket(c.data_bucket_id);
3697 if (!bucket || bucket->size() == 0) {
3698 return error::kInvalidArguments;
3699 }
3700 return ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:033701 c.shader, bucket->GetDataAs<const char*>(0, bucket->size() - 1),
[email protected]558847a2010-03-24 07:02:543702 bucket->size() - 1);
3703}
3704
[email protected]ae51d192010-04-27 00:48:033705void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
[email protected]6b8cf1a2010-05-06 16:13:583706 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
3707 client_id, "glCompileShader");
[email protected]45bf5152010-02-12 00:11:313708 if (!info) {
[email protected]45bf5152010-02-12 00:11:313709 return;
3710 }
[email protected]de17df392010-04-23 21:09:413711 // Translate GL ES 2.0 shader to Desktop GL shader and pass that to
3712 // glShaderSource and then glCompileShader.
3713 const char* shader_src = info->source().c_str();
[email protected]b1d2dcb2010-05-17 19:24:183714 if (use_shader_translator_) {
3715 int dbg_options = 0;
[email protected]5236b752010-07-27 18:02:233716 ShHandle compiler = info->shader_type() == GL_VERTEX_SHADER ?
3717 vertex_compiler_ : fragment_compiler_;
3718
3719 if (!ShCompile(compiler, &shader_src, 1, EShOptNone, dbg_options)) {
[email protected]e5186162010-06-14 18:54:413720 info->SetStatus(false, ShGetInfoLog(compiler));
[email protected]b1d2dcb2010-05-17 19:24:183721 return;
3722 }
3723 shader_src = ShGetObjectCode(compiler);
[email protected]de17df392010-04-23 21:09:413724 }
[email protected]de17df392010-04-23 21:09:413725
[email protected]ae51d192010-04-27 00:48:033726 glShaderSource(info->service_id(), 1, &shader_src, NULL);
3727 glCompileShader(info->service_id());
[email protected]e5186162010-06-14 18:54:413728 GLint status = GL_FALSE;
3729 glGetShaderiv(info->service_id(), GL_COMPILE_STATUS, &status);
3730 if (status) {
3731 info->SetStatus(true, "");
3732 } else {
3733 GLint len = 0;
3734 glGetShaderiv(info->service_id(), GL_INFO_LOG_LENGTH, &len);
3735 scoped_array<char> temp(new char[len]);
3736 glGetShaderInfoLog(info->service_id(), len, &len, temp.get());
3737 info->SetStatus(false, std::string(temp.get(), len));
3738 }
[email protected]45bf5152010-02-12 00:11:313739};
3740
[email protected]ddd968b82010-03-02 00:44:293741void GLES2DecoderImpl::DoGetShaderiv(
3742 GLuint shader, GLenum pname, GLint* params) {
[email protected]6b8cf1a2010-05-06 16:13:583743 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
3744 shader, "glGetShaderiv");
[email protected]ddd968b82010-03-02 00:44:293745 if (!info) {
[email protected]ddd968b82010-03-02 00:44:293746 return;
3747 }
[email protected]8f1ccdac2010-05-19 21:01:483748 switch (pname) {
3749 case GL_SHADER_SOURCE_LENGTH:
3750 *params = info->source().size();
3751 return;
3752 case GL_COMPILE_STATUS:
[email protected]e5186162010-06-14 18:54:413753 *params = info->IsValid();
3754 return;
[email protected]8f1ccdac2010-05-19 21:01:483755 case GL_INFO_LOG_LENGTH:
[email protected]e5186162010-06-14 18:54:413756 *params = info->log_info().size() + 1;
3757 return;
[email protected]8f1ccdac2010-05-19 21:01:483758 default:
3759 break;
[email protected]ddd968b82010-03-02 00:44:293760 }
[email protected]8f1ccdac2010-05-19 21:01:483761 glGetShaderiv(info->service_id(), pname, params);
[email protected]ddd968b82010-03-02 00:44:293762}
3763
[email protected]ae51d192010-04-27 00:48:033764error::Error GLES2DecoderImpl::HandleGetShaderSource(
3765 uint32 immediate_data_size, const gles2::GetShaderSource& c) {
3766 GLuint shader = c.shader;
[email protected]ae51d192010-04-27 00:48:033767 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
3768 Bucket* bucket = CreateBucket(bucket_id);
[email protected]6b8cf1a2010-05-06 16:13:583769 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
3770 shader, "glGetShaderSource");
[email protected]8eee29c2010-04-29 03:38:293771 if (!info) {
3772 bucket->SetSize(0);
[email protected]8eee29c2010-04-29 03:38:293773 return error::kNoError;
3774 }
[email protected]ae51d192010-04-27 00:48:033775 bucket->SetFromString(info->source());
3776 return error::kNoError;
3777}
3778
3779error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
3780 uint32 immediate_data_size, const gles2::GetProgramInfoLog& c) {
3781 GLuint program = c.program;
[email protected]6b8cf1a2010-05-06 16:13:583782 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
3783 Bucket* bucket = CreateBucket(bucket_id);
3784 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3785 program, "glGetProgramInfoLog");
[email protected]ae51d192010-04-27 00:48:033786 if (!info) {
[email protected]ae51d192010-04-27 00:48:033787 return error::kNoError;
[email protected]45bf5152010-02-12 00:11:313788 }
[email protected]e5186162010-06-14 18:54:413789 bucket->SetFromString(info->log_info());
[email protected]ae51d192010-04-27 00:48:033790 return error::kNoError;
3791}
3792
3793error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
3794 uint32 immediate_data_size, const gles2::GetShaderInfoLog& c) {
3795 GLuint shader = c.shader;
[email protected]6b8cf1a2010-05-06 16:13:583796 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
3797 Bucket* bucket = CreateBucket(bucket_id);
3798 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
3799 shader, "glGetShaderInfoLog");
[email protected]ae51d192010-04-27 00:48:033800 if (!info) {
[email protected]6b8cf1a2010-05-06 16:13:583801 bucket->SetSize(0);
[email protected]ae51d192010-04-27 00:48:033802 return error::kNoError;
3803 }
[email protected]e5186162010-06-14 18:54:413804 bucket->SetFromString(info->log_info());
[email protected]ae51d192010-04-27 00:48:033805 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323806}
3807
[email protected]1958e0e2010-04-22 05:17:153808bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:033809 return GetBufferInfo(client_id) != NULL;
[email protected]1958e0e2010-04-22 05:17:153810}
3811
3812bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:033813 return GetFramebufferInfo(client_id) != NULL;
[email protected]1958e0e2010-04-22 05:17:153814}
3815
3816bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:033817 return GetProgramInfo(client_id) != NULL;
[email protected]1958e0e2010-04-22 05:17:153818}
3819
3820bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:033821 return GetRenderbufferInfo(client_id) != NULL;
[email protected]1958e0e2010-04-22 05:17:153822}
3823
3824bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:033825 return GetShaderInfo(client_id) != NULL;
[email protected]1958e0e2010-04-22 05:17:153826}
3827
3828bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:033829 return GetTextureInfo(client_id) != NULL;
3830}
3831
3832void GLES2DecoderImpl::DoAttachShader(
3833 GLuint program_client_id, GLint shader_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:583834 ProgramManager::ProgramInfo* program_info = GetProgramInfoNotShader(
3835 program_client_id, "glAttachShader");
[email protected]ae51d192010-04-27 00:48:033836 if (!program_info) {
[email protected]ae51d192010-04-27 00:48:033837 return;
[email protected]1958e0e2010-04-22 05:17:153838 }
[email protected]6b8cf1a2010-05-06 16:13:583839 ShaderManager::ShaderInfo* shader_info = GetShaderInfoNotProgram(
3840 shader_client_id, "glAttachShader");
[email protected]ae51d192010-04-27 00:48:033841 if (!shader_info) {
[email protected]ae51d192010-04-27 00:48:033842 return;
3843 }
[email protected]fb96c8e2010-08-12 04:10:313844 if (!program_info->AttachShader(shader_info)) {
3845 SetGLError(GL_INVALID_OPERATION,
3846 "glAttachShader: can not attach more than"
3847 " one shader of the same type.");
3848 return;
3849 }
[email protected]ae51d192010-04-27 00:48:033850 glAttachShader(program_info->service_id(), shader_info->service_id());
3851}
3852
3853void GLES2DecoderImpl::DoDetachShader(
3854 GLuint program_client_id, GLint shader_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:583855 ProgramManager::ProgramInfo* program_info = GetProgramInfoNotShader(
3856 program_client_id, "glDetachShader");
[email protected]ae51d192010-04-27 00:48:033857 if (!program_info) {
[email protected]ae51d192010-04-27 00:48:033858 return;
3859 }
[email protected]6b8cf1a2010-05-06 16:13:583860 ShaderManager::ShaderInfo* shader_info = GetShaderInfoNotProgram(
3861 shader_client_id, "glDetachShader");
[email protected]ae51d192010-04-27 00:48:033862 if (!shader_info) {
[email protected]ae51d192010-04-27 00:48:033863 return;
3864 }
[email protected]d81e8c52010-06-07 17:58:323865 program_info->DetachShader(shader_info);
[email protected]ae51d192010-04-27 00:48:033866 glDetachShader(program_info->service_id(), shader_info->service_id());
3867}
3868
3869void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:583870 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3871 program_client_id, "glValidateProgram");
[email protected]ae51d192010-04-27 00:48:033872 if (!info) {
[email protected]ae51d192010-04-27 00:48:033873 return;
3874 }
[email protected]e5186162010-06-14 18:54:413875 if (!info->CanLink()) {
3876 info->set_log_info("Missing Shader");
3877 return;
3878 }
[email protected]ae51d192010-04-27 00:48:033879 glValidateProgram(info->service_id());
[email protected]e5186162010-06-14 18:54:413880 info->UpdateLogInfo();
[email protected]1958e0e2010-04-22 05:17:153881}
3882
[email protected]b1122982010-05-17 23:04:243883void GLES2DecoderImpl::DoGetVertexAttribfv(
3884 GLuint index, GLenum pname, GLfloat* params) {
3885 VertexAttribManager::VertexAttribInfo* info =
3886 vertex_attrib_manager_.GetVertexAttribInfo(index);
3887 if (!info) {
3888 SetGLError(GL_INVALID_VALUE, "glGetVertexAttribfv: index out of range");
3889 return;
3890 }
3891 switch (pname) {
3892 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
3893 BufferManager::BufferInfo* buffer = info->buffer();
3894 if (buffer && !buffer->IsDeleted()) {
3895 GLuint client_id;
3896 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
3897 *params = static_cast<GLfloat>(client_id);
3898 }
3899 break;
3900 }
3901 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
3902 *params = static_cast<GLfloat>(info->enabled());
3903 break;
3904 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
3905 *params = static_cast<GLfloat>(info->size());
3906 break;
3907 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
3908 *params = static_cast<GLfloat>(info->gl_stride());
3909 break;
3910 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
3911 *params = static_cast<GLfloat>(info->type());
3912 break;
3913 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
3914 *params = static_cast<GLfloat>(info->normalized());
3915 break;
3916 case GL_CURRENT_VERTEX_ATTRIB:
3917 params[0] = info->value().v[0];
3918 params[1] = info->value().v[1];
3919 params[2] = info->value().v[2];
3920 params[3] = info->value().v[3];
3921 break;
3922 default:
3923 NOTREACHED();
3924 break;
3925 }
3926}
3927
3928void GLES2DecoderImpl::DoGetVertexAttribiv(
3929 GLuint index, GLenum pname, GLint* params) {
3930 VertexAttribManager::VertexAttribInfo* info =
3931 vertex_attrib_manager_.GetVertexAttribInfo(index);
3932 if (!info) {
3933 SetGLError(GL_INVALID_VALUE, "glGetVertexAttribiv: index out of range");
3934 return;
3935 }
3936 switch (pname) {
3937 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
3938 BufferManager::BufferInfo* buffer = info->buffer();
3939 if (buffer && !buffer->IsDeleted()) {
3940 GLuint client_id;
3941 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
3942 *params = client_id;
3943 }
3944 break;
3945 }
3946 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
3947 *params = info->enabled();
3948 break;
3949 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
3950 *params = info->size();
3951 break;
3952 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
3953 *params = info->gl_stride();
3954 break;
3955 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
3956 *params = info->type();
3957 break;
3958 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
3959 *params = static_cast<GLint>(info->normalized());
3960 break;
3961 case GL_CURRENT_VERTEX_ATTRIB:
3962 params[0] = static_cast<GLint>(info->value().v[0]);
3963 params[1] = static_cast<GLint>(info->value().v[1]);
3964 params[2] = static_cast<GLint>(info->value().v[2]);
3965 params[3] = static_cast<GLint>(info->value().v[3]);
3966 break;
3967 default:
3968 NOTREACHED();
3969 break;
3970 }
3971}
3972
3973void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
3974 VertexAttribManager::VertexAttribInfo* info =
3975 vertex_attrib_manager_.GetVertexAttribInfo(index);
3976 if (!info) {
3977 SetGLError(GL_INVALID_VALUE, "glVertexAttrib1f: index out of range");
3978 return;
3979 }
3980 VertexAttribManager::VertexAttribInfo::Vec4 value;
3981 value.v[0] = v0;
3982 value.v[1] = 0.0f;
3983 value.v[2] = 0.0f;
3984 value.v[3] = 1.0f;
3985 info->set_value(value);
3986 glVertexAttrib1f(index, v0);
3987}
3988
3989void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
3990 VertexAttribManager::VertexAttribInfo* info =
3991 vertex_attrib_manager_.GetVertexAttribInfo(index);
3992 if (!info) {
3993 SetGLError(GL_INVALID_VALUE, "glVertexAttrib2f: index out of range");
3994 return;
3995 }
3996 VertexAttribManager::VertexAttribInfo::Vec4 value;
3997 value.v[0] = v0;
3998 value.v[1] = v1;
3999 value.v[2] = 0.0f;
4000 value.v[3] = 1.0f;
4001 info->set_value(value);
4002 glVertexAttrib2f(index, v0, v1);
4003}
4004
4005void GLES2DecoderImpl::DoVertexAttrib3f(
4006 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
4007 VertexAttribManager::VertexAttribInfo* info =
4008 vertex_attrib_manager_.GetVertexAttribInfo(index);
4009 if (!info) {
4010 SetGLError(GL_INVALID_VALUE, "glVertexAttrib3f: index out of range");
4011 return;
4012 }
4013 VertexAttribManager::VertexAttribInfo::Vec4 value;
4014 value.v[0] = v0;
4015 value.v[1] = v1;
4016 value.v[2] = v2;
4017 value.v[3] = 1.0f;
4018 info->set_value(value);
4019 glVertexAttrib3f(index, v0, v1, v2);
4020}
4021
4022void GLES2DecoderImpl::DoVertexAttrib4f(
4023 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
4024 VertexAttribManager::VertexAttribInfo* info =
4025 vertex_attrib_manager_.GetVertexAttribInfo(index);
4026 if (!info) {
4027 SetGLError(GL_INVALID_VALUE, "glVertexAttrib4f: index out of range");
4028 return;
4029 }
4030 VertexAttribManager::VertexAttribInfo::Vec4 value;
4031 value.v[0] = v0;
4032 value.v[1] = v1;
4033 value.v[2] = v2;
4034 value.v[3] = v3;
4035 info->set_value(value);
4036 glVertexAttrib4f(index, v0, v1, v2, v3);
4037}
4038
4039void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
4040 VertexAttribManager::VertexAttribInfo* info =
4041 vertex_attrib_manager_.GetVertexAttribInfo(index);
4042 if (!info) {
4043 SetGLError(GL_INVALID_VALUE, "glVertexAttrib1fv: index out of range");
4044 return;
4045 }
4046 VertexAttribManager::VertexAttribInfo::Vec4 value;
4047 value.v[0] = v[0];
4048 value.v[1] = 0.0f;
4049 value.v[2] = 0.0f;
4050 value.v[3] = 1.0f;
4051 info->set_value(value);
4052 glVertexAttrib1fv(index, v);
4053}
4054
4055void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
4056 VertexAttribManager::VertexAttribInfo* info =
4057 vertex_attrib_manager_.GetVertexAttribInfo(index);
4058 if (!info) {
4059 SetGLError(GL_INVALID_VALUE, "glVertexAttrib2fv: index out of range");
4060 return;
4061 }
4062 VertexAttribManager::VertexAttribInfo::Vec4 value;
4063 value.v[0] = v[0];
4064 value.v[1] = v[1];
4065 value.v[2] = 0.0f;
4066 value.v[3] = 1.0f;
4067 info->set_value(value);
4068 glVertexAttrib2fv(index, v);
4069}
4070
4071void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
4072 VertexAttribManager::VertexAttribInfo* info =
4073 vertex_attrib_manager_.GetVertexAttribInfo(index);
4074 if (!info) {
4075 SetGLError(GL_INVALID_VALUE, "glVertexAttrib3fv: index out of range");
4076 return;
4077 }
4078 VertexAttribManager::VertexAttribInfo::Vec4 value;
4079 value.v[0] = v[0];
4080 value.v[1] = v[1];
4081 value.v[2] = v[2];
4082 value.v[3] = 1.0f;
4083 info->set_value(value);
4084 glVertexAttrib3fv(index, v);
4085}
4086
4087void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
4088 VertexAttribManager::VertexAttribInfo* info =
4089 vertex_attrib_manager_.GetVertexAttribInfo(index);
4090 if (!info) {
4091 SetGLError(GL_INVALID_VALUE, "glVertexAttrib4fv: index out of range");
4092 return;
4093 }
4094 VertexAttribManager::VertexAttribInfo::Vec4 value;
4095 value.v[0] = v[0];
4096 value.v[1] = v[1];
4097 value.v[2] = v[2];
4098 value.v[3] = v[3];
4099 info->set_value(value);
4100 glVertexAttrib4fv(index, v);
4101}
4102
[email protected]f7a64ee2010-02-01 22:24:144103error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
[email protected]b9849abf2009-11-25 19:13:194104 uint32 immediate_data_size, const gles2::VertexAttribPointer& c) {
[email protected]8eee29c2010-04-29 03:38:294105 if (!bound_array_buffer_ || bound_array_buffer_->IsDeleted()) {
4106 SetGLError(GL_INVALID_VALUE,
4107 "glVertexAttribPointer: no array buffer bound");
4108 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324109 }
[email protected]8eee29c2010-04-29 03:38:294110
4111 GLuint indx = c.indx;
4112 GLint size = c.size;
4113 GLenum type = c.type;
4114 GLboolean normalized = c.normalized;
4115 GLsizei stride = c.stride;
4116 GLsizei offset = c.offset;
4117 const void* ptr = reinterpret_cast<const void*>(offset);
[email protected]9438b012010-06-15 22:55:054118 if (!validators_->vertex_attrib_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:294119 SetGLError(GL_INVALID_ENUM,
4120 "glVertexAttribPointer: type GL_INVALID_ENUM");
4121 return error::kNoError;
4122 }
[email protected]9438b012010-06-15 22:55:054123 if (!validators_->vertex_attrib_size.IsValid(size)) {
[email protected]8eee29c2010-04-29 03:38:294124 SetGLError(GL_INVALID_ENUM,
4125 "glVertexAttribPointer: size GL_INVALID_VALUE");
4126 return error::kNoError;
4127 }
4128 if (indx >= group_->max_vertex_attribs()) {
4129 SetGLError(GL_INVALID_VALUE, "glVertexAttribPointer: index out of range");
4130 return error::kNoError;
4131 }
4132 if (stride < 0) {
4133 SetGLError(GL_INVALID_VALUE,
4134 "glVertexAttribPointer: stride < 0");
4135 return error::kNoError;
4136 }
4137 if (stride > 255) {
4138 SetGLError(GL_INVALID_VALUE,
4139 "glVertexAttribPointer: stride > 255");
4140 return error::kNoError;
4141 }
4142 if (offset < 0) {
4143 SetGLError(GL_INVALID_VALUE,
4144 "glVertexAttribPointer: offset < 0");
4145 return error::kNoError;
4146 }
4147 GLsizei component_size =
4148 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
[email protected]8eee29c2010-04-29 03:38:294149 if (offset % component_size > 0) {
4150 SetGLError(GL_INVALID_VALUE,
4151 "glVertexAttribPointer: stride not valid for type");
4152 return error::kNoError;
4153 }
[email protected]f39f4b3f2010-05-12 17:04:084154 vertex_attrib_manager_.GetVertexAttribInfo(indx)->SetInfo(
[email protected]8eee29c2010-04-29 03:38:294155 bound_array_buffer_,
4156 size,
4157 type,
[email protected]b1122982010-05-17 23:04:244158 normalized,
4159 stride,
4160 stride != 0 ? stride : component_size * size,
[email protected]8eee29c2010-04-29 03:38:294161 offset);
4162 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
[email protected]f7a64ee2010-02-01 22:24:144163 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324164}
4165
[email protected]f7a64ee2010-02-01 22:24:144166error::Error GLES2DecoderImpl::HandleReadPixels(
[email protected]b9849abf2009-11-25 19:13:194167 uint32 immediate_data_size, const gles2::ReadPixels& c) {
[email protected]612d2f82009-12-08 20:49:314168 GLint x = c.x;
4169 GLint y = c.y;
4170 GLsizei width = c.width;
4171 GLsizei height = c.height;
4172 GLenum format = c.format;
4173 GLenum type = c.type;
[email protected]57f223832010-03-19 01:57:564174 if (width < 0 || height < 0) {
[email protected]8eee29c2010-04-29 03:38:294175 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions < 0");
[email protected]57f223832010-03-19 01:57:564176 return error::kNoError;
4177 }
[email protected]a51788e2010-02-24 21:54:254178 typedef gles2::ReadPixels::Result Result;
[email protected]a76b0052010-03-05 00:33:184179 uint32 pixels_size;
4180 if (!GLES2Util::ComputeImageDataSize(
4181 width, height, format, type, pack_alignment_, &pixels_size)) {
4182 return error::kOutOfBounds;
4183 }
[email protected]612d2f82009-12-08 20:49:314184 void* pixels = GetSharedMemoryAs<void*>(
4185 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
[email protected]a51788e2010-02-24 21:54:254186 Result* result = GetSharedMemoryAs<Result*>(
4187 c.result_shm_id, c.result_shm_offset, sizeof(*result));
4188 if (!pixels || !result) {
[email protected]f7a64ee2010-02-01 22:24:144189 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:464190 }
[email protected]a51788e2010-02-24 21:54:254191
[email protected]9438b012010-06-15 22:55:054192 if (!validators_->read_pixel_format.IsValid(format)) {
[email protected]8eee29c2010-04-29 03:38:294193 SetGLError(GL_INVALID_ENUM, "glReadPixels: format GL_INVALID_ENUM");
4194 return error::kNoError;
4195 }
[email protected]9438b012010-06-15 22:55:054196 if (!validators_->pixel_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:294197 SetGLError(GL_INVALID_ENUM, "glReadPixels: type GL_INVALID_ENUM");
[email protected]d2cf0a2d2010-02-25 21:36:124198 return error::kNoError;
4199 }
[email protected]57f223832010-03-19 01:57:564200 if (width == 0 || height == 0) {
4201 return error::kNoError;
4202 }
4203
4204 CopyRealGLErrorsToWrapper();
4205
4206 // Get the size of the current fbo or backbuffer.
[email protected]8e3e0662010-08-23 18:46:304207 gfx::Size max_size = GetBoundReadFrameBufferSize();
[email protected]57f223832010-03-19 01:57:564208
4209 GLint max_x;
4210 GLint max_y;
4211 if (!SafeAdd(x, width, &max_x) || !SafeAdd(y, height, &max_y)) {
[email protected]8eee29c2010-04-29 03:38:294212 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]f7a64ee2010-02-01 22:24:144213 return error::kNoError;
[email protected]612d2f82009-12-08 20:49:314214 }
[email protected]57f223832010-03-19 01:57:564215
[email protected]d37231fa2010-04-09 21:16:024216 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
[email protected]57f223832010-03-19 01:57:564217 // The user requested an out of range area. Get the results 1 line
4218 // at a time.
4219 uint32 temp_size;
4220 if (!GLES2Util::ComputeImageDataSize(
4221 width, 1, format, type, pack_alignment_, &temp_size)) {
[email protected]8eee29c2010-04-29 03:38:294222 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:564223 return error::kNoError;
4224 }
4225 GLsizei unpadded_row_size = temp_size;
4226 if (!GLES2Util::ComputeImageDataSize(
4227 width, 2, format, type, pack_alignment_, &temp_size)) {
[email protected]8eee29c2010-04-29 03:38:294228 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:564229 return error::kNoError;
4230 }
4231 GLsizei padded_row_size = temp_size - unpadded_row_size;
4232 if (padded_row_size < 0 || unpadded_row_size < 0) {
[email protected]8eee29c2010-04-29 03:38:294233 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:564234 return error::kNoError;
4235 }
4236
4237 GLint dest_x_offset = std::max(-x, 0);
4238 uint32 dest_row_offset;
4239 if (!GLES2Util::ComputeImageDataSize(
4240 dest_x_offset, 1, format, type, pack_alignment_, &dest_row_offset)) {
[email protected]8eee29c2010-04-29 03:38:294241 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:564242 return error::kNoError;
4243 }
4244
4245 // Copy each row into the larger dest rect.
4246 int8* dst = static_cast<int8*>(pixels);
4247 GLint read_x = std::max(0, x);
[email protected]d37231fa2010-04-09 21:16:024248 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
[email protected]57f223832010-03-19 01:57:564249 GLint read_width = read_end_x - read_x;
4250 for (GLint yy = 0; yy < height; ++yy) {
4251 GLint ry = y + yy;
4252
4253 // Clear the row.
4254 memset(dst, 0, unpadded_row_size);
4255
4256 // If the row is in range, copy it.
[email protected]d37231fa2010-04-09 21:16:024257 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
[email protected]57f223832010-03-19 01:57:564258 glReadPixels(
4259 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
4260 }
4261 dst += padded_row_size;
4262 }
4263 } else {
4264 glReadPixels(x, y, width, height, format, type, pixels);
4265 }
[email protected]a51788e2010-02-24 21:54:254266 GLenum error = glGetError();
4267 if (error == GL_NO_ERROR) {
4268 *result = true;
4269 } else {
[email protected]8eee29c2010-04-29 03:38:294270 SetGLError(error, NULL);
[email protected]a51788e2010-02-24 21:54:254271 }
[email protected]f7a64ee2010-02-01 22:24:144272 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324273}
4274
[email protected]f7a64ee2010-02-01 22:24:144275error::Error GLES2DecoderImpl::HandlePixelStorei(
[email protected]b9849abf2009-11-25 19:13:194276 uint32 immediate_data_size, const gles2::PixelStorei& c) {
4277 GLenum pname = c.pname;
4278 GLenum param = c.param;
[email protected]9438b012010-06-15 22:55:054279 if (!validators_->pixel_store.IsValid(pname)) {
[email protected]8eee29c2010-04-29 03:38:294280 SetGLError(GL_INVALID_ENUM, "glPixelStorei: pname GL_INVALID_ENUM");
[email protected]d2cf0a2d2010-02-25 21:36:124281 return error::kNoError;
4282 }
[email protected]9438b012010-06-15 22:55:054283 if (!validators_->pixel_store_alignment.IsValid(param)) {
[email protected]8eee29c2010-04-29 03:38:294284 SetGLError(GL_INVALID_VALUE, "glPixelSTore: param GL_INVALID_VALUE");
[email protected]f7a64ee2010-02-01 22:24:144285 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:194286 }
4287 glPixelStorei(pname, param);
4288 switch (pname) {
4289 case GL_PACK_ALIGNMENT:
4290 pack_alignment_ = param;
4291 break;
4292 case GL_UNPACK_ALIGNMENT:
4293 unpack_alignment_ = param;
4294 break;
4295 default:
4296 // Validation should have prevented us from getting here.
[email protected]656dcaad2010-05-07 17:18:374297 NOTREACHED();
[email protected]b9849abf2009-11-25 19:13:194298 break;
4299 }
[email protected]f7a64ee2010-02-01 22:24:144300 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:194301}
4302
[email protected]558847a2010-03-24 07:02:544303error::Error GLES2DecoderImpl::GetAttribLocationHelper(
4304 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
4305 const std::string& name_str) {
[email protected]6b8cf1a2010-05-06 16:13:584306 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
4307 client_id, "glGetAttribLocation");
[email protected]ae51d192010-04-27 00:48:034308 if (!info) {
[email protected]f7a64ee2010-02-01 22:24:144309 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:194310 }
[email protected]ae51d192010-04-27 00:48:034311 if (!info->IsValid()) {
[email protected]8eee29c2010-04-29 03:38:294312 SetGLError(GL_INVALID_OPERATION, "glGetAttribLocation: program not linked");
[email protected]0bfd9882010-02-05 23:02:254313 return error::kNoError;
4314 }
[email protected]b9849abf2009-11-25 19:13:194315 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:544316 location_shm_id, location_shm_offset, sizeof(GLint));
4317 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:144318 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:194319 }
[email protected]558847a2010-03-24 07:02:544320 // Require the client to init this incase the context is lost and we are no
4321 // longer executing commands.
4322 if (*location != -1) {
4323 return error::kGenericError;
4324 }
[email protected]0bfd9882010-02-05 23:02:254325 *location = info->GetAttribLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:144326 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:194327}
4328
[email protected]558847a2010-03-24 07:02:544329error::Error GLES2DecoderImpl::HandleGetAttribLocation(
4330 uint32 immediate_data_size, const gles2::GetAttribLocation& c) {
4331 uint32 name_size = c.data_size;
4332 const char* name = GetSharedMemoryAs<const char*>(
4333 c.name_shm_id, c.name_shm_offset, name_size);
4334 if (!name) {
4335 return error::kOutOfBounds;
4336 }
4337 String name_str(name, name_size);
4338 return GetAttribLocationHelper(
4339 c.program, c.location_shm_id, c.location_shm_offset, name_str);
4340}
4341
[email protected]f7a64ee2010-02-01 22:24:144342error::Error GLES2DecoderImpl::HandleGetAttribLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:194343 uint32 immediate_data_size, const gles2::GetAttribLocationImmediate& c) {
[email protected]558847a2010-03-24 07:02:544344 uint32 name_size = c.data_size;
4345 const char* name = GetImmediateDataAs<const char*>(
4346 c, name_size, immediate_data_size);
4347 if (!name) {
4348 return error::kOutOfBounds;
4349 }
4350 String name_str(name, name_size);
4351 return GetAttribLocationHelper(
4352 c.program, c.location_shm_id, c.location_shm_offset, name_str);
4353}
4354
4355error::Error GLES2DecoderImpl::HandleGetAttribLocationBucket(
4356 uint32 immediate_data_size, const gles2::GetAttribLocationBucket& c) {
4357 Bucket* bucket = GetBucket(c.name_bucket_id);
4358 if (!bucket) {
4359 return error::kInvalidArguments;
4360 }
4361 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:184362 if (!bucket->GetAsString(&name_str)) {
4363 return error::kInvalidArguments;
4364 }
[email protected]558847a2010-03-24 07:02:544365 return GetAttribLocationHelper(
4366 c.program, c.location_shm_id, c.location_shm_offset, name_str);
4367}
4368
4369error::Error GLES2DecoderImpl::GetUniformLocationHelper(
4370 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
4371 const std::string& name_str) {
[email protected]6b8cf1a2010-05-06 16:13:584372 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
4373 client_id, "glUniformLocation");
[email protected]ae51d192010-04-27 00:48:034374 if (!info) {
[email protected]f7a64ee2010-02-01 22:24:144375 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:194376 }
[email protected]ae51d192010-04-27 00:48:034377 if (!info->IsValid()) {
[email protected]8eee29c2010-04-29 03:38:294378 SetGLError(GL_INVALID_OPERATION,
4379 "glGetUniformLocation: program not linked");
[email protected]0bfd9882010-02-05 23:02:254380 return error::kNoError;
4381 }
[email protected]b9849abf2009-11-25 19:13:194382 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:544383 location_shm_id, location_shm_offset, sizeof(GLint));
4384 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:144385 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:194386 }
[email protected]558847a2010-03-24 07:02:544387 // Require the client to init this incase the context is lost an we are no
4388 // longer executing commands.
4389 if (*location != -1) {
4390 return error::kGenericError;
4391 }
4392 *location = info->GetUniformLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:144393 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:194394}
4395
[email protected]f7a64ee2010-02-01 22:24:144396error::Error GLES2DecoderImpl::HandleGetUniformLocation(
[email protected]b9849abf2009-11-25 19:13:194397 uint32 immediate_data_size, const gles2::GetUniformLocation& c) {
[email protected]b9849abf2009-11-25 19:13:194398 uint32 name_size = c.data_size;
4399 const char* name = GetSharedMemoryAs<const char*>(
4400 c.name_shm_id, c.name_shm_offset, name_size);
[email protected]558847a2010-03-24 07:02:544401 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:144402 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:194403 }
4404 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:544405 return GetUniformLocationHelper(
4406 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:194407}
4408
[email protected]f7a64ee2010-02-01 22:24:144409error::Error GLES2DecoderImpl::HandleGetUniformLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:194410 uint32 immediate_data_size, const gles2::GetUniformLocationImmediate& c) {
[email protected]b9849abf2009-11-25 19:13:194411 uint32 name_size = c.data_size;
[email protected]07f54fcc2009-12-22 02:46:304412 const char* name = GetImmediateDataAs<const char*>(
4413 c, name_size, immediate_data_size);
[email protected]558847a2010-03-24 07:02:544414 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:144415 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:194416 }
4417 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:544418 return GetUniformLocationHelper(
4419 c.program, c.location_shm_id, c.location_shm_offset, name_str);
4420}
4421
4422error::Error GLES2DecoderImpl::HandleGetUniformLocationBucket(
4423 uint32 immediate_data_size, const gles2::GetUniformLocationBucket& c) {
4424 Bucket* bucket = GetBucket(c.name_bucket_id);
4425 if (!bucket) {
4426 return error::kInvalidArguments;
4427 }
4428 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:184429 if (!bucket->GetAsString(&name_str)) {
4430 return error::kInvalidArguments;
4431 }
[email protected]558847a2010-03-24 07:02:544432 return GetUniformLocationHelper(
4433 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:194434}
4435
[email protected]ddd968b82010-03-02 00:44:294436error::Error GLES2DecoderImpl::HandleGetString(
4437 uint32 immediate_data_size, const gles2::GetString& c) {
4438 GLenum name = static_cast<GLenum>(c.name);
[email protected]9438b012010-06-15 22:55:054439 if (!validators_->string_type.IsValid(name)) {
[email protected]8eee29c2010-04-29 03:38:294440 SetGLError(GL_INVALID_ENUM, "glGetString: name GL_INVALID_ENUM");
[email protected]ddd968b82010-03-02 00:44:294441 return error::kNoError;
4442 }
[email protected]1958e0e2010-04-22 05:17:154443 const char* gl_str = reinterpret_cast<const char*>(glGetString(name));
4444 const char* str = NULL;
4445 switch (name) {
4446 case GL_VERSION:
4447 str = "OpenGL ES 2.0 Chromium";
4448 break;
4449 case GL_SHADING_LANGUAGE_VERSION:
4450 str = "OpenGL ES GLSL ES 1.0 Chromium";
4451 break;
4452 case GL_EXTENSIONS:
[email protected]7488d962010-07-16 02:41:584453 str = group_->extensions().c_str();
[email protected]1958e0e2010-04-22 05:17:154454 break;
4455 default:
4456 str = gl_str;
4457 break;
4458 }
[email protected]ddd968b82010-03-02 00:44:294459 Bucket* bucket = CreateBucket(c.bucket_id);
[email protected]1958e0e2010-04-22 05:17:154460 bucket->SetFromString(str);
[email protected]ddd968b82010-03-02 00:44:294461 return error::kNoError;
4462}
4463
[email protected]0c86dbf2010-03-05 08:14:114464void GLES2DecoderImpl::DoBufferData(
[email protected]b9363b22010-06-09 22:06:154465 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage) {
[email protected]9438b012010-06-15 22:55:054466 if (!validators_->buffer_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:294467 SetGLError(GL_INVALID_ENUM, "glBufferData: target GL_INVALID_ENUM");
4468 return;
4469 }
[email protected]9438b012010-06-15 22:55:054470 if (!validators_->buffer_usage.IsValid(usage)) {
[email protected]8eee29c2010-04-29 03:38:294471 SetGLError(GL_INVALID_ENUM, "glBufferData: usage GL_INVALID_ENUM");
[email protected]0c86dbf2010-03-05 08:14:114472 return;
[email protected]3b6ec202010-03-05 05:16:234473 }
4474 if (size < 0) {
[email protected]8eee29c2010-04-29 03:38:294475 SetGLError(GL_INVALID_VALUE, "glBufferData: size < 0");
[email protected]037896bd2010-04-21 19:07:284476 return;
[email protected]3b6ec202010-03-05 05:16:234477 }
4478 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
4479 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294480 SetGLError(GL_INVALID_VALUE, "glBufferData: unknown buffer");
[email protected]037896bd2010-04-21 19:07:284481 return;
[email protected]3b6ec202010-03-05 05:16:234482 }
4483 // Clear the buffer to 0 if no initial data was passed in.
4484 scoped_array<int8> zero;
4485 if (!data) {
4486 zero.reset(new int8[size]);
4487 memset(zero.get(), 0, size);
4488 data = zero.get();
4489 }
4490 CopyRealGLErrorsToWrapper();
4491 glBufferData(target, size, data, usage);
4492 GLenum error = glGetError();
4493 if (error != GL_NO_ERROR) {
[email protected]8eee29c2010-04-29 03:38:294494 SetGLError(error, NULL);
[email protected]3b6ec202010-03-05 05:16:234495 } else {
[email protected]4e8a5b122010-05-08 22:00:104496 buffer_manager()->SetSize(info, size);
[email protected]0c86dbf2010-03-05 08:14:114497 info->SetRange(0, size, data);
[email protected]3b6ec202010-03-05 05:16:234498 }
[email protected]0c86dbf2010-03-05 08:14:114499}
4500
4501error::Error GLES2DecoderImpl::HandleBufferData(
4502 uint32 immediate_data_size, const gles2::BufferData& c) {
4503 GLenum target = static_cast<GLenum>(c.target);
4504 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
4505 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
4506 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
4507 GLenum usage = static_cast<GLenum>(c.usage);
4508 const void* data = NULL;
4509 if (data_shm_id != 0 || data_shm_offset != 0) {
4510 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
4511 if (!data) {
4512 return error::kOutOfBounds;
4513 }
4514 }
4515 DoBufferData(target, size, data, usage);
[email protected]f7a64ee2010-02-01 22:24:144516 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:194517}
4518
[email protected]f7a64ee2010-02-01 22:24:144519error::Error GLES2DecoderImpl::HandleBufferDataImmediate(
[email protected]b9849abf2009-11-25 19:13:194520 uint32 immediate_data_size, const gles2::BufferDataImmediate& c) {
4521 GLenum target = static_cast<GLenum>(c.target);
4522 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
[email protected]07f54fcc2009-12-22 02:46:304523 const void* data = GetImmediateDataAs<const void*>(
4524 c, size, immediate_data_size);
4525 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:144526 return error::kOutOfBounds;
[email protected]07f54fcc2009-12-22 02:46:304527 }
[email protected]b9849abf2009-11-25 19:13:194528 GLenum usage = static_cast<GLenum>(c.usage);
[email protected]0c86dbf2010-03-05 08:14:114529 DoBufferData(target, size, data, usage);
4530 return error::kNoError;
4531}
4532
4533void GLES2DecoderImpl::DoBufferSubData(
4534 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
[email protected]3916c97e2010-02-25 03:20:504535 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:474536 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294537 SetGLError(GL_INVALID_VALUE, "glBufferSubData: unknown buffer");
[email protected]037896bd2010-04-21 19:07:284538 return;
[email protected]a93bb842010-02-16 23:03:474539 }
[email protected]0c86dbf2010-03-05 08:14:114540 if (!info->SetRange(offset, size, data)) {
[email protected]8eee29c2010-04-29 03:38:294541 SetGLError(GL_INVALID_VALUE, "glBufferSubData: out of range");
[email protected]07f54fcc2009-12-22 02:46:304542 } else {
[email protected]0c86dbf2010-03-05 08:14:114543 glBufferSubData(target, offset, size, data);
[email protected]07f54fcc2009-12-22 02:46:304544 }
[email protected]b9849abf2009-11-25 19:13:194545}
4546
[email protected]a93bb842010-02-16 23:03:474547error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
4548 GLenum target,
4549 GLint level,
4550 GLenum internal_format,
4551 GLsizei width,
4552 GLsizei height,
4553 GLint border,
4554 GLsizei image_size,
4555 const void* data) {
[email protected]a93bb842010-02-16 23:03:474556 // TODO(gman): Validate image_size is correct for width, height and format.
[email protected]9438b012010-06-15 22:55:054557 if (!validators_->texture_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:294558 SetGLError(GL_INVALID_ENUM,
4559 "glCompressedTexImage2D: target GL_INVALID_ENUM");
4560 return error::kNoError;
4561 }
[email protected]9438b012010-06-15 22:55:054562 if (!validators_->compressed_texture_format.IsValid(
4563 internal_format)) {
[email protected]8eee29c2010-04-29 03:38:294564 SetGLError(GL_INVALID_ENUM,
4565 "glCompressedTexImage2D: internal_format GL_INVALID_ENUM");
[email protected]a93bb842010-02-16 23:03:474566 return error::kNoError;
4567 }
[email protected]3916c97e2010-02-25 03:20:504568 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:474569 border != 0) {
[email protected]8eee29c2010-04-29 03:38:294570 SetGLError(GL_INVALID_VALUE,
4571 "glCompressedTexImage2D: dimensions out of range");
[email protected]a93bb842010-02-16 23:03:474572 return error::kNoError;
4573 }
[email protected]3916c97e2010-02-25 03:20:504574 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:474575 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294576 SetGLError(GL_INVALID_VALUE,
4577 "glCompressedTexImage2D: unknown texture target");
[email protected]a93bb842010-02-16 23:03:474578 return error::kNoError;
4579 }
4580 scoped_array<int8> zero;
4581 if (!data) {
4582 zero.reset(new int8[image_size]);
4583 memset(zero.get(), 0, image_size);
4584 data = zero.get();
4585 }
[email protected]cadde4a2010-07-31 17:10:434586 CopyRealGLErrorsToWrapper();
[email protected]a93bb842010-02-16 23:03:474587 glCompressedTexImage2D(
4588 target, level, internal_format, width, height, border, image_size, data);
[email protected]cadde4a2010-07-31 17:10:434589 GLenum error = glGetError();
4590 if (error == GL_NO_ERROR) {
4591 texture_manager()->SetLevelInfo(
4592 info, target, level, internal_format, width, height, 1, border, 0, 0);
4593 }
[email protected]a93bb842010-02-16 23:03:474594 return error::kNoError;
4595}
4596
[email protected]f7a64ee2010-02-01 22:24:144597error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:194598 uint32 immediate_data_size, const gles2::CompressedTexImage2D& c) {
4599 GLenum target = static_cast<GLenum>(c.target);
4600 GLint level = static_cast<GLint>(c.level);
4601 GLenum internal_format = static_cast<GLenum>(c.internalformat);
4602 GLsizei width = static_cast<GLsizei>(c.width);
4603 GLsizei height = static_cast<GLsizei>(c.height);
4604 GLint border = static_cast<GLint>(c.border);
4605 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
4606 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
4607 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
4608 const void* data = NULL;
4609 if (data_shm_id != 0 || data_shm_offset != 0) {
4610 data = GetSharedMemoryAs<const void*>(
4611 data_shm_id, data_shm_offset, image_size);
[email protected]ba3176a2009-12-16 18:19:464612 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:144613 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:194614 }
4615 }
[email protected]a93bb842010-02-16 23:03:474616 return DoCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:194617 target, level, internal_format, width, height, border, image_size, data);
[email protected]b9849abf2009-11-25 19:13:194618}
4619
[email protected]f7a64ee2010-02-01 22:24:144620error::Error GLES2DecoderImpl::HandleCompressedTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:194621 uint32 immediate_data_size, const gles2::CompressedTexImage2DImmediate& c) {
4622 GLenum target = static_cast<GLenum>(c.target);
4623 GLint level = static_cast<GLint>(c.level);
4624 GLenum internal_format = static_cast<GLenum>(c.internalformat);
4625 GLsizei width = static_cast<GLsizei>(c.width);
4626 GLsizei height = static_cast<GLsizei>(c.height);
4627 GLint border = static_cast<GLint>(c.border);
4628 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
[email protected]07f54fcc2009-12-22 02:46:304629 const void* data = GetImmediateDataAs<const void*>(
4630 c, image_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:464631 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:144632 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:464633 }
[email protected]a93bb842010-02-16 23:03:474634 return DoCompressedTexImage2D(
4635 target, level, internal_format, width, height, border, image_size, data);
4636}
4637
[email protected]b6140d02010-05-17 14:47:164638error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
4639 uint32 immediate_data_size, const gles2::CompressedTexImage2DBucket& c) {
4640 GLenum target = static_cast<GLenum>(c.target);
4641 GLint level = static_cast<GLint>(c.level);
4642 GLenum internal_format = static_cast<GLenum>(c.internalformat);
4643 GLsizei width = static_cast<GLsizei>(c.width);
4644 GLsizei height = static_cast<GLsizei>(c.height);
4645 GLint border = static_cast<GLint>(c.border);
4646 Bucket* bucket = GetBucket(c.bucket_id);
4647 return DoCompressedTexImage2D(
4648 target, level, internal_format, width, height, border,
4649 bucket->size(), bucket->GetData(0, bucket->size()));
4650}
4651
4652error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
4653 uint32 immediate_data_size,
4654 const gles2::CompressedTexSubImage2DBucket& c) {
4655 GLenum target = static_cast<GLenum>(c.target);
4656 GLint level = static_cast<GLint>(c.level);
4657 GLint xoffset = static_cast<GLint>(c.xoffset);
4658 GLint yoffset = static_cast<GLint>(c.yoffset);
4659 GLsizei width = static_cast<GLsizei>(c.width);
4660 GLsizei height = static_cast<GLsizei>(c.height);
4661 GLenum format = static_cast<GLenum>(c.format);
4662 Bucket* bucket = GetBucket(c.bucket_id);
4663 uint32 data_size = bucket->size();
4664 GLsizei imageSize = data_size;
4665 const void* data = bucket->GetData(0, data_size);
[email protected]9438b012010-06-15 22:55:054666 if (!validators_->texture_target.IsValid(target)) {
[email protected]b6140d02010-05-17 14:47:164667 SetGLError(
4668 GL_INVALID_ENUM, "glCompressedTexSubImage2D: target GL_INVALID_ENUM");
4669 return error::kNoError;
4670 }
[email protected]9438b012010-06-15 22:55:054671 if (!validators_->compressed_texture_format.IsValid(format)) {
4672 SetGLError(GL_INVALID_ENUM,
4673 "glCompressedTexSubImage2D: format GL_INVALID_ENUM");
4674 return error::kNoError;
4675 }
[email protected]b6140d02010-05-17 14:47:164676 if (width < 0) {
4677 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: width < 0");
4678 return error::kNoError;
4679 }
4680 if (height < 0) {
4681 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: height < 0");
4682 return error::kNoError;
4683 }
4684 if (imageSize < 0) {
4685 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: imageSize < 0");
4686 return error::kNoError;
4687 }
[email protected]cadde4a2010-07-31 17:10:434688 DoCompressedTexSubImage2D(
[email protected]b6140d02010-05-17 14:47:164689 target, level, xoffset, yoffset, width, height, format, imageSize, data);
4690 return error::kNoError;
4691}
4692
[email protected]a93bb842010-02-16 23:03:474693error::Error GLES2DecoderImpl::DoTexImage2D(
4694 GLenum target,
4695 GLint level,
4696 GLenum internal_format,
4697 GLsizei width,
4698 GLsizei height,
4699 GLint border,
4700 GLenum format,
4701 GLenum type,
4702 const void* pixels,
4703 uint32 pixels_size) {
[email protected]9438b012010-06-15 22:55:054704 if (!validators_->texture_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:294705 SetGLError(GL_INVALID_ENUM, "glTexImage2D: target GL_INVALID_ENUM");
4706 return error::kNoError;
4707 }
[email protected]9438b012010-06-15 22:55:054708 if (!validators_->texture_format.IsValid(internal_format)) {
[email protected]8eee29c2010-04-29 03:38:294709 SetGLError(GL_INVALID_ENUM,
4710 "glTexImage2D: internal_format GL_INVALID_ENUM");
4711 return error::kNoError;
4712 }
[email protected]9438b012010-06-15 22:55:054713 if (!validators_->texture_format.IsValid(format)) {
[email protected]8eee29c2010-04-29 03:38:294714 SetGLError(GL_INVALID_ENUM, "glTexImage2D: format GL_INVALID_ENUM");
4715 return error::kNoError;
4716 }
[email protected]9438b012010-06-15 22:55:054717 if (!validators_->pixel_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:294718 SetGLError(GL_INVALID_ENUM, "glTexImage2D: type GL_INVALID_ENUM");
[email protected]f7a64ee2010-02-01 22:24:144719 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:194720 }
[email protected]7b92c412010-07-20 17:48:254721 if (format != internal_format) {
4722 SetGLError(GL_INVALID_OPERATION, "glTexImage2D: format != internalFormat");
4723 return error::kNoError;
4724 }
[email protected]3916c97e2010-02-25 03:20:504725 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:474726 border != 0) {
[email protected]8eee29c2010-04-29 03:38:294727 SetGLError(GL_INVALID_VALUE, "glTexImage2D: dimensions out of range");
[email protected]a93bb842010-02-16 23:03:474728 return error::kNoError;
4729 }
[email protected]3916c97e2010-02-25 03:20:504730 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:474731 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294732 SetGLError(GL_INVALID_OPERATION,
4733 "glTexImage2D: unknown texture for target");
[email protected]a93bb842010-02-16 23:03:474734 return error::kNoError;
4735 }
4736 scoped_array<int8> zero;
4737 if (!pixels) {
4738 zero.reset(new int8[pixels_size]);
4739 memset(zero.get(), 0, pixels_size);
4740 pixels = zero.get();
4741 }
[email protected]876f6fee2010-08-02 23:10:324742
[email protected]f5719fb2010-08-04 18:27:184743 GLenum gl_internal_format = internal_format;
[email protected]876f6fee2010-08-02 23:10:324744 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
4745 if (format == GL_BGRA_EXT && internal_format == GL_BGRA_EXT) {
[email protected]f5719fb2010-08-04 18:27:184746 gl_internal_format = GL_RGBA;
[email protected]876f6fee2010-08-02 23:10:324747 } else if (type == GL_FLOAT) {
4748 if (format == GL_RGBA) {
[email protected]f5719fb2010-08-04 18:27:184749 gl_internal_format = GL_RGBA32F_ARB;
[email protected]876f6fee2010-08-02 23:10:324750 } else if (format == GL_RGB) {
[email protected]f5719fb2010-08-04 18:27:184751 gl_internal_format = GL_RGB32F_ARB;
[email protected]876f6fee2010-08-02 23:10:324752 }
4753 } else if (type == GL_HALF_FLOAT_OES) {
4754 if (format == GL_RGBA) {
[email protected]f5719fb2010-08-04 18:27:184755 gl_internal_format = GL_RGBA16F_ARB;
[email protected]876f6fee2010-08-02 23:10:324756 } else if (format == GL_RGB) {
[email protected]f5719fb2010-08-04 18:27:184757 gl_internal_format = GL_RGB16F_ARB;
[email protected]876f6fee2010-08-02 23:10:324758 }
[email protected]7b92c412010-07-20 17:48:254759 }
[email protected]7488d962010-07-16 02:41:584760 }
[email protected]876f6fee2010-08-02 23:10:324761
[email protected]cadde4a2010-07-31 17:10:434762 CopyRealGLErrorsToWrapper();
[email protected]a93bb842010-02-16 23:03:474763 glTexImage2D(
[email protected]f5719fb2010-08-04 18:27:184764 target, level, gl_internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:474765 pixels);
[email protected]cadde4a2010-07-31 17:10:434766 GLenum error = glGetError();
4767 if (error == GL_NO_ERROR) {
4768 texture_manager()->SetLevelInfo(info,
4769 target, level, internal_format, width, height, 1, border, format, type);
4770 }
[email protected]f7a64ee2010-02-01 22:24:144771 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:194772}
4773
[email protected]f7a64ee2010-02-01 22:24:144774error::Error GLES2DecoderImpl::HandleTexImage2D(
[email protected]b9849abf2009-11-25 19:13:194775 uint32 immediate_data_size, const gles2::TexImage2D& c) {
4776 GLenum target = static_cast<GLenum>(c.target);
4777 GLint level = static_cast<GLint>(c.level);
4778 GLint internal_format = static_cast<GLint>(c.internalformat);
4779 GLsizei width = static_cast<GLsizei>(c.width);
4780 GLsizei height = static_cast<GLsizei>(c.height);
4781 GLint border = static_cast<GLint>(c.border);
4782 GLenum format = static_cast<GLenum>(c.format);
4783 GLenum type = static_cast<GLenum>(c.type);
4784 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
4785 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
[email protected]a76b0052010-03-05 00:33:184786 uint32 pixels_size;
4787 if (!GLES2Util::ComputeImageDataSize(
4788 width, height, format, type, unpack_alignment_, &pixels_size)) {
4789 return error::kOutOfBounds;
4790 }
[email protected]b9849abf2009-11-25 19:13:194791 const void* pixels = NULL;
4792 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
4793 pixels = GetSharedMemoryAs<const void*>(
4794 pixels_shm_id, pixels_shm_offset, pixels_size);
[email protected]ba3176a2009-12-16 18:19:464795 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:144796 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:194797 }
4798 }
[email protected]a93bb842010-02-16 23:03:474799 return DoTexImage2D(
[email protected]b9849abf2009-11-25 19:13:194800 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:474801 pixels, pixels_size);
[email protected]b9849abf2009-11-25 19:13:194802}
4803
[email protected]f7a64ee2010-02-01 22:24:144804error::Error GLES2DecoderImpl::HandleTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:194805 uint32 immediate_data_size, const gles2::TexImage2DImmediate& c) {
4806 GLenum target = static_cast<GLenum>(c.target);
4807 GLint level = static_cast<GLint>(c.level);
[email protected]ba3176a2009-12-16 18:19:464808 GLint internal_format = static_cast<GLint>(c.internalformat);
[email protected]b9849abf2009-11-25 19:13:194809 GLsizei width = static_cast<GLsizei>(c.width);
4810 GLsizei height = static_cast<GLsizei>(c.height);
4811 GLint border = static_cast<GLint>(c.border);
4812 GLenum format = static_cast<GLenum>(c.format);
4813 GLenum type = static_cast<GLenum>(c.type);
[email protected]a76b0052010-03-05 00:33:184814 uint32 size;
4815 if (!GLES2Util::ComputeImageDataSize(
4816 width, height, format, type, unpack_alignment_, &size)) {
4817 return error::kOutOfBounds;
4818 }
[email protected]07f54fcc2009-12-22 02:46:304819 const void* pixels = GetImmediateDataAs<const void*>(
4820 c, size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:464821 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:144822 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:464823 }
[email protected]a93bb842010-02-16 23:03:474824 DoTexImage2D(
[email protected]ba3176a2009-12-16 18:19:464825 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:474826 pixels, size);
[email protected]f7a64ee2010-02-01 22:24:144827 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324828}
4829
[email protected]cadde4a2010-07-31 17:10:434830void GLES2DecoderImpl::DoCompressedTexSubImage2D(
4831 GLenum target,
4832 GLint level,
4833 GLint xoffset,
4834 GLint yoffset,
4835 GLsizei width,
4836 GLsizei height,
4837 GLenum format,
4838 GLsizei image_size,
4839 const void * data) {
4840 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
4841 if (!info) {
4842 SetGLError(GL_INVALID_OPERATION,
4843 "glCompressedTexSubImage2D: unknown texture for target");
4844 return;
4845 }
4846 GLenum type = 0;
4847 GLenum dummy = 0;
4848 if (!info->GetLevelType(target, level, &type, &dummy) ||
4849 !info->ValidForTexture(
4850 target, level, xoffset, yoffset, width, height, format, type)) {
4851 SetGLError(GL_INVALID_VALUE,
4852 "glCompressdTexSubImage2D: bad dimensions.");
4853 return;
4854 }
4855 glCompressedTexSubImage2D(
4856 target, level, xoffset, yoffset, width, height, format, image_size, data);
4857}
4858
4859void GLES2DecoderImpl::DoCopyTexImage2D(
4860 GLenum target,
4861 GLint level,
4862 GLenum internal_format,
4863 GLint x,
4864 GLint y,
4865 GLsizei width,
4866 GLsizei height,
4867 GLint border) {
4868 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
4869 if (!info) {
4870 SetGLError(GL_INVALID_OPERATION,
4871 "glCopyTexImage2D: unknown texture for target");
4872 return;
4873 }
[email protected]f5719fb2010-08-04 18:27:184874 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
4875 border != 0) {
4876 SetGLError(GL_INVALID_VALUE, "glCopyTexImage2D: dimensions out of range");
4877 return;
4878 }
4879
[email protected]cadde4a2010-07-31 17:10:434880 // TODO(gman): Need to check that current FBO is compatible with
4881 // internal_format.
4882 // TODO(gman): Type needs to match format for FBO.
4883 CopyRealGLErrorsToWrapper();
4884 glCopyTexImage2D(target, level, internal_format, x, y, width, height, border);
4885 GLenum error = glGetError();
4886 if (error == GL_NO_ERROR) {
4887 texture_manager()->SetLevelInfo(
4888 info, target, level, internal_format, width, height, 1, border,
4889 internal_format, GL_UNSIGNED_BYTE);
4890 }
4891}
4892
4893void GLES2DecoderImpl::DoCopyTexSubImage2D(
4894 GLenum target,
4895 GLint level,
4896 GLint xoffset,
4897 GLint yoffset,
4898 GLint x,
4899 GLint y,
4900 GLsizei width,
4901 GLsizei height) {
4902 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
4903 if (!info) {
4904 SetGLError(GL_INVALID_OPERATION,
4905 "glCopyTexSubImage2D: unknown texture for target");
4906 return;
4907 }
4908 GLenum type = 0;
4909 GLenum format = 0;
4910 if (!info->GetLevelType(target, level, &type, &format) ||
4911 !info->ValidForTexture(
4912 target, level, xoffset, yoffset, width, height, format, type)) {
4913 SetGLError(GL_INVALID_VALUE,
4914 "glCopyTexSubImage2D: bad dimensions.");
4915 return;
4916 }
4917 // TODO(gman): Should we check that x, y, width, and height are in range
4918 // for current FBO?
4919 glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
4920}
4921
4922void GLES2DecoderImpl::DoTexSubImage2D(
4923 GLenum target,
4924 GLint level,
4925 GLint xoffset,
4926 GLint yoffset,
4927 GLsizei width,
4928 GLsizei height,
4929 GLenum format,
4930 GLenum type,
4931 const void * data) {
4932 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
4933 if (!info) {
4934 SetGLError(GL_INVALID_OPERATION,
4935 "glTexSubImage2D: unknown texture for target");
4936 return;
4937 }
4938 if (!info->ValidForTexture(
4939 target, level, xoffset, yoffset, width, height, format, type)) {
4940 SetGLError(GL_INVALID_VALUE,
4941 "glTexSubImage2D: bad dimensions.");
4942 return;
4943 }
4944 glTexSubImage2D(
4945 target, level, xoffset, yoffset, width, height, format, type, data);
4946}
4947
[email protected]f7a64ee2010-02-01 22:24:144948error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
[email protected]b9849abf2009-11-25 19:13:194949 uint32 immediate_data_size, const gles2::GetVertexAttribPointerv& c) {
[email protected]8bf5a3e2010-01-29 04:21:364950 GLuint index = static_cast<GLuint>(c.index);
4951 GLenum pname = static_cast<GLenum>(c.pname);
[email protected]0bfd9882010-02-05 23:02:254952 typedef gles2::GetVertexAttribPointerv::Result Result;
4953 Result* result = GetSharedMemoryAs<Result*>(
4954 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
[email protected]8bf5a3e2010-01-29 04:21:364955 if (!result) {
[email protected]f7a64ee2010-02-01 22:24:144956 return error::kOutOfBounds;
[email protected]8bf5a3e2010-01-29 04:21:364957 }
[email protected]07d0cc82010-02-17 04:51:404958 // Check that the client initialized the result.
4959 if (result->size != 0) {
4960 return error::kInvalidArguments;
4961 }
[email protected]9438b012010-06-15 22:55:054962 if (!validators_->vertex_pointer.IsValid(pname)) {
[email protected]8eee29c2010-04-29 03:38:294963 SetGLError(GL_INVALID_ENUM,
4964 "glGetVertexAttribPointerv: pname GL_INVALID_ENUM");
[email protected]f7a64ee2010-02-01 22:24:144965 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:364966 }
[email protected]3916c97e2010-02-25 03:20:504967 if (index >= group_->max_vertex_attribs()) {
[email protected]8eee29c2010-04-29 03:38:294968 SetGLError(GL_INVALID_VALUE,
4969 "glGetVertexAttribPointerv: index out of range.");
[email protected]f7a64ee2010-02-01 22:24:144970 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:364971 }
[email protected]0bfd9882010-02-05 23:02:254972 result->SetNumResults(1);
[email protected]f39f4b3f2010-05-12 17:04:084973 *result->GetData() =
4974 vertex_attrib_manager_.GetVertexAttribInfo(index)->offset();
[email protected]f7a64ee2010-02-01 22:24:144975 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324976}
4977
[email protected]f7b85372010-02-03 01:11:374978bool GLES2DecoderImpl::GetUniformSetup(
4979 GLuint program, GLint location,
4980 uint32 shm_id, uint32 shm_offset,
[email protected]939e7362010-05-13 20:49:104981 error::Error* error, GLuint* service_id, void** result_pointer,
4982 GLenum* result_type) {
4983 DCHECK(error);
4984 DCHECK(service_id);
4985 DCHECK(result_pointer);
4986 DCHECK(result_type);
[email protected]f7b85372010-02-03 01:11:374987 *error = error::kNoError;
4988 // Make sure we have enough room for the result on failure.
[email protected]0bfd9882010-02-05 23:02:254989 SizedResult<GLint>* result;
4990 result = GetSharedMemoryAs<SizedResult<GLint>*>(
4991 shm_id, shm_offset, SizedResult<GLint>::ComputeSize(0));
4992 if (!result) {
[email protected]f7b85372010-02-03 01:11:374993 *error = error::kOutOfBounds;
4994 return false;
4995 }
[email protected]0bfd9882010-02-05 23:02:254996 *result_pointer = result;
[email protected]f7b85372010-02-03 01:11:374997 // Set the result size to 0 so the client does not have to check for success.
[email protected]0bfd9882010-02-05 23:02:254998 result->SetNumResults(0);
[email protected]6b8cf1a2010-05-06 16:13:584999 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
5000 program, "glGetUniform");
[email protected]f7b85372010-02-03 01:11:375001 if (!info) {
[email protected]ae51d192010-04-27 00:48:035002 return false;
5003 }
5004 if (!info->IsValid()) {
[email protected]f7b85372010-02-03 01:11:375005 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]8eee29c2010-04-29 03:38:295006 SetGLError(GL_INVALID_OPERATION, "glGetUniform: program not linked");
[email protected]f7b85372010-02-03 01:11:375007 return false;
5008 }
[email protected]ae51d192010-04-27 00:48:035009 *service_id = info->service_id();
[email protected]0bfd9882010-02-05 23:02:255010 GLenum type;
5011 if (!info->GetUniformTypeByLocation(location, &type)) {
[email protected]f7b85372010-02-03 01:11:375012 // No such location.
[email protected]8eee29c2010-04-29 03:38:295013 SetGLError(GL_INVALID_OPERATION, "glGetUniform: unknown location");
[email protected]f7b85372010-02-03 01:11:375014 return false;
5015 }
[email protected]3916c97e2010-02-25 03:20:505016 GLsizei size = GLES2Util::GetGLDataTypeSizeForUniforms(type);
[email protected]f7b85372010-02-03 01:11:375017 if (size == 0) {
[email protected]8eee29c2010-04-29 03:38:295018 SetGLError(GL_INVALID_OPERATION, "glGetUniform: unknown type");
[email protected]f7b85372010-02-03 01:11:375019 return false;
5020 }
[email protected]0bfd9882010-02-05 23:02:255021 result = GetSharedMemoryAs<SizedResult<GLint>*>(
5022 shm_id, shm_offset, SizedResult<GLint>::ComputeSizeFromBytes(size));
5023 if (!result) {
[email protected]f7b85372010-02-03 01:11:375024 *error = error::kOutOfBounds;
5025 return false;
5026 }
[email protected]0bfd9882010-02-05 23:02:255027 result->size = size;
[email protected]939e7362010-05-13 20:49:105028 *result_type = type;
[email protected]f7b85372010-02-03 01:11:375029 return true;
5030}
5031
[email protected]f7a64ee2010-02-01 22:24:145032error::Error GLES2DecoderImpl::HandleGetUniformiv(
[email protected]b9849abf2009-11-25 19:13:195033 uint32 immediate_data_size, const gles2::GetUniformiv& c) {
[email protected]f7b85372010-02-03 01:11:375034 GLuint program = c.program;
5035 GLint location = c.location;
5036 GLuint service_id;
[email protected]939e7362010-05-13 20:49:105037 GLenum result_type;
[email protected]f7b85372010-02-03 01:11:375038 Error error;
[email protected]0bfd9882010-02-05 23:02:255039 void* result;
[email protected]f7b85372010-02-03 01:11:375040 if (GetUniformSetup(
5041 program, location, c.params_shm_id, c.params_shm_offset,
[email protected]939e7362010-05-13 20:49:105042 &error, &service_id, &result, &result_type)) {
[email protected]0bfd9882010-02-05 23:02:255043 glGetUniformiv(
5044 service_id, location,
5045 static_cast<gles2::GetUniformiv::Result*>(result)->GetData());
[email protected]f7b85372010-02-03 01:11:375046 }
5047 return error;
[email protected]96449d2c2009-11-25 00:01:325048}
5049
[email protected]f7a64ee2010-02-01 22:24:145050error::Error GLES2DecoderImpl::HandleGetUniformfv(
[email protected]b9849abf2009-11-25 19:13:195051 uint32 immediate_data_size, const gles2::GetUniformfv& c) {
[email protected]f7b85372010-02-03 01:11:375052 GLuint program = c.program;
5053 GLint location = c.location;
5054 GLuint service_id;
5055 Error error;
[email protected]0bfd9882010-02-05 23:02:255056 typedef gles2::GetUniformfv::Result Result;
[email protected]939e7362010-05-13 20:49:105057 Result* result;
5058 GLenum result_type;
[email protected]f7b85372010-02-03 01:11:375059 if (GetUniformSetup(
5060 program, location, c.params_shm_id, c.params_shm_offset,
[email protected]939e7362010-05-13 20:49:105061 &error, &service_id, reinterpret_cast<void**>(&result), &result_type)) {
5062 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
5063 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
5064 GLsizei num_values = result->GetNumResults();
5065 scoped_array<GLint> temp(new GLint[num_values]);
5066 glGetUniformiv(service_id, location, temp.get());
5067 GLfloat* dst = result->GetData();
5068 for (GLsizei ii = 0; ii < num_values; ++ii) {
5069 dst[ii] = (temp[ii] != 0);
5070 }
5071 } else {
5072 glGetUniformfv(service_id, location, result->GetData());
5073 }
[email protected]f7b85372010-02-03 01:11:375074 }
5075 return error;
[email protected]96449d2c2009-11-25 00:01:325076}
5077
[email protected]f7a64ee2010-02-01 22:24:145078error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
[email protected]b9849abf2009-11-25 19:13:195079 uint32 immediate_data_size, const gles2::GetShaderPrecisionFormat& c) {
[email protected]0bfd9882010-02-05 23:02:255080 GLenum shader_type = static_cast<GLenum>(c.shadertype);
5081 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
5082 typedef gles2::GetShaderPrecisionFormat::Result Result;
5083 Result* result = GetSharedMemoryAs<Result*>(
5084 c.result_shm_id, c.result_shm_offset, sizeof(*result));
5085 if (!result) {
5086 return error::kOutOfBounds;
5087 }
[email protected]07d0cc82010-02-17 04:51:405088 // Check that the client initialized the result.
5089 if (result->success != 0) {
5090 return error::kInvalidArguments;
5091 }
[email protected]9438b012010-06-15 22:55:055092 if (!validators_->shader_type.IsValid(shader_type)) {
[email protected]8eee29c2010-04-29 03:38:295093 SetGLError(GL_INVALID_ENUM,
5094 "glGetShaderPrecisionFormat: shader_type GL_INVALID_ENUM");
5095 return error::kNoError;
5096 }
[email protected]9438b012010-06-15 22:55:055097 if (!validators_->shader_precision.IsValid(precision_type)) {
[email protected]8eee29c2010-04-29 03:38:295098 SetGLError(GL_INVALID_ENUM,
5099 "glGetShaderPrecisionFormat: precision_type GL_INVALID_ENUM");
5100 return error::kNoError;
5101 }
5102
5103 result->success = 1; // true
5104 switch (precision_type) {
5105 case GL_LOW_INT:
5106 case GL_MEDIUM_INT:
5107 case GL_HIGH_INT:
5108 result->min_range = -31;
5109 result->max_range = 31;
5110 result->precision = 0;
[email protected]4e8a5b122010-05-08 22:00:105111 break;
[email protected]8eee29c2010-04-29 03:38:295112 case GL_LOW_FLOAT:
5113 case GL_MEDIUM_FLOAT:
5114 case GL_HIGH_FLOAT:
5115 result->min_range = -62;
5116 result->max_range = 62;
5117 result->precision = -16;
5118 break;
5119 default:
5120 NOTREACHED();
5121 break;
[email protected]0bfd9882010-02-05 23:02:255122 }
[email protected]f7a64ee2010-02-01 22:24:145123 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325124}
5125
[email protected]f7a64ee2010-02-01 22:24:145126error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
[email protected]b9849abf2009-11-25 19:13:195127 uint32 immediate_data_size, const gles2::GetAttachedShaders& c) {
[email protected]0bfd9882010-02-05 23:02:255128 uint32 result_size = c.result_size;
[email protected]6b8cf1a2010-05-06 16:13:585129 GLuint program = static_cast<GLuint>(c.program);
5130 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
5131 program, "glGetAttachedShaders");
[email protected]ae51d192010-04-27 00:48:035132 if (!info) {
[email protected]0bfd9882010-02-05 23:02:255133 return error::kNoError;
5134 }
5135 typedef gles2::GetAttachedShaders::Result Result;
5136 uint32 max_count = Result::ComputeMaxResults(result_size);
5137 Result* result = GetSharedMemoryAs<Result*>(
5138 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
5139 if (!result) {
5140 return error::kOutOfBounds;
5141 }
[email protected]07d0cc82010-02-17 04:51:405142 // Check that the client initialized the result.
5143 if (result->size != 0) {
5144 return error::kInvalidArguments;
5145 }
[email protected]0bfd9882010-02-05 23:02:255146 GLsizei count = 0;
[email protected]ae51d192010-04-27 00:48:035147 glGetAttachedShaders(
5148 info->service_id(), max_count, &count, result->GetData());
[email protected]0bfd9882010-02-05 23:02:255149 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]ae51d192010-04-27 00:48:035150 if (!shader_manager()->GetClientId(result->GetData()[ii],
5151 &result->GetData()[ii])) {
[email protected]0bfd9882010-02-05 23:02:255152 NOTREACHED();
5153 return error::kGenericError;
5154 }
5155 }
5156 result->SetNumResults(count);
[email protected]f7a64ee2010-02-01 22:24:145157 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325158}
5159
[email protected]f7a64ee2010-02-01 22:24:145160error::Error GLES2DecoderImpl::HandleGetActiveUniform(
[email protected]b9849abf2009-11-25 19:13:195161 uint32 immediate_data_size, const gles2::GetActiveUniform& c) {
[email protected]0bfd9882010-02-05 23:02:255162 GLuint program = c.program;
5163 GLuint index = c.index;
5164 uint32 name_bucket_id = c.name_bucket_id;
[email protected]0bfd9882010-02-05 23:02:255165 typedef gles2::GetActiveUniform::Result Result;
5166 Result* result = GetSharedMemoryAs<Result*>(
5167 c.result_shm_id, c.result_shm_offset, sizeof(*result));
5168 if (!result) {
5169 return error::kOutOfBounds;
5170 }
[email protected]07d0cc82010-02-17 04:51:405171 // Check that the client initialized the result.
5172 if (result->success != 0) {
5173 return error::kInvalidArguments;
5174 }
[email protected]6b8cf1a2010-05-06 16:13:585175 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
5176 program, "glGetActiveUniform");
[email protected]ae51d192010-04-27 00:48:035177 if (!info) {
[email protected]0bfd9882010-02-05 23:02:255178 return error::kNoError;
5179 }
5180 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
5181 info->GetUniformInfo(index);
5182 if (!uniform_info) {
[email protected]8eee29c2010-04-29 03:38:295183 SetGLError(GL_INVALID_VALUE, "glGetActiveUniform: index out of range");
[email protected]0bfd9882010-02-05 23:02:255184 return error::kNoError;
5185 }
5186 result->success = 1; // true.
5187 result->size = uniform_info->size;
5188 result->type = uniform_info->type;
5189 Bucket* bucket = CreateBucket(name_bucket_id);
5190 bucket->SetFromString(uniform_info->name);
[email protected]f7a64ee2010-02-01 22:24:145191 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325192}
5193
[email protected]f7a64ee2010-02-01 22:24:145194error::Error GLES2DecoderImpl::HandleGetActiveAttrib(
[email protected]b9849abf2009-11-25 19:13:195195 uint32 immediate_data_size, const gles2::GetActiveAttrib& c) {
[email protected]0bfd9882010-02-05 23:02:255196 GLuint program = c.program;
5197 GLuint index = c.index;
5198 uint32 name_bucket_id = c.name_bucket_id;
[email protected]0bfd9882010-02-05 23:02:255199 typedef gles2::GetActiveAttrib::Result Result;
5200 Result* result = GetSharedMemoryAs<Result*>(
5201 c.result_shm_id, c.result_shm_offset, sizeof(*result));
5202 if (!result) {
5203 return error::kOutOfBounds;
5204 }
[email protected]07d0cc82010-02-17 04:51:405205 // Check that the client initialized the result.
5206 if (result->success != 0) {
5207 return error::kInvalidArguments;
5208 }
[email protected]6b8cf1a2010-05-06 16:13:585209 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
5210 program, "glGetActiveAttrib");
[email protected]ae51d192010-04-27 00:48:035211 if (!info) {
[email protected]0bfd9882010-02-05 23:02:255212 return error::kNoError;
5213 }
5214 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
5215 info->GetAttribInfo(index);
5216 if (!attrib_info) {
[email protected]8eee29c2010-04-29 03:38:295217 SetGLError(GL_INVALID_VALUE, "glGetActiveAttrib: index out of range");
[email protected]0bfd9882010-02-05 23:02:255218 return error::kNoError;
5219 }
5220 result->success = 1; // true.
5221 result->size = attrib_info->size;
5222 result->type = attrib_info->type;
5223 Bucket* bucket = CreateBucket(name_bucket_id);
5224 bucket->SetFromString(attrib_info->name);
[email protected]f7a64ee2010-02-01 22:24:145225 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325226}
5227
[email protected]b273e432010-04-12 17:23:585228error::Error GLES2DecoderImpl::HandleShaderBinary(
5229 uint32 immediate_data_size, const gles2::ShaderBinary& c) {
5230#if 1 // No binary shader support.
[email protected]8eee29c2010-04-29 03:38:295231 SetGLError(GL_INVALID_OPERATION, "glShaderBinary: not supported");
[email protected]b273e432010-04-12 17:23:585232 return error::kNoError;
5233#else
5234 GLsizei n = static_cast<GLsizei>(c.n);
5235 if (n < 0) {
[email protected]8eee29c2010-04-29 03:38:295236 SetGLError(GL_INVALID_VALUE, "glShaderBinary: n < 0");
[email protected]b273e432010-04-12 17:23:585237 return error::kNoError;
5238 }
5239 GLsizei length = static_cast<GLsizei>(c.length);
5240 if (length < 0) {
[email protected]8eee29c2010-04-29 03:38:295241 SetGLError(GL_INVALID_VALUE, "glShaderBinary: length < 0");
[email protected]b273e432010-04-12 17:23:585242 return error::kNoError;
5243 }
5244 uint32 data_size;
5245 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
5246 return error::kOutOfBounds;
5247 }
5248 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
5249 c.shaders_shm_id, c.shaders_shm_offset, data_size);
5250 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
5251 const void* binary = GetSharedMemoryAs<const void*>(
5252 c.binary_shm_id, c.binary_shm_offset, length);
5253 if (shaders == NULL || binary == NULL) {
5254 return error::kOutOfBounds;
5255 }
5256 scoped_array<GLuint> service_ids(new GLuint[n]);
5257 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:035258 ShaderManager::ShaderInfo* info = GetShaderInfo(shaders[ii]);
5259 if (!info) {
[email protected]8eee29c2010-04-29 03:38:295260 SetGLError(GL_INVALID_VALUE, "glShaderBinary: unknown shader");
[email protected]b273e432010-04-12 17:23:585261 return error::kNoError;
5262 }
[email protected]ae51d192010-04-27 00:48:035263 service_ids[ii] = info->service_id();
[email protected]b273e432010-04-12 17:23:585264 }
5265 // TODO(gman): call glShaderBinary
5266 return error::kNoError;
5267#endif
5268}
5269
[email protected]6217d392010-03-25 22:08:355270error::Error GLES2DecoderImpl::HandleSwapBuffers(
5271 uint32 immediate_data_size, const gles2::SwapBuffers& c) {
[email protected]6217d392010-03-25 22:08:355272 // If offscreen then don't actually SwapBuffers to the display. Just copy
5273 // the rendered frame to another frame buffer.
5274 if (offscreen_target_frame_buffer_.get()) {
5275 ScopedGLErrorSuppressor suppressor(this);
5276
5277 // First check to see if a deferred offscreen render buffer resize is
5278 // pending.
5279 if (!UpdateOffscreenFrameBufferSize())
5280 return error::kLostContext;
5281
[email protected]0c8c9d22010-06-25 17:36:395282 if (parent_) {
5283 ScopedFrameBufferBinder binder(this,
5284 offscreen_target_frame_buffer_->id());
5285 offscreen_saved_color_texture_->Copy(
5286 offscreen_saved_color_texture_->size());
5287 }
[email protected]6217d392010-03-25 22:08:355288 } else {
[email protected]d37231fa2010-04-09 21:16:025289 context_->SwapBuffers();
[email protected]6217d392010-03-25 22:08:355290 }
5291
[email protected]7d9ce4f2010-04-14 18:39:405292 // TODO(kbr): when the back buffer is multisampled, then at least on Mac
5293 // OS X (and probably on all platforms, for best semantics), we will need
5294 // to perform the resolve step and bind the offscreen_saved_color_texture_
5295 // as the color attachment before calling the swap buffers callback, which
5296 // expects a normal (non-multisampled) frame buffer for glCopyTexImage2D /
5297 // glReadPixels. After the callback runs, the multisampled frame buffer
5298 // needs to be bound again.
5299
[email protected]6217d392010-03-25 22:08:355300 if (swap_buffers_callback_.get()) {
5301 swap_buffers_callback_->Run();
5302 }
5303
5304 return error::kNoError;
5305}
5306
[email protected]b1d2dcb2010-05-17 19:24:185307error::Error GLES2DecoderImpl::HandleCommandBufferEnable(
5308 uint32 immediate_data_size, const gles2::CommandBufferEnable& c) {
5309 Bucket* bucket = GetBucket(c.bucket_id);
5310 typedef gles2::CommandBufferEnable::Result Result;
5311 Result* result = GetSharedMemoryAs<Result*>(
5312 c.result_shm_id, c.result_shm_offset, sizeof(*result));
5313 if (!result) {
5314 return error::kOutOfBounds;
[email protected]4e8a5b122010-05-08 22:00:105315 }
[email protected]b1d2dcb2010-05-17 19:24:185316 // Check that the client initialized the result.
5317 if (*result != 0) {
5318 return error::kInvalidArguments;
5319 }
5320 std::string feature_str;
5321 if (!bucket->GetAsString(&feature_str)) {
5322 return error::kInvalidArguments;
5323 }
5324
5325 // TODO(gman): make this some kind of table to function pointer thingy.
5326 if (feature_str.compare(PEPPER3D_ALLOW_BUFFERS_ON_MULTIPLE_TARGETS) == 0) {
5327 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
5328 } else if (feature_str.compare(PEPPER3D_SKIP_GLSL_TRANSLATION) == 0) {
5329 use_shader_translator_ = false;
5330 } else {
5331 return error::kNoError;
5332 }
5333
5334 *result = 1; // true.
5335 return error::kNoError;
[email protected]4e8a5b122010-05-08 22:00:105336}
5337
[email protected]96449d2c2009-11-25 00:01:325338// Include the auto-generated part of this file. We split this because it means
5339// we can easily edit the non-auto generated parts right here in this file
5340// instead of having to edit some template or the code generator.
5341#include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
5342
5343} // namespace gles2
[email protected]a7a27ace2009-12-12 00:11:255344} // namespace gpu