blob: c081fa2174c382964383eac771ddf97a660afaf0 [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]2041cf342010-02-19 03:15:5916#include "base/callback.h"
[email protected]96449d2c2009-11-25 00:01:3217#include "base/scoped_ptr.h"
[email protected]6217d392010-03-25 22:08:3518#include "base/weak_ptr.h"
[email protected]d37231fa2010-04-09 21:16:0219#include "build/build_config.h"
[email protected]96449d2c2009-11-25 00:01:3220#define GLES2_GPU_SERVICE 1
21#include "gpu/command_buffer/common/gles2_cmd_format.h"
22#include "gpu/command_buffer/common/gles2_cmd_utils.h"
[email protected]066849e32010-05-03 19:14:1023#include "gpu/command_buffer/common/id_allocator.h"
[email protected]3916c97e2010-02-25 03:20:5024#include "gpu/command_buffer/service/buffer_manager.h"
[email protected]96449d2c2009-11-25 00:01:3225#include "gpu/command_buffer/service/cmd_buffer_engine.h"
[email protected]3916c97e2010-02-25 03:20:5026#include "gpu/command_buffer/service/context_group.h"
[email protected]a25fa872010-03-25 02:57:5827#include "gpu/command_buffer/service/framebuffer_manager.h"
[email protected]96449d2c2009-11-25 00:01:3228#include "gpu/command_buffer/service/gl_utils.h"
[email protected]ba3176a2009-12-16 18:19:4629#include "gpu/command_buffer/service/gles2_cmd_validation.h"
[email protected]a93bb842010-02-16 23:03:4730#include "gpu/command_buffer/service/program_manager.h"
[email protected]a25fa872010-03-25 02:57:5831#include "gpu/command_buffer/service/renderbuffer_manager.h"
[email protected]a93bb842010-02-16 23:03:4732#include "gpu/command_buffer/service/shader_manager.h"
33#include "gpu/command_buffer/service/texture_manager.h"
[email protected]4e8a5b122010-05-08 22:00:1034#include "gpu/GLES2/gles2_command_buffer.h"
[email protected]2cb1fa92010-05-13 20:30:5135
[email protected]2cb1fa92010-05-13 20:30:5136#if defined(GLES2_GPU_SERVICE_TRANSLATE_SHADER)
[email protected]3094c2a2010-04-29 21:50:4537#include "third_party/angle/include/GLSLANG/ShaderLang.h"
[email protected]2cb1fa92010-05-13 20:30:5138#endif // GLES2_GPU_SERVICE_TRANSLATE_SHADER
[email protected]de17df392010-04-23 21:09:4139
[email protected]6217d392010-03-25 22:08:3540#if !defined(GL_DEPTH24_STENCIL8)
41#define GL_DEPTH24_STENCIL8 0x88F0
42#endif
43
[email protected]a7a27ace2009-12-12 00:11:2544namespace gpu {
[email protected]96449d2c2009-11-25 00:01:3245namespace gles2 {
46
[email protected]6217d392010-03-25 22:08:3547class GLES2DecoderImpl;
48
[email protected]07f54fcc2009-12-22 02:46:3049// Check that certain assumptions the code makes are true. There are places in
50// the code where shared memory is passed direclty to GL. Example, glUniformiv,
51// glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
52// a few others) are 32bits. If they are not 32bits the code will have to change
53// to call those GL functions with service side memory and then copy the results
54// to shared memory, converting the sizes.
55COMPILE_ASSERT(sizeof(GLint) == sizeof(uint32), // NOLINT
56 GLint_not_same_size_as_uint32);
57COMPILE_ASSERT(sizeof(GLsizei) == sizeof(uint32), // NOLINT
58 GLint_not_same_size_as_uint32);
[email protected]f7b85372010-02-03 01:11:3759COMPILE_ASSERT(sizeof(GLfloat) == sizeof(float), // NOLINT
60 GLfloat_not_same_size_as_float);
[email protected]07f54fcc2009-12-22 02:46:3061
[email protected]43f28f832010-02-03 02:28:4862// TODO(kbr): the use of this anonymous namespace core dumps the
63// linker on Mac OS X 10.6 when the symbol ordering file is used
64// namespace {
[email protected]96449d2c2009-11-25 00:01:3265
66// Returns the address of the first byte after a struct.
67template <typename T>
68const void* AddressAfterStruct(const T& pod) {
69 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
70}
71
[email protected]07f54fcc2009-12-22 02:46:3072// Returns the address of the frst byte after the struct or NULL if size >
73// immediate_data_size.
[email protected]96449d2c2009-11-25 00:01:3274template <typename RETURN_TYPE, typename COMMAND_TYPE>
[email protected]07f54fcc2009-12-22 02:46:3075RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod,
76 uint32 size,
77 uint32 immediate_data_size) {
78 return (size <= immediate_data_size) ?
79 static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))) :
80 NULL;
[email protected]96449d2c2009-11-25 00:01:3281}
82
[email protected]07f54fcc2009-12-22 02:46:3083// Computes the data size for certain gl commands like glUniform.
[email protected]a76b0052010-03-05 00:33:1884bool ComputeDataSize(
[email protected]96449d2c2009-11-25 00:01:3285 GLuint count,
86 size_t size,
[email protected]a76b0052010-03-05 00:33:1887 unsigned int elements_per_unit,
88 uint32* dst) {
89 uint32 value;
90 if (!SafeMultiplyUint32(count, size, &value)) {
91 return false;
92 }
93 if (!SafeMultiplyUint32(value, elements_per_unit, &value)) {
94 return false;
95 }
96 *dst = value;
97 return true;
[email protected]96449d2c2009-11-25 00:01:3298}
99
100// A struct to hold info about each command.
101struct CommandInfo {
102 int arg_flags; // How to handle the arguments for this command
103 int arg_count; // How many arguments are expected for this command.
104};
105
106// A table of CommandInfo for all the commands.
107const CommandInfo g_command_info[] = {
108 #define GLES2_CMD_OP(name) { \
109 name::kArgFlags, \
110 sizeof(name) / sizeof(CommandBufferEntry) - 1, }, /* NOLINT */ \
111
112 GLES2_COMMAND_LIST(GLES2_CMD_OP)
113
114 #undef GLES2_CMD_OP
115};
116
[email protected]6217d392010-03-25 22:08:35117// This class prevents any GL errors that occur when it is in scope from
118// being reported to the client.
119class ScopedGLErrorSuppressor {
120 public:
121 explicit ScopedGLErrorSuppressor(GLES2DecoderImpl* decoder);
122 ~ScopedGLErrorSuppressor();
123 private:
124 GLES2DecoderImpl* decoder_;
125 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor);
126};
127
128// Temporarily changes a decoder's bound 2D texture and restore it when this
129// object goes out of scope. Also temporarily switches to using active texture
130// unit zero in case the client has changed that to something invalid.
131class ScopedTexture2DBinder {
132 public:
133 ScopedTexture2DBinder(GLES2DecoderImpl* decoder, GLuint id);
134 ~ScopedTexture2DBinder();
135
136 private:
137 GLES2DecoderImpl* decoder_;
138 DISALLOW_COPY_AND_ASSIGN(ScopedTexture2DBinder);
139};
140
141// Temporarily changes a decoder's bound render buffer and restore it when this
142// object goes out of scope.
143class ScopedRenderBufferBinder {
144 public:
145 ScopedRenderBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
146 ~ScopedRenderBufferBinder();
147
148 private:
149 GLES2DecoderImpl* decoder_;
150 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder);
151};
152
153// Temporarily changes a decoder's bound frame buffer and restore it when this
154// object goes out of scope.
155class ScopedFrameBufferBinder {
156 public:
157 ScopedFrameBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
158 ~ScopedFrameBufferBinder();
159
160 private:
161 GLES2DecoderImpl* decoder_;
162 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder);
163};
164
[email protected]2f2d7042010-04-14 21:45:58165// Temporarily switch to a decoder's default GL context, having known default
166// state.
167class ScopedDefaultGLContext {
168 public:
169 explicit ScopedDefaultGLContext(GLES2DecoderImpl* decoder);
170 ~ScopedDefaultGLContext();
171
172 private:
173 GLES2DecoderImpl* decoder_;
174 DISALLOW_COPY_AND_ASSIGN(ScopedDefaultGLContext);
175};
176
[email protected]6217d392010-03-25 22:08:35177// Encapsulates an OpenGL texture.
178class Texture {
179 public:
180 explicit Texture(GLES2DecoderImpl* decoder);
181 ~Texture();
182
183 // Create a new render texture.
184 void Create();
185
186 // Set the initial size and format of a render texture or resize it.
187 bool AllocateStorage(const gfx::Size& size);
188
189 // Copy the contents of the currently bound frame buffer.
190 void Copy(const gfx::Size& size);
191
192 // Destroy the render texture. This must be explicitly called before
193 // destroying this object.
194 void Destroy();
195
196 GLuint id() const {
197 return id_;
198 }
199
[email protected]d37231fa2010-04-09 21:16:02200 gfx::Size size() const {
201 return size_;
202 }
203
[email protected]6217d392010-03-25 22:08:35204 private:
205 GLES2DecoderImpl* decoder_;
206 GLuint id_;
[email protected]d37231fa2010-04-09 21:16:02207 gfx::Size size_;
[email protected]6217d392010-03-25 22:08:35208 DISALLOW_COPY_AND_ASSIGN(Texture);
209};
210
211// Encapsulates an OpenGL render buffer of any format.
212class RenderBuffer {
213 public:
214 explicit RenderBuffer(GLES2DecoderImpl* decoder);
215 ~RenderBuffer();
216
217 // Create a new render buffer.
218 void Create();
219
220 // Set the initial size and format of a render buffer or resize it.
221 bool AllocateStorage(const gfx::Size& size, GLenum format);
222
223 // Destroy the render buffer. This must be explicitly called before destroying
224 // this object.
225 void Destroy();
226
227 GLuint id() const {
228 return id_;
229 }
230
231 private:
232 GLES2DecoderImpl* decoder_;
233 GLuint id_;
234 DISALLOW_COPY_AND_ASSIGN(RenderBuffer);
235};
236
237// Encapsulates an OpenGL frame buffer.
238class FrameBuffer {
239 public:
240 explicit FrameBuffer(GLES2DecoderImpl* decoder);
241 ~FrameBuffer();
242
243 // Create a new frame buffer.
244 void Create();
245
246 // Attach a color render buffer to a frame buffer.
247 void AttachRenderTexture(Texture* texture);
248
249 // Attach a depth stencil render buffer to a frame buffer. Note that
250 // this unbinds any currently bound frame buffer.
251 void AttachDepthStencilRenderBuffer(RenderBuffer* render_buffer);
252
253 // Clear the given attached buffers.
254 void Clear(GLbitfield buffers);
255
256 // Destroy the frame buffer. This must be explicitly called before destroying
257 // this object.
258 void Destroy();
259
260 // See glCheckFramebufferStatusEXT.
261 GLenum CheckStatus();
262
263 GLuint id() const {
264 return id_;
265 }
266
267 private:
268 GLES2DecoderImpl* decoder_;
269 GLuint id_;
270 DISALLOW_COPY_AND_ASSIGN(FrameBuffer);
271};
[email protected]43f28f832010-02-03 02:28:48272// } // anonymous namespace.
[email protected]96449d2c2009-11-25 00:01:32273
[email protected]3916c97e2010-02-25 03:20:50274GLES2Decoder::GLES2Decoder(ContextGroup* group)
275 : group_(group),
[email protected]3916c97e2010-02-25 03:20:50276 debug_(false) {
[email protected]96449d2c2009-11-25 00:01:32277}
278
[email protected]3916c97e2010-02-25 03:20:50279GLES2Decoder::~GLES2Decoder() {
280}
281
[email protected]f39f4b3f2010-05-12 17:04:08282class VertexAttribManager {
[email protected]96449d2c2009-11-25 00:01:32283 public:
[email protected]07f54fcc2009-12-22 02:46:30284 // Info about Vertex Attributes. This is used to track what the user currently
285 // has bound on each Vertex Attribute so that checking can be done at
286 // glDrawXXX time.
287 class VertexAttribInfo {
288 public:
[email protected]f39f4b3f2010-05-12 17:04:08289 typedef std::list<VertexAttribInfo*> VertexAttribInfoList;
[email protected]b1122982010-05-17 23:04:24290 struct Vec4 {
291 float v[4];
292 };
[email protected]f39f4b3f2010-05-12 17:04:08293
[email protected]07f54fcc2009-12-22 02:46:30294 VertexAttribInfo()
[email protected]f39f4b3f2010-05-12 17:04:08295 : index_(0),
296 enabled_(false),
297 size_(4),
298 type_(GL_FLOAT),
[email protected]07f54fcc2009-12-22 02:46:30299 offset_(0),
[email protected]b1122982010-05-17 23:04:24300 normalized_(GL_FALSE),
301 gl_stride_(0),
[email protected]f39f4b3f2010-05-12 17:04:08302 real_stride_(16),
303 list_(NULL) {
[email protected]b1122982010-05-17 23:04:24304 value_.v[0] = 0.0f;
305 value_.v[1] = 0.0f;
306 value_.v[2] = 0.0f;
307 value_.v[3] = 1.0f;
[email protected]07f54fcc2009-12-22 02:46:30308 }
[email protected]3916c97e2010-02-25 03:20:50309
[email protected]07f54fcc2009-12-22 02:46:30310 // Returns true if this VertexAttrib can access index.
[email protected]f39f4b3f2010-05-12 17:04:08311 bool CanAccess(GLuint index) const;
[email protected]07f54fcc2009-12-22 02:46:30312
[email protected]3916c97e2010-02-25 03:20:50313 BufferManager::BufferInfo* buffer() const {
[email protected]07f54fcc2009-12-22 02:46:30314 return buffer_;
315 }
316
[email protected]8bf5a3e2010-01-29 04:21:36317 GLsizei offset() const {
318 return offset_;
319 }
320
[email protected]f39f4b3f2010-05-12 17:04:08321 GLuint index() const {
322 return index_;
323 }
324
[email protected]b1122982010-05-17 23:04:24325 GLint size() const {
326 return size_;
327 }
328
329 GLenum type() const {
330 return type_;
331 }
332
333 GLboolean normalized() const {
334 return normalized_;
335 }
336
337 GLsizei gl_stride() const {
338 return gl_stride_;
339 }
340
[email protected]07f54fcc2009-12-22 02:46:30341 void SetInfo(
[email protected]3916c97e2010-02-25 03:20:50342 BufferManager::BufferInfo* buffer,
[email protected]07f54fcc2009-12-22 02:46:30343 GLint size,
344 GLenum type,
[email protected]b1122982010-05-17 23:04:24345 GLboolean normalized,
346 GLsizei gl_stride,
[email protected]07f54fcc2009-12-22 02:46:30347 GLsizei real_stride,
348 GLsizei offset) {
[email protected]8a837bb2010-01-05 00:21:24349 DCHECK_GT(real_stride, 0);
[email protected]07f54fcc2009-12-22 02:46:30350 buffer_ = buffer;
351 size_ = size;
352 type_ = type;
[email protected]b1122982010-05-17 23:04:24353 normalized_ = normalized;
354 gl_stride_ = gl_stride;
[email protected]07f54fcc2009-12-22 02:46:30355 real_stride_ = real_stride;
356 offset_ = offset;
[email protected]3916c97e2010-02-25 03:20:50357 }
358
359 void ClearBuffer() {
360 buffer_ = NULL;
[email protected]07f54fcc2009-12-22 02:46:30361 }
362
[email protected]f39f4b3f2010-05-12 17:04:08363 bool enabled() const {
364 return enabled_;
365 }
366
[email protected]b1122982010-05-17 23:04:24367 void set_value(const Vec4& value) {
368 value_ = value;
369 }
370
371 const Vec4& value() const {
372 return value_;
373 }
374
[email protected]07f54fcc2009-12-22 02:46:30375 private:
[email protected]f39f4b3f2010-05-12 17:04:08376 friend class VertexAttribManager;
377
378 void set_enabled(bool enabled) {
379 enabled_ = enabled;
380 }
381
382 void set_index(GLuint index) {
383 index_ = index;
384 }
385
386 void SetList(VertexAttribInfoList* new_list) {
387 DCHECK(new_list);
388
389 if (list_) {
390 list_->erase(it_);
391 }
392
393 it_ = new_list->insert(new_list->end(), this);
394 list_ = new_list;
395 }
396
397 // The index of this attrib.
398 GLuint index_;
399
[email protected]07f54fcc2009-12-22 02:46:30400 // Whether or not this attribute is enabled.
401 bool enabled_;
402
403 // number of components (1, 2, 3, 4)
404 GLint size_;
405
406 // GL_BYTE, GL_FLOAT, etc. See glVertexAttribPointer.
407 GLenum type_;
408
409 // The offset into the buffer.
410 GLsizei offset_;
411
[email protected]b1122982010-05-17 23:04:24412 GLboolean normalized_;
413
414 // The stride passed to glVertexAttribPointer.
415 GLsizei gl_stride_;
416
[email protected]07f54fcc2009-12-22 02:46:30417 // The stride that will be used to access the buffer. This is the actual
418 // stide, NOT the GL bogus stride. In other words there is never a stride
419 // of 0.
420 GLsizei real_stride_;
421
[email protected]b1122982010-05-17 23:04:24422 // The current value of the attrib.
423 Vec4 value_;
424
[email protected]3916c97e2010-02-25 03:20:50425 // The buffer bound to this attribute.
426 BufferManager::BufferInfo::Ref buffer_;
[email protected]f39f4b3f2010-05-12 17:04:08427
428 // List this info is on.
429 VertexAttribInfoList* list_;
430
431 // Iterator for list this info is on. Enabled/Disabled
432 VertexAttribInfoList::iterator it_;
[email protected]07f54fcc2009-12-22 02:46:30433 };
434
[email protected]f39f4b3f2010-05-12 17:04:08435 typedef std::list<VertexAttribInfo*> VertexAttribInfoList;
436
437 VertexAttribManager()
438 : max_vertex_attribs_(0) {
439 }
440
441 void Initialize(uint32 num_vertex_attribs);
442
443 bool Enable(GLuint index, bool enable);
444
445 const VertexAttribInfoList& GetEnabledVertexAttribInfos() const {
446 return enabled_vertex_attribs_;
447 }
448
449 VertexAttribInfo* GetVertexAttribInfo(GLuint index) {
[email protected]b1122982010-05-17 23:04:24450 if (index < max_vertex_attribs_) {
451 return &vertex_attrib_infos_[index];
452 }
453 return NULL;
[email protected]f39f4b3f2010-05-12 17:04:08454 }
455
456 private:
457 uint32 max_vertex_attribs_;
458
459 // Info for each vertex attribute saved so we can check at glDrawXXX time
460 // if it is safe to draw.
461 scoped_array<VertexAttribInfo> vertex_attrib_infos_;
462
463 // Lists for which vertex attribs are enabled, disabled.
464 VertexAttribInfoList enabled_vertex_attribs_;
465 VertexAttribInfoList disabled_vertex_attribs_;
466};
467
468bool VertexAttribManager::VertexAttribInfo::CanAccess(GLuint index) const {
469 if (!enabled_) {
470 return true;
471 }
472
473 if (!buffer_ || buffer_->IsDeleted()) {
474 return false;
475 }
476
477 // The number of elements that can be accessed.
478 GLsizeiptr buffer_size = buffer_->size();
479 if (offset_ > buffer_size || real_stride_ == 0) {
480 return false;
481 }
482
483 uint32 usable_size = buffer_size - offset_;
484 GLuint num_elements = usable_size / real_stride_ +
485 ((usable_size % real_stride_) >=
486 (GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type_) * size_) ? 1 : 0);
487 return index < num_elements;
488}
489
490
491void VertexAttribManager::Initialize(uint32 max_vertex_attribs) {
492 max_vertex_attribs_ = max_vertex_attribs;
493 vertex_attrib_infos_.reset(
494 new VertexAttribInfo[max_vertex_attribs]);
495 for (uint32 vv = 0; vv < max_vertex_attribs; ++vv) {
496 vertex_attrib_infos_[vv].set_index(vv);
497 vertex_attrib_infos_[vv].SetList(&disabled_vertex_attribs_);
498 }
499}
500
501bool VertexAttribManager::Enable(GLuint index, bool enable) {
502 if (index >= max_vertex_attribs_) {
503 return false;
504 }
505 VertexAttribInfo& info = vertex_attrib_infos_[index];
506 if (info.enabled() != enable) {
507 info.set_enabled(enable);
508 info.SetList(enable ? &enabled_vertex_attribs_ : &disabled_vertex_attribs_);
509 }
510 return true;
511}
512
513// This class implements GLES2Decoder so we don't have to expose all the GLES2
514// cmd stuff to outside this class.
515class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
516 public GLES2Decoder {
517 public:
518 explicit GLES2DecoderImpl(ContextGroup* group);
519
[email protected]96449d2c2009-11-25 00:01:32520 // Overridden from AsyncAPIInterface.
[email protected]f7a64ee2010-02-01 22:24:14521 virtual Error DoCommand(unsigned int command,
[email protected]3916c97e2010-02-25 03:20:50522 unsigned int arg_count,
523 const void* args);
[email protected]96449d2c2009-11-25 00:01:32524
525 // Overridden from AsyncAPIInterface.
526 virtual const char* GetCommandName(unsigned int command_id) const;
527
528 // Overridden from GLES2Decoder.
[email protected]5a6db6c2010-04-22 18:32:06529 virtual bool Initialize(gfx::GLContext* context,
[email protected]6217d392010-03-25 22:08:35530 const gfx::Size& size,
[email protected]d37231fa2010-04-09 21:16:02531 GLES2Decoder* parent,
[email protected]6217d392010-03-25 22:08:35532 uint32 parent_client_texture_id);
[email protected]96449d2c2009-11-25 00:01:32533 virtual void Destroy();
[email protected]6217d392010-03-25 22:08:35534 virtual void ResizeOffscreenFrameBuffer(const gfx::Size& size);
[email protected]eb54a562010-01-20 21:55:18535 virtual bool MakeCurrent();
[email protected]56ac89b2010-03-17 21:16:55536 virtual GLES2Util* GetGLES2Util() { return &util_; }
[email protected]5a6db6c2010-04-22 18:32:06537 virtual gfx::GLContext* GetGLContext() { return context_; }
[email protected]43f28f832010-02-03 02:28:48538
539 virtual void SetSwapBuffersCallback(Callback0::Type* callback);
540
[email protected]96449d2c2009-11-25 00:01:32541 private:
[email protected]6217d392010-03-25 22:08:35542 friend class ScopedGLErrorSuppressor;
543 friend class ScopedTexture2DBinder;
544 friend class ScopedFrameBufferBinder;
545 friend class ScopedRenderBufferBinder;
[email protected]2f2d7042010-04-14 21:45:58546 friend class ScopedDefaultGLContext;
[email protected]6217d392010-03-25 22:08:35547 friend class RenderBuffer;
548 friend class FrameBuffer;
549
[email protected]3916c97e2010-02-25 03:20:50550 // State associated with each texture unit.
551 struct TextureUnit {
552 TextureUnit() : bind_target(GL_TEXTURE_2D) { }
553
554 // The last target that was bound to this texture unit.
555 GLenum bind_target;
556
557 // texture currently bound to this unit's GL_TEXTURE_2D with glBindTexture
558 TextureManager::TextureInfo::Ref bound_texture_2d;
559
560 // texture currently bound to this unit's GL_TEXTURE_CUBE_MAP with
561 // glBindTexture
562 TextureManager::TextureInfo::Ref bound_texture_cube_map;
563 };
564
[email protected]ae51d192010-04-27 00:48:03565 // Helpers for the glGen and glDelete functions.
566 bool GenTexturesHelper(GLsizei n, const GLuint* client_ids);
567 void DeleteTexturesHelper(GLsizei n, const GLuint* client_ids);
568 bool GenBuffersHelper(GLsizei n, const GLuint* client_ids);
569 void DeleteBuffersHelper(GLsizei n, const GLuint* client_ids);
570 bool GenFramebuffersHelper(GLsizei n, const GLuint* client_ids);
571 void DeleteFramebuffersHelper(GLsizei n, const GLuint* client_ids);
572 bool GenRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
573 void DeleteRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
[email protected]a93bb842010-02-16 23:03:47574
[email protected]3916c97e2010-02-25 03:20:50575 // TODO(gman): Cache these pointers?
[email protected]3916c97e2010-02-25 03:20:50576 BufferManager* buffer_manager() {
577 return group_->buffer_manager();
578 }
579
[email protected]a25fa872010-03-25 02:57:58580 RenderbufferManager* renderbuffer_manager() {
581 return group_->renderbuffer_manager();
582 }
583
584 FramebufferManager* framebuffer_manager() {
585 return group_->framebuffer_manager();
586 }
587
[email protected]3916c97e2010-02-25 03:20:50588 ProgramManager* program_manager() {
589 return group_->program_manager();
590 }
591
592 ShaderManager* shader_manager() {
593 return group_->shader_manager();
594 }
595
596 TextureManager* texture_manager() {
597 return group_->texture_manager();
598 }
599
[email protected]6217d392010-03-25 22:08:35600 bool UpdateOffscreenFrameBufferSize();
601
[email protected]a93bb842010-02-16 23:03:47602 // Creates a TextureInfo for the given texture.
[email protected]ae51d192010-04-27 00:48:03603 TextureManager::TextureInfo* CreateTextureInfo(
604 GLuint client_id, GLuint service_id) {
605 return texture_manager()->CreateTextureInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47606 }
607
608 // Gets the texture info for the given texture. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03609 TextureManager::TextureInfo* GetTextureInfo(GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:50610 TextureManager::TextureInfo* info =
[email protected]ae51d192010-04-27 00:48:03611 texture_manager()->GetTextureInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:50612 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]a93bb842010-02-16 23:03:47613 }
614
615 // Deletes the texture info for the given texture.
[email protected]ae51d192010-04-27 00:48:03616 void RemoveTextureInfo(GLuint client_id) {
617 texture_manager()->RemoveTextureInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:50618 }
[email protected]a93bb842010-02-16 23:03:47619
[email protected]d37231fa2010-04-09 21:16:02620 // Get the size (in pixels) of the currently bound frame buffer (either FBO
621 // or regular back buffer).
622 gfx::Size GetBoundFrameBufferSize();
623
[email protected]a93bb842010-02-16 23:03:47624 // Wrapper for CompressedTexImage2D commands.
625 error::Error DoCompressedTexImage2D(
626 GLenum target,
627 GLint level,
628 GLenum internal_format,
629 GLsizei width,
630 GLsizei height,
631 GLint border,
632 GLsizei image_size,
633 const void* data);
634
635 // Wrapper for TexImage2D commands.
636 error::Error DoTexImage2D(
637 GLenum target,
638 GLint level,
639 GLenum internal_format,
640 GLsizei width,
641 GLsizei height,
642 GLint border,
643 GLenum format,
644 GLenum type,
645 const void* pixels,
646 uint32 pixels_size);
647
648 // Creates a ProgramInfo for the given program.
[email protected]ae51d192010-04-27 00:48:03649 void CreateProgramInfo(GLuint client_id, GLuint service_id) {
650 program_manager()->CreateProgramInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47651 }
652
[email protected]07f54fcc2009-12-22 02:46:30653 // Gets the program info for the given program. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03654 ProgramManager::ProgramInfo* GetProgramInfo(GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:50655 ProgramManager::ProgramInfo* info =
[email protected]ae51d192010-04-27 00:48:03656 program_manager()->GetProgramInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:50657 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]1d32bc82010-01-13 22:06:46658 }
[email protected]07f54fcc2009-12-22 02:46:30659
[email protected]6b8cf1a2010-05-06 16:13:58660 // Gets the program info for the given program. If it's not a program
661 // generates a GL error. Returns NULL if not program.
662 ProgramManager::ProgramInfo* GetProgramInfoNotShader(
663 GLuint client_id, const char* function_name) {
664 ProgramManager::ProgramInfo* info = GetProgramInfo(client_id);
665 if (!info) {
666 if (GetShaderInfo(client_id)) {
667 SetGLError(GL_INVALID_OPERATION,
668 (std::string(function_name) +
669 ": shader passed for program").c_str());
670 } else {
671 SetGLError(GL_INVALID_VALUE,
672 (std::string(function_name) + ": unknown program").c_str());
673 }
674 }
675 return info;
676 }
677
678
[email protected]07f54fcc2009-12-22 02:46:30679 // Deletes the program info for the given program.
[email protected]ae51d192010-04-27 00:48:03680 void RemoveProgramInfo(GLuint client_id) {
681 program_manager()->RemoveProgramInfo(client_id);
[email protected]1d32bc82010-01-13 22:06:46682 }
[email protected]07f54fcc2009-12-22 02:46:30683
[email protected]45bf5152010-02-12 00:11:31684 // Creates a ShaderInfo for the given shader.
[email protected]7cea56d92010-04-28 17:21:38685 void CreateShaderInfo(GLuint client_id,
686 GLuint service_id,
687 GLenum shader_type) {
688 shader_manager()->CreateShaderInfo(client_id, service_id, shader_type);
[email protected]45bf5152010-02-12 00:11:31689 }
690
691 // Gets the shader info for the given shader. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03692 ShaderManager::ShaderInfo* GetShaderInfo(GLuint client_id) {
693 ShaderManager::ShaderInfo* info =
694 shader_manager()->GetShaderInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:50695 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]45bf5152010-02-12 00:11:31696 }
697
[email protected]6b8cf1a2010-05-06 16:13:58698 // Gets the shader info for the given shader. If it's not a shader generates a
699 // GL error. Returns NULL if not shader.
700 ShaderManager::ShaderInfo* GetShaderInfoNotProgram(
701 GLuint client_id, const char* function_name) {
702 ShaderManager::ShaderInfo* info = GetShaderInfo(client_id);
703 if (!info) {
704 if (GetProgramInfo(client_id)) {
705 SetGLError(
706 GL_INVALID_OPERATION,
707 (std::string(function_name) +
708 ": program passed for shader").c_str());
709 } else {
710 SetGLError(GL_INVALID_VALUE,
711 (std::string(function_name) + ": unknown shader").c_str());
712 }
713 }
714 return info;
715 }
716
[email protected]45bf5152010-02-12 00:11:31717 // Deletes the shader info for the given shader.
[email protected]ae51d192010-04-27 00:48:03718 void RemoveShaderInfo(GLuint client_id) {
719 shader_manager()->RemoveShaderInfo(client_id);
[email protected]45bf5152010-02-12 00:11:31720 }
721
[email protected]a93bb842010-02-16 23:03:47722 // Creates a buffer info for the given buffer.
[email protected]ae51d192010-04-27 00:48:03723 void CreateBufferInfo(GLuint client_id, GLuint service_id) {
724 return buffer_manager()->CreateBufferInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47725 }
726
[email protected]07f54fcc2009-12-22 02:46:30727 // Gets the buffer info for the given buffer.
[email protected]ae51d192010-04-27 00:48:03728 BufferManager::BufferInfo* GetBufferInfo(GLuint client_id) {
729 BufferManager::BufferInfo* info =
730 buffer_manager()->GetBufferInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:50731 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]1d32bc82010-01-13 22:06:46732 }
[email protected]07f54fcc2009-12-22 02:46:30733
[email protected]a93bb842010-02-16 23:03:47734 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
735 // on glDeleteBuffers so we can make sure the user does not try to render
736 // with deleted buffers.
[email protected]ae51d192010-04-27 00:48:03737 void RemoveBufferInfo(GLuint client_id);
[email protected]a93bb842010-02-16 23:03:47738
[email protected]a25fa872010-03-25 02:57:58739 // Creates a framebuffer info for the given framebuffer.
[email protected]ae51d192010-04-27 00:48:03740 void CreateFramebufferInfo(GLuint client_id, GLuint service_id) {
741 return framebuffer_manager()->CreateFramebufferInfo(client_id, service_id);
[email protected]a25fa872010-03-25 02:57:58742 }
743
744 // Gets the framebuffer info for the given framebuffer.
745 FramebufferManager::FramebufferInfo* GetFramebufferInfo(
[email protected]ae51d192010-04-27 00:48:03746 GLuint client_id) {
[email protected]a25fa872010-03-25 02:57:58747 FramebufferManager::FramebufferInfo* info =
[email protected]ae51d192010-04-27 00:48:03748 framebuffer_manager()->GetFramebufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58749 return (info && !info->IsDeleted()) ? info : NULL;
750 }
751
752 // Removes the framebuffer info for the given framebuffer.
[email protected]ae51d192010-04-27 00:48:03753 void RemoveFramebufferInfo(GLuint client_id) {
754 framebuffer_manager()->RemoveFramebufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58755 }
756
757 // Creates a renderbuffer info for the given renderbuffer.
[email protected]ae51d192010-04-27 00:48:03758 void CreateRenderbufferInfo(GLuint client_id, GLuint service_id) {
759 return renderbuffer_manager()->CreateRenderbufferInfo(
760 client_id, service_id);
[email protected]a25fa872010-03-25 02:57:58761 }
762
763 // Gets the renderbuffer info for the given renderbuffer.
764 RenderbufferManager::RenderbufferInfo* GetRenderbufferInfo(
[email protected]ae51d192010-04-27 00:48:03765 GLuint client_id) {
[email protected]a25fa872010-03-25 02:57:58766 RenderbufferManager::RenderbufferInfo* info =
[email protected]ae51d192010-04-27 00:48:03767 renderbuffer_manager()->GetRenderbufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58768 return (info && !info->IsDeleted()) ? info : NULL;
769 }
770
771 // Removes the renderbuffer info for the given renderbuffer.
[email protected]ae51d192010-04-27 00:48:03772 void RemoveRenderbufferInfo(GLuint client_id) {
773 renderbuffer_manager()->RemoveRenderbufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58774 }
775
[email protected]558847a2010-03-24 07:02:54776 error::Error GetAttribLocationHelper(
777 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
778 const std::string& name_str);
779
780 error::Error GetUniformLocationHelper(
781 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
782 const std::string& name_str);
783
[email protected]3916c97e2010-02-25 03:20:50784 // Helper for glShaderSource.
785 error::Error ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:03786 GLuint client_id, const char* data, uint32 data_size);
[email protected]07f54fcc2009-12-22 02:46:30787
[email protected]939e7362010-05-13 20:49:10788 // Checks if the current program exists and is valid. If not generates the
789 // appropriate GL error. Returns true if the current program is in a usable
790 // state.
791 bool CheckCurrentProgram(const char* function_name);
792
793 // Checks if the current program exists and is valid and that location is not
794 // -1. If the current program is not valid generates the appropriate GL
795 // error. Returns true if the current program is in a usable state and
796 // location is not -1.
797 bool CheckCurrentProgramForUniform(GLint location, const char* function_name);
798
799 // Gets the type of a uniform for a location in the current program. Sets GL
800 // errors if the current program is not valid. Returns true if the current
801 // program is valid and the location exists.
802 bool GetUniformTypeByLocation(
803 GLint location, const char* function_name, GLenum* type);
804
[email protected]b273e432010-04-12 17:23:58805 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
806 bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
807
[email protected]96449d2c2009-11-25 00:01:32808 // Wrapper for glCreateProgram
[email protected]ae51d192010-04-27 00:48:03809 bool CreateProgramHelper(GLuint client_id);
[email protected]96449d2c2009-11-25 00:01:32810
811 // Wrapper for glCreateShader
[email protected]ae51d192010-04-27 00:48:03812 bool CreateShaderHelper(GLenum type, GLuint client_id);
[email protected]96449d2c2009-11-25 00:01:32813
[email protected]3916c97e2010-02-25 03:20:50814 // Wrapper for glActiveTexture
815 void DoActiveTexture(GLenum texture_unit);
816
[email protected]ae51d192010-04-27 00:48:03817 // Wrapper for glAttachShader
818 void DoAttachShader(GLuint client_program_id, GLint client_shader_id);
819
[email protected]96449d2c2009-11-25 00:01:32820 // Wrapper for glBindBuffer since we need to track the current targets.
821 void DoBindBuffer(GLenum target, GLuint buffer);
822
[email protected]86093972010-03-11 00:13:56823 // Wrapper for glBindFramebuffer since we need to track the current targets.
824 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
825
826 // Wrapper for glBindRenderbuffer since we need to track the current targets.
827 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
828
[email protected]a93bb842010-02-16 23:03:47829 // Wrapper for glBindTexture since we need to track the current targets.
830 void DoBindTexture(GLenum target, GLuint texture);
831
[email protected]36cef8ce2010-03-16 07:34:45832 // Wrapper for glBufferData.
[email protected]0c86dbf2010-03-05 08:14:11833 void DoBufferData(
834 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage);
835
[email protected]36cef8ce2010-03-16 07:34:45836 // Wrapper for glBufferSubData.
[email protected]0c86dbf2010-03-05 08:14:11837 void DoBufferSubData(
838 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
839
[email protected]36cef8ce2010-03-16 07:34:45840 // Wrapper for glCheckFramebufferStatus
841 GLenum DoCheckFramebufferStatus(GLenum target);
842
[email protected]45bf5152010-02-12 00:11:31843 // Wrapper for glCompileShader.
844 void DoCompileShader(GLuint shader);
845
[email protected]066849e32010-05-03 19:14:10846 // Helper for DeleteSharedIds commands.
847 void DoDeleteSharedIds(GLuint namespace_id, GLsizei n, const GLuint* ids);
848
[email protected]ae51d192010-04-27 00:48:03849 // Wrapper for glDetachShader
850 void DoDetachShader(GLuint client_program_id, GLint client_shader_id);
851
[email protected]07f54fcc2009-12-22 02:46:30852 // Wrapper for glDrawArrays.
853 void DoDrawArrays(GLenum mode, GLint first, GLsizei count);
854
855 // Wrapper for glDisableVertexAttribArray.
856 void DoDisableVertexAttribArray(GLuint index);
857
858 // Wrapper for glEnableVertexAttribArray.
859 void DoEnableVertexAttribArray(GLuint index);
860
[email protected]36cef8ce2010-03-16 07:34:45861 // Wrapper for glFramebufferRenderbufffer.
862 void DoFramebufferRenderbuffer(
863 GLenum target, GLenum attachment, GLenum renderbuffertarget,
864 GLuint renderbuffer);
865
866 // Wrapper for glFramebufferTexture2D.
867 void DoFramebufferTexture2D(
868 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
869 GLint level);
870
[email protected]a93bb842010-02-16 23:03:47871 // Wrapper for glGenerateMipmap
872 void DoGenerateMipmap(GLenum target);
873
[email protected]066849e32010-05-03 19:14:10874 // Helper for GenSharedIds commands.
875 void DoGenSharedIds(
876 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids);
877
[email protected]b273e432010-04-12 17:23:58878 // Wrapper for DoGetBooleanv.
879 void DoGetBooleanv(GLenum pname, GLboolean* params);
880
881 // Wrapper for DoGetFloatv.
882 void DoGetFloatv(GLenum pname, GLfloat* params);
883
[email protected]36cef8ce2010-03-16 07:34:45884 // Wrapper for glGetFramebufferAttachmentParameteriv.
885 void DoGetFramebufferAttachmentParameteriv(
886 GLenum target, GLenum attachment, GLenum pname, GLint* params);
887
[email protected]a0c3e972010-04-21 00:49:13888 // Wrapper for glGetIntegerv.
[email protected]b273e432010-04-12 17:23:58889 void DoGetIntegerv(GLenum pname, GLint* params);
890
[email protected]29a9eb52010-04-13 09:04:23891 // Gets the max value in a range in a buffer.
892 GLuint DoGetMaxValueInBuffer(
893 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset);
894
[email protected]a0c3e972010-04-21 00:49:13895 // Wrapper for glGetProgramiv.
896 void DoGetProgramiv(
897 GLuint program_id, GLenum pname, GLint* params);
898
[email protected]36cef8ce2010-03-16 07:34:45899 // Wrapper for glRenderbufferParameteriv.
900 void DoGetRenderbufferParameteriv(
901 GLenum target, GLenum pname, GLint* params);
902
[email protected]ddd968b82010-03-02 00:44:29903 // Wrapper for glGetShaderiv
904 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
905
[email protected]b1122982010-05-17 23:04:24906 // Wrappers for glGetVertexAttrib.
907 void DoGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params);
908 void DoGetVertexAttribiv(GLuint index, GLenum pname, GLint *params);
909
[email protected]1958e0e2010-04-22 05:17:15910 // Wrappers for glIsXXX functions.
911 bool DoIsBuffer(GLuint client_id);
912 bool DoIsFramebuffer(GLuint client_id);
913 bool DoIsProgram(GLuint client_id);
914 bool DoIsRenderbuffer(GLuint client_id);
915 bool DoIsShader(GLuint client_id);
916 bool DoIsTexture(GLuint client_id);
917
[email protected]07f54fcc2009-12-22 02:46:30918 // Wrapper for glLinkProgram
919 void DoLinkProgram(GLuint program);
920
[email protected]066849e32010-05-03 19:14:10921 // Helper for RegisterSharedIds.
922 void DoRegisterSharedIds(GLuint namespace_id, GLsizei n, const GLuint* ids);
923
[email protected]36cef8ce2010-03-16 07:34:45924 // Wrapper for glRenderbufferStorage.
925 void DoRenderbufferStorage(
[email protected]ae51d192010-04-27 00:48:03926 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
[email protected]36cef8ce2010-03-16 07:34:45927
[email protected]b273e432010-04-12 17:23:58928 // Wrapper for glReleaseShaderCompiler.
929 void DoReleaseShaderCompiler() { }
930
[email protected]3916c97e2010-02-25 03:20:50931 // Wrappers for glTexParameter functions.
932 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
933 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
934 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
935 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
936
937 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
938 // spec only these 2 functions can be used to set sampler uniforms.
939 void DoUniform1i(GLint location, GLint v0);
[email protected]939e7362010-05-13 20:49:10940 void DoUniform1iv(GLint location, GLsizei count, const GLint* value);
941
942 // Wrappers for glUniformfv because some drivers don't correctly accept
943 // bool uniforms.
944 void DoUniform1fv(GLint location, GLsizei count, const GLfloat* value);
945 void DoUniform2fv(GLint location, GLsizei count, const GLfloat* value);
946 void DoUniform3fv(GLint location, GLsizei count, const GLfloat* value);
947 void DoUniform4fv(GLint location, GLsizei count, const GLfloat* value);
[email protected]3916c97e2010-02-25 03:20:50948
[email protected]b1122982010-05-17 23:04:24949 // Wrappers for glVertexAttrib??
950 void DoVertexAttrib1f(GLuint index, GLfloat v0);
951 void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
952 void DoVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
953 void DoVertexAttrib4f(
954 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
955 void DoVertexAttrib1fv(GLuint index, const GLfloat *v);
956 void DoVertexAttrib2fv(GLuint index, const GLfloat *v);
957 void DoVertexAttrib3fv(GLuint index, const GLfloat *v);
958 void DoVertexAttrib4fv(GLuint index, const GLfloat *v);
959
[email protected]07f54fcc2009-12-22 02:46:30960 // Wrapper for glUseProgram
961 void DoUseProgram(GLuint program);
962
[email protected]ae51d192010-04-27 00:48:03963 // Wrapper for glValidateProgram.
964 void DoValidateProgram(GLuint program_client_id);
965
[email protected]4e8a5b122010-05-08 22:00:10966 // Gets the number of values that will be returned by glGetXXX. Returns
967 // false if pname is unknown.
968 bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
969
[email protected]96449d2c2009-11-25 00:01:32970 // Gets the GLError through our wrapper.
971 GLenum GetGLError();
972
973 // Sets our wrapper for the GLError.
[email protected]8eee29c2010-04-29 03:38:29974 void SetGLError(GLenum error, const char* msg);
[email protected]96449d2c2009-11-25 00:01:32975
[email protected]07f54fcc2009-12-22 02:46:30976 // Copies the real GL errors to the wrapper. This is so we can
977 // make sure there are no native GL errors before calling some GL function
978 // so that on return we know any error generated was for that specific
979 // command.
980 void CopyRealGLErrorsToWrapper();
981
[email protected]6217d392010-03-25 22:08:35982 // Clear all real GL errors. This is to prevent the client from seeing any
983 // errors caused by GL calls that it was not responsible for issuing.
984 void ClearRealGLErrors();
985
[email protected]07f54fcc2009-12-22 02:46:30986 // Checks if the current program and vertex attributes are valid for drawing.
987 bool IsDrawValid(GLuint max_vertex_accessed);
988
[email protected]b1122982010-05-17 23:04:24989 // Returns true if attrib0 was simulated.
990 bool SimulateAttrib0(GLuint max_vertex_accessed);
991 void RestoreStateForSimulatedAttrib0();
992
[email protected]ef526492010-06-02 23:12:25993 // Returns true if textures were set.
994 bool SetBlackTextureForNonRenderableTextures();
[email protected]3916c97e2010-02-25 03:20:50995 void RestoreStateForNonRenderableTextures();
996
[email protected]07f54fcc2009-12-22 02:46:30997 // Gets the buffer id for a given target.
[email protected]3916c97e2010-02-25 03:20:50998 BufferManager::BufferInfo* GetBufferInfoForTarget(GLenum target) {
[email protected]07f54fcc2009-12-22 02:46:30999 DCHECK(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER);
[email protected]3916c97e2010-02-25 03:20:501000 BufferManager::BufferInfo* info = target == GL_ARRAY_BUFFER ?
1001 bound_array_buffer_ : bound_element_array_buffer_;
1002 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]07f54fcc2009-12-22 02:46:301003 }
1004
[email protected]a93bb842010-02-16 23:03:471005 // Gets the texture id for a given target.
[email protected]3916c97e2010-02-25 03:20:501006 TextureManager::TextureInfo* GetTextureInfoForTarget(GLenum target) {
1007 TextureUnit& unit = texture_units_[active_texture_unit_];
1008 TextureManager::TextureInfo* info = NULL;
[email protected]a93bb842010-02-16 23:03:471009 switch (target) {
1010 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:501011 info = unit.bound_texture_2d;
1012 break;
[email protected]a93bb842010-02-16 23:03:471013 case GL_TEXTURE_CUBE_MAP:
1014 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1015 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1016 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1017 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1018 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1019 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
[email protected]3916c97e2010-02-25 03:20:501020 info = unit.bound_texture_cube_map;
1021 break;
[email protected]1aef98132010-02-23 18:00:071022 // Note: If we ever support TEXTURE_RECTANGLE as a target, be sure to
1023 // track |texture_| with the currently bound TEXTURE_RECTANGLE texture,
1024 // because |texture_| is used by the FBO rendering mechanism for readback
1025 // to the bits that get sent to the browser.
[email protected]a93bb842010-02-16 23:03:471026 default:
1027 NOTREACHED();
[email protected]3916c97e2010-02-25 03:20:501028 return NULL;
[email protected]a93bb842010-02-16 23:03:471029 }
[email protected]3916c97e2010-02-25 03:20:501030 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]a93bb842010-02-16 23:03:471031 }
1032
[email protected]f7b85372010-02-03 01:11:371033 // Validates the program and location for a glGetUniform call and returns
1034 // a SizeResult setup to receive the result. Returns true if glGetUniform
1035 // should be called.
1036 bool GetUniformSetup(
1037 GLuint program, GLint location,
1038 uint32 shm_id, uint32 shm_offset,
[email protected]939e7362010-05-13 20:49:101039 error::Error* error, GLuint* service_id, void** result,
1040 GLenum* result_type);
[email protected]f7b85372010-02-03 01:11:371041
[email protected]86093972010-03-11 00:13:561042 bool ValidateGLenumCompressedTextureInternalFormat(GLenum format);
1043
[email protected]96449d2c2009-11-25 00:01:321044 // Generate a member function prototype for each command in an automated and
1045 // typesafe way.
1046 #define GLES2_CMD_OP(name) \
[email protected]f7a64ee2010-02-01 22:24:141047 Error Handle ## name( \
[email protected]b9849abf2009-11-25 19:13:191048 uint32 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:321049 const gles2::name& args); \
1050
1051 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1052
1053 #undef GLES2_CMD_OP
1054
[email protected]2f2d7042010-04-14 21:45:581055 // The GL context this decoder renders to on behalf of the client.
[email protected]5a6db6c2010-04-22 18:32:061056 gfx::GLContext* context_;
[email protected]d37231fa2010-04-09 21:16:021057
[email protected]2f2d7042010-04-14 21:45:581058 // A GLContext that is kept in its default state. It is used to perform
1059 // operations that should not be dependent on client set GLContext state, like
1060 // clearing a render buffer when it is created.
1061 // TODO(apatrick): Decoders in the same ContextGroup could potentially share
1062 // the same default GL context.
[email protected]5a6db6c2010-04-22 18:32:061063 scoped_ptr<gfx::GLContext> default_context_;
[email protected]2f2d7042010-04-14 21:45:581064
[email protected]6217d392010-03-25 22:08:351065 // A parent decoder can access this decoders saved offscreen frame buffer.
1066 // The parent pointer is reset if the parent is destroyed.
1067 base::WeakPtr<GLES2DecoderImpl> parent_;
1068
1069 // Width and height to which an offscreen frame buffer should be resized on
1070 // the next call to SwapBuffers.
[email protected]d37231fa2010-04-09 21:16:021071 gfx::Size pending_offscreen_size_;
[email protected]6217d392010-03-25 22:08:351072
[email protected]96449d2c2009-11-25 00:01:321073 // Current GL error bits.
1074 uint32 error_bits_;
1075
[email protected]96449d2c2009-11-25 00:01:321076 // Util to help with GL.
1077 GLES2Util util_;
1078
1079 // pack alignment as last set by glPixelStorei
1080 GLint pack_alignment_;
1081
1082 // unpack alignment as last set by glPixelStorei
1083 GLint unpack_alignment_;
1084
1085 // The currently bound array buffer. If this is 0 it is illegal to call
1086 // glVertexAttribPointer.
[email protected]3916c97e2010-02-25 03:20:501087 BufferManager::BufferInfo::Ref bound_array_buffer_;
[email protected]96449d2c2009-11-25 00:01:321088
1089 // The currently bound element array buffer. If this is 0 it is illegal
1090 // to call glDrawElements.
[email protected]3916c97e2010-02-25 03:20:501091 BufferManager::BufferInfo::Ref bound_element_array_buffer_;
[email protected]07f54fcc2009-12-22 02:46:301092
[email protected]f39f4b3f2010-05-12 17:04:081093 // Class that manages vertex attribs.
1094 VertexAttribManager vertex_attrib_manager_;
[email protected]07f54fcc2009-12-22 02:46:301095
[email protected]b1122982010-05-17 23:04:241096 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1097 GLuint attrib_0_buffer_id_;
1098
1099 // The value currently in attrib_0.
1100 VertexAttribManager::VertexAttribInfo::Vec4 attrib_0_value_;
1101
1102 // The size of attrib 0.
1103 GLsizei attrib_0_size_;
1104
[email protected]3916c97e2010-02-25 03:20:501105 // Current active texture by 0 - n index.
1106 // In other words, if we call glActiveTexture(GL_TEXTURE2) this value would
1107 // be 2.
1108 GLuint active_texture_unit_;
[email protected]07f54fcc2009-12-22 02:46:301109
[email protected]3916c97e2010-02-25 03:20:501110 // Which textures are bound to texture units through glActiveTexture.
1111 scoped_array<TextureUnit> texture_units_;
[email protected]a93bb842010-02-16 23:03:471112
[email protected]cd6cd4762010-06-01 23:07:211113 // Black (0,0,0,1) textures for when non-renderable textures are used.
[email protected]3916c97e2010-02-25 03:20:501114 // NOTE: There is no corresponding TextureInfo for these textures.
1115 // TextureInfos are only for textures the client side can access.
1116 GLuint black_2d_texture_id_;
1117 GLuint black_cube_texture_id_;
[email protected]45bf5152010-02-12 00:11:311118
[email protected]1d32bc82010-01-13 22:06:461119 // The program in use by glUseProgram
[email protected]3916c97e2010-02-25 03:20:501120 ProgramManager::ProgramInfo::Ref current_program_;
[email protected]07f54fcc2009-12-22 02:46:301121
[email protected]86093972010-03-11 00:13:561122 // The currently bound framebuffer
[email protected]051b1372010-04-12 02:42:081123 FramebufferManager::FramebufferInfo::Ref bound_framebuffer_;
[email protected]86093972010-03-11 00:13:561124
1125 // The currently bound renderbuffer
[email protected]051b1372010-04-12 02:42:081126 RenderbufferManager::RenderbufferInfo::Ref bound_renderbuffer_;
[email protected]86093972010-03-11 00:13:561127
[email protected]96449d2c2009-11-25 00:01:321128 bool anti_aliased_;
1129
[email protected]6217d392010-03-25 22:08:351130 // The offscreen frame buffer that the client renders to.
1131 scoped_ptr<FrameBuffer> offscreen_target_frame_buffer_;
1132 scoped_ptr<Texture> offscreen_target_color_texture_;
1133 scoped_ptr<RenderBuffer> offscreen_target_depth_stencil_render_buffer_;
1134
1135 // The copy that is saved when SwapBuffers is called.
1136 scoped_ptr<Texture> offscreen_saved_color_texture_;
1137
[email protected]43f28f832010-02-03 02:28:481138 scoped_ptr<Callback0::Type> swap_buffers_callback_;
1139
[email protected]8eee29c2010-04-29 03:38:291140 // The last error message set.
1141 std::string last_error_;
1142
[email protected]b1d2dcb2010-05-17 19:24:181143 bool use_shader_translator_;
1144
[email protected]96449d2c2009-11-25 00:01:321145 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
1146};
1147
[email protected]6217d392010-03-25 22:08:351148ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(GLES2DecoderImpl* decoder)
1149 : decoder_(decoder) {
1150 decoder_->CopyRealGLErrorsToWrapper();
1151}
1152
1153ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
1154 decoder_->ClearRealGLErrors();
1155}
1156
1157ScopedTexture2DBinder::ScopedTexture2DBinder(GLES2DecoderImpl* decoder,
1158 GLuint id)
1159 : decoder_(decoder) {
1160 ScopedGLErrorSuppressor suppressor(decoder_);
1161
1162 // TODO(apatrick): Check if there are any other states that need to be reset
1163 // before binding a new texture.
1164 glActiveTexture(GL_TEXTURE0);
1165 glBindTexture(GL_TEXTURE_2D, id);
1166}
1167
1168ScopedTexture2DBinder::~ScopedTexture2DBinder() {
1169 ScopedGLErrorSuppressor suppressor(decoder_);
1170 GLES2DecoderImpl::TextureUnit& info = decoder_->texture_units_[0];
1171 GLuint last_id;
1172 if (info.bound_texture_2d)
[email protected]ae51d192010-04-27 00:48:031173 last_id = info.bound_texture_2d->service_id();
[email protected]6217d392010-03-25 22:08:351174 else
1175 last_id = 0;
1176
1177 glBindTexture(GL_TEXTURE_2D, last_id);
1178 glActiveTexture(GL_TEXTURE0 + decoder_->active_texture_unit_);
1179}
1180
1181ScopedRenderBufferBinder::ScopedRenderBufferBinder(GLES2DecoderImpl* decoder,
1182 GLuint id)
1183 : decoder_(decoder) {
1184 ScopedGLErrorSuppressor suppressor(decoder_);
1185 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
1186}
1187
1188ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
1189 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]051b1372010-04-12 02:42:081190 glBindRenderbufferEXT(
1191 GL_RENDERBUFFER,
1192 decoder_->bound_renderbuffer_ ?
[email protected]ae51d192010-04-27 00:48:031193 decoder_->bound_renderbuffer_->service_id() : 0);
[email protected]6217d392010-03-25 22:08:351194}
1195
1196ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
1197 GLuint id)
1198 : decoder_(decoder) {
1199 ScopedGLErrorSuppressor suppressor(decoder_);
1200 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
1201}
1202
1203ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
1204 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]051b1372010-04-12 02:42:081205 FramebufferManager::FramebufferInfo* info =
1206 decoder_->bound_framebuffer_.get();
[email protected]ae51d192010-04-27 00:48:031207 GLuint framebuffer_id = info ? info->service_id() : 0;
[email protected]051b1372010-04-12 02:42:081208 if (framebuffer_id == 0 &&
[email protected]6217d392010-03-25 22:08:351209 decoder_->offscreen_target_frame_buffer_.get()) {
1210 glBindFramebufferEXT(GL_FRAMEBUFFER,
1211 decoder_->offscreen_target_frame_buffer_->id());
1212 } else {
[email protected]051b1372010-04-12 02:42:081213 glBindFramebufferEXT(GL_FRAMEBUFFER, framebuffer_id);
[email protected]6217d392010-03-25 22:08:351214 }
1215}
1216
[email protected]2f2d7042010-04-14 21:45:581217ScopedDefaultGLContext::ScopedDefaultGLContext(GLES2DecoderImpl* decoder)
1218 : decoder_(decoder) {
1219 decoder_->default_context_->MakeCurrent();
1220}
1221
1222ScopedDefaultGLContext::~ScopedDefaultGLContext() {
1223 decoder_->context_->MakeCurrent();
1224}
1225
[email protected]6217d392010-03-25 22:08:351226Texture::Texture(GLES2DecoderImpl* decoder)
1227 : decoder_(decoder),
1228 id_(0) {
1229}
1230
1231Texture::~Texture() {
1232 // This does not destroy the render texture because that would require that
1233 // the associated GL context was current. Just check that it was explicitly
1234 // destroyed.
1235 DCHECK_EQ(id_, 0u);
1236}
1237
1238void Texture::Create() {
1239 ScopedGLErrorSuppressor suppressor(decoder_);
1240 Destroy();
1241 glGenTextures(1, &id_);
1242}
1243
1244bool Texture::AllocateStorage(const gfx::Size& size) {
1245 DCHECK_NE(id_, 0u);
1246 ScopedGLErrorSuppressor suppressor(decoder_);
1247 ScopedTexture2DBinder binder(decoder_, id_);
1248 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1249 glTexParameteri(
1250 GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1251 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1252 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1253 glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
1254
1255 glTexImage2D(GL_TEXTURE_2D,
1256 0, // mip level
1257 GL_RGBA,
1258 size.width(),
1259 size.height(),
1260 0, // border
1261 GL_RGBA,
1262 GL_UNSIGNED_BYTE,
1263 NULL);
1264
[email protected]d37231fa2010-04-09 21:16:021265 size_ = size;
1266
[email protected]6217d392010-03-25 22:08:351267 return glGetError() == GL_NO_ERROR;
1268}
1269
1270void Texture::Copy(const gfx::Size& size) {
1271 DCHECK_NE(id_, 0u);
1272 ScopedGLErrorSuppressor suppressor(decoder_);
1273 ScopedTexture2DBinder binder(decoder_, id_);
1274 glCopyTexImage2D(GL_TEXTURE_2D,
1275 0, // level
1276 GL_RGBA,
1277 0, 0,
1278 size.width(),
1279 size.height(),
1280 0); // border
1281}
1282
1283void Texture::Destroy() {
1284 if (id_ != 0) {
1285 ScopedGLErrorSuppressor suppressor(decoder_);
1286 glDeleteTextures(1, &id_);
1287 id_ = 0;
1288 }
1289}
1290
1291RenderBuffer::RenderBuffer(GLES2DecoderImpl* decoder)
1292 : decoder_(decoder),
1293 id_(0) {
1294}
1295
1296RenderBuffer::~RenderBuffer() {
1297 // This does not destroy the render buffer because that would require that
1298 // the associated GL context was current. Just check that it was explicitly
1299 // destroyed.
1300 DCHECK_EQ(id_, 0u);
1301}
1302
1303void RenderBuffer::Create() {
1304 ScopedGLErrorSuppressor suppressor(decoder_);
1305 Destroy();
1306 glGenRenderbuffersEXT(1, &id_);
1307}
1308
1309bool RenderBuffer::AllocateStorage(const gfx::Size& size, GLenum format) {
1310 ScopedGLErrorSuppressor suppressor(decoder_);
1311 ScopedRenderBufferBinder binder(decoder_, id_);
1312 glRenderbufferStorageEXT(GL_RENDERBUFFER,
1313 format,
1314 size.width(),
1315 size.height());
1316 return glGetError() == GL_NO_ERROR;
1317}
1318
1319void RenderBuffer::Destroy() {
1320 if (id_ != 0) {
1321 ScopedGLErrorSuppressor suppressor(decoder_);
1322 glDeleteRenderbuffersEXT(1, &id_);
1323 id_ = 0;
1324 }
1325}
1326
1327FrameBuffer::FrameBuffer(GLES2DecoderImpl* decoder)
1328 : decoder_(decoder),
1329 id_(0) {
1330}
1331
1332FrameBuffer::~FrameBuffer() {
1333 // This does not destroy the frame buffer because that would require that
1334 // the associated GL context was current. Just check that it was explicitly
1335 // destroyed.
1336 DCHECK_EQ(id_, 0u);
1337}
1338
1339void FrameBuffer::Create() {
1340 ScopedGLErrorSuppressor suppressor(decoder_);
1341 Destroy();
1342 glGenFramebuffersEXT(1, &id_);
1343}
1344
1345void FrameBuffer::AttachRenderTexture(Texture* texture) {
1346 DCHECK_NE(id_, 0u);
1347 ScopedGLErrorSuppressor suppressor(decoder_);
1348 ScopedFrameBufferBinder binder(decoder_, id_);
1349 GLuint attach_id = texture ? texture->id() : 0;
1350 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
1351 GL_COLOR_ATTACHMENT0,
1352 GL_TEXTURE_2D,
1353 attach_id,
1354 0);
1355}
1356
1357void FrameBuffer::AttachDepthStencilRenderBuffer(RenderBuffer* render_buffer) {
1358 DCHECK_NE(id_, 0u);
1359 ScopedGLErrorSuppressor suppressor(decoder_);
1360 ScopedFrameBufferBinder binder(decoder_, id_);
1361 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
1362 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
1363 GL_DEPTH_ATTACHMENT,
1364 GL_RENDERBUFFER,
1365 attach_id);
1366 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
1367 GL_STENCIL_ATTACHMENT,
1368 GL_RENDERBUFFER,
1369 attach_id);
1370}
1371
1372void FrameBuffer::Clear(GLbitfield buffers) {
1373 ScopedGLErrorSuppressor suppressor(decoder_);
1374 ScopedFrameBufferBinder binder(decoder_, id_);
1375 glClear(buffers);
1376}
1377
1378void FrameBuffer::Destroy() {
1379 if (id_ != 0) {
1380 ScopedGLErrorSuppressor suppressor(decoder_);
1381 glDeleteFramebuffersEXT(1, &id_);
1382 id_ = 0;
1383 }
1384}
1385
1386GLenum FrameBuffer::CheckStatus() {
1387 DCHECK_NE(id_, 0u);
1388 ScopedGLErrorSuppressor suppressor(decoder_);
1389 ScopedFrameBufferBinder binder(decoder_, id_);
1390 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
1391}
1392
[email protected]3916c97e2010-02-25 03:20:501393GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
1394 return new GLES2DecoderImpl(group);
[email protected]96449d2c2009-11-25 00:01:321395}
1396
[email protected]3916c97e2010-02-25 03:20:501397GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
1398 : GLES2Decoder(group),
[email protected]d37231fa2010-04-09 21:16:021399 context_(NULL),
[email protected]96449d2c2009-11-25 00:01:321400 error_bits_(0),
1401 util_(0), // TODO(gman): Set to actual num compress texture formats.
1402 pack_alignment_(4),
1403 unpack_alignment_(4),
[email protected]b1122982010-05-17 23:04:241404 attrib_0_buffer_id_(0),
1405 attrib_0_size_(0),
[email protected]3916c97e2010-02-25 03:20:501406 active_texture_unit_(0),
1407 black_2d_texture_id_(0),
1408 black_cube_texture_id_(0),
[email protected]b1d2dcb2010-05-17 19:24:181409 anti_aliased_(false),
1410 use_shader_translator_(true) {
[email protected]b1122982010-05-17 23:04:241411 attrib_0_value_.v[0] = 0.0f;
1412 attrib_0_value_.v[1] = 0.0f;
1413 attrib_0_value_.v[2] = 0.0f;
1414 attrib_0_value_.v[3] = 1.0f;
[email protected]96449d2c2009-11-25 00:01:321415}
1416
[email protected]5a6db6c2010-04-22 18:32:061417bool GLES2DecoderImpl::Initialize(gfx::GLContext* context,
[email protected]6217d392010-03-25 22:08:351418 const gfx::Size& size,
[email protected]d37231fa2010-04-09 21:16:021419 GLES2Decoder* parent,
[email protected]6217d392010-03-25 22:08:351420 uint32 parent_client_texture_id) {
[email protected]4bedba72010-04-20 22:08:541421 DCHECK(context);
[email protected]d37231fa2010-04-09 21:16:021422 DCHECK(!context_);
1423 context_ = context;
1424
[email protected]2f2d7042010-04-14 21:45:581425 // Create a GL context that is kept in a default state and shares a namespace
1426 // with the main GL context.
[email protected]5a6db6c2010-04-22 18:32:061427 default_context_.reset(gfx::GLContext::CreateOffscreenGLContext(
[email protected]4bedba72010-04-20 22:08:541428 context_->GetHandle()));
1429 if (!default_context_.get()) {
[email protected]2f2d7042010-04-14 21:45:581430 Destroy();
1431 return false;
1432 }
1433
[email protected]6217d392010-03-25 22:08:351434 // Keep only a weak pointer to the parent so we don't unmap its client
[email protected]d37231fa2010-04-09 21:16:021435 // frame buffer after it has been destroyed.
[email protected]6217d392010-03-25 22:08:351436 if (parent)
1437 parent_ = static_cast<GLES2DecoderImpl*>(parent)->AsWeakPtr();
1438
[email protected]246a70452010-03-05 21:53:501439 if (!MakeCurrent()) {
1440 Destroy();
1441 return false;
[email protected]eb54a562010-01-20 21:55:181442 }
1443
[email protected]246a70452010-03-05 21:53:501444 CHECK_GL_ERROR();
1445
1446 if (!group_->Initialize()) {
1447 Destroy();
1448 return false;
1449 }
1450
[email protected]f39f4b3f2010-05-12 17:04:081451 vertex_attrib_manager_.Initialize(group_->max_vertex_attribs());
[email protected]b1122982010-05-17 23:04:241452 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
1453 // OpenGL ES 2.0 does not have this issue.
1454 glEnableVertexAttribArray(0);
1455 glGenBuffersARB(1, &attrib_0_buffer_id_);
1456 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
1457 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
1458 glBindBuffer(GL_ARRAY_BUFFER, 0);
[email protected]f39f4b3f2010-05-12 17:04:081459
[email protected]246a70452010-03-05 21:53:501460 texture_units_.reset(
1461 new TextureUnit[group_->max_texture_units()]);
[email protected]1958e0e2010-04-22 05:17:151462 for (uint32 tt = 0; tt < group_->max_texture_units(); ++tt) {
1463 texture_units_[tt].bound_texture_2d =
1464 texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
1465 texture_units_[tt].bound_texture_cube_map =
1466 texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
1467 }
[email protected]4e8a5b122010-05-08 22:00:101468
[email protected]246a70452010-03-05 21:53:501469 GLuint ids[2];
1470 glGenTextures(2, ids);
1471 // Make black textures for replacing non-renderable textures.
1472 black_2d_texture_id_ = ids[0];
1473 black_cube_texture_id_ = ids[1];
[email protected]cd6cd4762010-06-01 23:07:211474 static uint8 black[] = {0, 0, 0, 255};
[email protected]246a70452010-03-05 21:53:501475 glBindTexture(GL_TEXTURE_2D, black_2d_texture_id_);
1476 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA,
1477 GL_UNSIGNED_BYTE, black);
1478 glBindTexture(GL_TEXTURE_2D, 0);
1479 glBindTexture(GL_TEXTURE_CUBE_MAP, black_cube_texture_id_);
[email protected]1958e0e2010-04-22 05:17:151480 for (int ii = 0; ii < GLES2Util::kNumFaces; ++ii) {
1481 glTexImage2D(GLES2Util::IndexToGLFaceTarget(ii), 0, GL_RGBA, 1, 1, 0,
1482 GL_RGBA, GL_UNSIGNED_BYTE, black);
[email protected]246a70452010-03-05 21:53:501483 }
1484 glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
1485 CHECK_GL_ERROR();
1486
[email protected]d37231fa2010-04-09 21:16:021487#if !defined(UNIT_TEST)
1488 if (context_->IsOffscreen()) {
[email protected]6217d392010-03-25 22:08:351489 // Create the target frame buffer. This is the one that the client renders
1490 // directly to.
1491 offscreen_target_frame_buffer_.reset(new FrameBuffer(this));
1492 offscreen_target_frame_buffer_->Create();
1493 offscreen_target_color_texture_.reset(new Texture(this));
1494 offscreen_target_color_texture_->Create();
1495 offscreen_target_depth_stencil_render_buffer_.reset(
1496 new RenderBuffer(this));
1497 offscreen_target_depth_stencil_render_buffer_->Create();
1498
1499 // Create the saved offscreen texture. The target frame buffer is copied
1500 // here when SwapBuffers is called.
1501 offscreen_saved_color_texture_.reset(new Texture(this));
1502 offscreen_saved_color_texture_->Create();
1503
[email protected]6217d392010-03-25 22:08:351504 // Map the ID of the saved offscreen texture into the parent so that
1505 // it can reference it.
1506 if (parent_) {
1507 GLuint service_id = offscreen_saved_color_texture_->id();
[email protected]6217d392010-03-25 22:08:351508 TextureManager::TextureInfo* info =
[email protected]ae51d192010-04-27 00:48:031509 parent_->CreateTextureInfo(parent_client_texture_id, service_id);
[email protected]6217d392010-03-25 22:08:351510 parent_->texture_manager()->SetInfoTarget(info, GL_TEXTURE_2D);
1511 }
1512
1513 // Allocate the render buffers at their initial size and check the status
1514 // of the frame buffers is okay.
[email protected]d37231fa2010-04-09 21:16:021515 pending_offscreen_size_ = size;
[email protected]6217d392010-03-25 22:08:351516 if (!UpdateOffscreenFrameBufferSize()) {
1517 DLOG(ERROR) << "Could not allocate offscreen buffer storage.";
1518 Destroy();
1519 return false;
1520 }
1521
1522 // Bind to the new default frame buffer (the offscreen target frame buffer).
1523 // This should now be associated with ID zero.
1524 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
1525 }
[email protected]d37231fa2010-04-09 21:16:021526#endif // UNIT_TEST
[email protected]6217d392010-03-25 22:08:351527
[email protected]76a0ee102010-04-07 21:03:041528#if !defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
1529 // OpenGL ES 2.0 implicitly enables the desktop GL capability
1530 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
1531 // isn't well documented; it was discovered in the Khronos OpenGL ES
1532 // mailing list archives.
1533 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
[email protected]de17df392010-04-23 21:09:411534
[email protected]bc10076c2010-05-14 19:14:061535#if defined(GLES2_GPU_SERVICE_TRANSLATE_SHADER) && !defined(UNIT_TEST)
[email protected]de17df392010-04-23 21:09:411536 // Initialize GLSL ES to GLSL translator.
1537 if (!ShInitialize()) {
1538 DLOG(ERROR) << "Could not initialize GLSL translator.";
1539 Destroy();
1540 return false;
1541 }
1542#endif // GLES2_GPU_SERVICE_TRANSLATE_SHADER
1543#endif // GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2
[email protected]76a0ee102010-04-07 21:03:041544
[email protected]246a70452010-03-05 21:53:501545 return true;
[email protected]96449d2c2009-11-25 00:01:321546}
1547
[email protected]ae51d192010-04-27 00:48:031548bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
[email protected]a93bb842010-02-16 23:03:471549 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:031550 if (GetBufferInfo(client_ids[ii])) {
1551 return false;
1552 }
1553 }
1554 scoped_array<GLuint> service_ids(new GLuint[n]);
1555 glGenBuffersARB(n, service_ids.get());
1556 for (GLsizei ii = 0; ii < n; ++ii) {
1557 CreateBufferInfo(client_ids[ii], service_ids[ii]);
1558 }
1559 return true;
1560}
1561
1562bool GLES2DecoderImpl::GenFramebuffersHelper(
1563 GLsizei n, const GLuint* client_ids) {
1564 for (GLsizei ii = 0; ii < n; ++ii) {
1565 if (GetFramebufferInfo(client_ids[ii])) {
1566 return false;
1567 }
1568 }
1569 scoped_array<GLuint> service_ids(new GLuint[n]);
1570 glGenFramebuffersEXT(n, service_ids.get());
1571 for (GLsizei ii = 0; ii < n; ++ii) {
1572 CreateFramebufferInfo(client_ids[ii], service_ids[ii]);
1573 }
1574 return true;
1575}
1576
1577bool GLES2DecoderImpl::GenRenderbuffersHelper(
1578 GLsizei n, const GLuint* client_ids) {
1579 for (GLsizei ii = 0; ii < n; ++ii) {
1580 if (GetRenderbufferInfo(client_ids[ii])) {
1581 return false;
1582 }
1583 }
1584 scoped_array<GLuint> service_ids(new GLuint[n]);
1585 glGenRenderbuffersEXT(n, service_ids.get());
1586 for (GLsizei ii = 0; ii < n; ++ii) {
1587 CreateRenderbufferInfo(client_ids[ii], service_ids[ii]);
1588 }
1589 return true;
1590}
1591
1592bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
1593 for (GLsizei ii = 0; ii < n; ++ii) {
1594 if (GetTextureInfo(client_ids[ii])) {
1595 return false;
1596 }
1597 }
1598 scoped_array<GLuint> service_ids(new GLuint[n]);
1599 glGenTextures(n, service_ids.get());
1600 for (GLsizei ii = 0; ii < n; ++ii) {
1601 CreateTextureInfo(client_ids[ii], service_ids[ii]);
1602 }
1603 return true;
1604}
1605
1606void GLES2DecoderImpl::DeleteBuffersHelper(
1607 GLsizei n, const GLuint* client_ids) {
1608 for (GLsizei ii = 0; ii < n; ++ii) {
1609 BufferManager::BufferInfo* info = GetBufferInfo(client_ids[ii]);
1610 if (info) {
1611 GLuint service_id = info->service_id();
1612 glDeleteBuffersARB(1, &service_id);
1613 RemoveBufferInfo(client_ids[ii]);
1614 }
[email protected]a93bb842010-02-16 23:03:471615 }
[email protected]07f54fcc2009-12-22 02:46:301616}
1617
[email protected]ae51d192010-04-27 00:48:031618void GLES2DecoderImpl::DeleteFramebuffersHelper(
1619 GLsizei n, const GLuint* client_ids) {
[email protected]a25fa872010-03-25 02:57:581620 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:031621 FramebufferManager::FramebufferInfo* info =
1622 GetFramebufferInfo(client_ids[ii]);
1623 if (info) {
1624 GLuint service_id = info->service_id();
1625 glDeleteFramebuffersEXT(1, &service_id);
1626 RemoveFramebufferInfo(client_ids[ii]);
1627 }
[email protected]a25fa872010-03-25 02:57:581628 }
[email protected]07f54fcc2009-12-22 02:46:301629}
1630
[email protected]ae51d192010-04-27 00:48:031631void GLES2DecoderImpl::DeleteRenderbuffersHelper(
1632 GLsizei n, const GLuint* client_ids) {
[email protected]a25fa872010-03-25 02:57:581633 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:031634 RenderbufferManager::RenderbufferInfo* info =
1635 GetRenderbufferInfo(client_ids[ii]);
1636 if (info) {
1637 GLuint service_id = info->service_id();
1638 glDeleteRenderbuffersEXT(1, &service_id);
1639 RemoveRenderbufferInfo(client_ids[ii]);
1640 }
[email protected]a25fa872010-03-25 02:57:581641 }
[email protected]07f54fcc2009-12-22 02:46:301642}
1643
[email protected]ae51d192010-04-27 00:48:031644void GLES2DecoderImpl::DeleteTexturesHelper(
1645 GLsizei n, const GLuint* client_ids) {
[email protected]a93bb842010-02-16 23:03:471646 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:031647 TextureManager::TextureInfo* info = GetTextureInfo(client_ids[ii]);
1648 if (info) {
1649 GLuint service_id = info->service_id();
1650 glDeleteTextures(1, &service_id);
1651 RemoveTextureInfo(client_ids[ii]);
1652 }
[email protected]a93bb842010-02-16 23:03:471653 }
[email protected]07f54fcc2009-12-22 02:46:301654}
1655
[email protected]43f28f832010-02-03 02:28:481656// } // anonymous namespace
[email protected]96449d2c2009-11-25 00:01:321657
[email protected]eb54a562010-01-20 21:55:181658bool GLES2DecoderImpl::MakeCurrent() {
1659#if defined(UNIT_TEST)
1660 return true;
[email protected]eb54a562010-01-20 21:55:181661#else
[email protected]d37231fa2010-04-09 21:16:021662 return context_->MakeCurrent();
[email protected]eb54a562010-01-20 21:55:181663#endif
1664}
1665
[email protected]d37231fa2010-04-09 21:16:021666gfx::Size GLES2DecoderImpl::GetBoundFrameBufferSize() {
1667 if (bound_framebuffer_ != 0) {
1668 int width = 0;
1669 int height = 0;
[email protected]246a70452010-03-05 21:53:501670
[email protected]d37231fa2010-04-09 21:16:021671 // Assume we have to have COLOR_ATTACHMENT0. Should we check for depth and
1672 // stencil.
1673 GLint fb_type = 0;
1674 glGetFramebufferAttachmentParameterivEXT(
1675 GL_FRAMEBUFFER,
1676 GL_COLOR_ATTACHMENT0,
1677 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE,
1678 &fb_type);
1679 switch (fb_type) {
1680 case GL_RENDERBUFFER:
1681 {
1682 GLint renderbuffer_id = 0;
1683 glGetFramebufferAttachmentParameterivEXT(
1684 GL_FRAMEBUFFER,
1685 GL_COLOR_ATTACHMENT0,
1686 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
1687 &renderbuffer_id);
1688 if (renderbuffer_id != 0) {
1689 glGetRenderbufferParameterivEXT(
1690 GL_RENDERBUFFER,
1691 GL_RENDERBUFFER_WIDTH,
1692 &width);
1693 glGetRenderbufferParameterivEXT(
1694 GL_RENDERBUFFER,
1695 GL_RENDERBUFFER_HEIGHT,
1696 &height);
1697 }
1698 break;
1699 }
1700 case GL_TEXTURE:
1701 {
1702 GLint texture_id = 0;
1703 glGetFramebufferAttachmentParameterivEXT(
1704 GL_FRAMEBUFFER,
1705 GL_COLOR_ATTACHMENT0,
1706 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
1707 &texture_id);
1708 if (texture_id != 0) {
[email protected]ae51d192010-04-27 00:48:031709 GLuint client_id = 0;
1710 if (texture_manager()->GetClientId(texture_id, &client_id)) {
1711 TextureManager::TextureInfo* texture_info =
1712 GetTextureInfo(client_id);
1713 if (texture_info) {
1714 GLint level = 0;
1715 GLint face = 0;
1716 glGetFramebufferAttachmentParameterivEXT(
1717 GL_FRAMEBUFFER,
1718 GL_COLOR_ATTACHMENT0,
1719 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL,
1720 &level);
1721 glGetFramebufferAttachmentParameterivEXT(
1722 GL_FRAMEBUFFER,
1723 GL_COLOR_ATTACHMENT0,
1724 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE,
1725 &face);
1726 texture_info->GetLevelSize(
1727 face ? face : GL_TEXTURE_2D, level, &width, &height);
1728 }
[email protected]d37231fa2010-04-09 21:16:021729 }
1730 }
1731 break;
1732 }
1733 default:
1734 // unknown so assume width and height are zero.
1735 break;
[email protected]246a70452010-03-05 21:53:501736 }
1737
[email protected]d37231fa2010-04-09 21:16:021738 return gfx::Size(width, height);
1739 } else if (offscreen_target_color_texture_.get()) {
1740 return offscreen_target_color_texture_->size();
[email protected]6217d392010-03-25 22:08:351741 } else {
[email protected]246a70452010-03-05 21:53:501742#if defined(UNIT_TEST)
[email protected]d37231fa2010-04-09 21:16:021743 return gfx::Size(INT_MAX, INT_MAX);
1744#else
1745 return context_->GetSize();
[email protected]246a70452010-03-05 21:53:501746#endif
[email protected]d37231fa2010-04-09 21:16:021747 }
[email protected]246a70452010-03-05 21:53:501748}
1749
[email protected]6217d392010-03-25 22:08:351750bool GLES2DecoderImpl::UpdateOffscreenFrameBufferSize() {
[email protected]d37231fa2010-04-09 21:16:021751 if (offscreen_target_color_texture_->size() == pending_offscreen_size_)
[email protected]6217d392010-03-25 22:08:351752 return true;
1753
[email protected]2f2d7042010-04-14 21:45:581754 if (parent_) {
1755 // Create the saved offscreen color texture (only accessible to parent).
1756 offscreen_saved_color_texture_->AllocateStorage(pending_offscreen_size_);
1757
1758 // Attach the saved offscreen color texture to a frame buffer so we can
1759 // clear it with glClear.
1760 offscreen_target_frame_buffer_->AttachRenderTexture(
1761 offscreen_saved_color_texture_.get());
1762 if (offscreen_target_frame_buffer_->CheckStatus() !=
1763 GL_FRAMEBUFFER_COMPLETE) {
1764 return false;
1765 }
1766
1767#if !defined(UNIT_TEST)
1768 // Clear the saved offscreen color texture. Use default GL context
1769 // to ensure clear is not affected by client set state.
[email protected]1958e0e2010-04-22 05:17:151770 { // NOLINT
[email protected]2f2d7042010-04-14 21:45:581771 ScopedDefaultGLContext scoped_context(this);
1772 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,
1773 offscreen_target_frame_buffer_->id());
1774 glClear(GL_COLOR_BUFFER_BIT);
1775 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1776
1777 if (glGetError() != GL_NO_ERROR)
1778 return false;
1779 }
1780#endif
1781 }
1782
[email protected]6217d392010-03-25 22:08:351783 // Reallocate the offscreen target buffers.
[email protected]d37231fa2010-04-09 21:16:021784 if (!offscreen_target_color_texture_->AllocateStorage(
1785 pending_offscreen_size_)) {
[email protected]6217d392010-03-25 22:08:351786 return false;
1787 }
1788
1789 if (!offscreen_target_depth_stencil_render_buffer_->AllocateStorage(
[email protected]d37231fa2010-04-09 21:16:021790 pending_offscreen_size_, GL_DEPTH24_STENCIL8)) {
[email protected]6217d392010-03-25 22:08:351791 return false;
1792 }
1793
[email protected]2f2d7042010-04-14 21:45:581794 // Attach the offscreen target buffers to the target frame buffer.
[email protected]6217d392010-03-25 22:08:351795 offscreen_target_frame_buffer_->AttachRenderTexture(
1796 offscreen_target_color_texture_.get());
1797 offscreen_target_frame_buffer_->AttachDepthStencilRenderBuffer(
1798 offscreen_target_depth_stencil_render_buffer_.get());
1799 if (offscreen_target_frame_buffer_->CheckStatus() !=
1800 GL_FRAMEBUFFER_COMPLETE) {
1801 return false;
1802 }
1803
[email protected]2f2d7042010-04-14 21:45:581804#if !defined(UNIT_TEST)
1805 // Clear offscreen frame buffer to its initial state. Use default GL context
1806 // to ensure clear is not affected by client set state.
[email protected]1958e0e2010-04-22 05:17:151807 { // NOLINT
[email protected]2f2d7042010-04-14 21:45:581808 ScopedDefaultGLContext scoped_context(this);
1809 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,
1810 offscreen_target_frame_buffer_->id());
1811 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1812 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1813
1814 if (glGetError() != GL_NO_ERROR)
1815 return false;
1816 }
1817#endif
1818
[email protected]6217d392010-03-25 22:08:351819 if (parent_) {
[email protected]d37231fa2010-04-09 21:16:021820 // Create the saved offscreen color texture (only accessible to parent).
1821 offscreen_saved_color_texture_->AllocateStorage(pending_offscreen_size_);
1822
[email protected]2f2d7042010-04-14 21:45:581823 // Update the info about the offscreen saved color texture in the parent.
1824 // The reference to the parent is a weak pointer and will become null if the
1825 // parent is later destroyed.
[email protected]6217d392010-03-25 22:08:351826 GLuint service_id = offscreen_saved_color_texture_->id();
1827
1828 TextureManager::TextureInfo* info =
1829 parent_->texture_manager()->GetTextureInfo(service_id);
1830 DCHECK(info);
1831
[email protected]ef526492010-06-02 23:12:251832 texture_manager()->SetLevelInfo(
1833 info,
1834 GL_TEXTURE_2D,
1835 0, // level
1836 GL_RGBA,
1837 pending_offscreen_size_.width(),
1838 pending_offscreen_size_.height(),
1839 1, // depth
1840 0, // border
1841 GL_RGBA,
1842 GL_UNSIGNED_BYTE);
[email protected]6217d392010-03-25 22:08:351843 }
1844
[email protected]6217d392010-03-25 22:08:351845 return true;
1846}
1847
[email protected]43f28f832010-02-03 02:28:481848void GLES2DecoderImpl::SetSwapBuffersCallback(Callback0::Type* callback) {
1849 swap_buffers_callback_.reset(callback);
1850}
1851
[email protected]96449d2c2009-11-25 00:01:321852void GLES2DecoderImpl::Destroy() {
[email protected]4bedba72010-04-20 22:08:541853 if (context_) {
1854 MakeCurrent();
[email protected]6217d392010-03-25 22:08:351855
[email protected]b1122982010-05-17 23:04:241856 if (black_2d_texture_id_) {
1857 glDeleteTextures(1, &black_2d_texture_id_);
1858 }
1859 if (black_cube_texture_id_) {
1860 glDeleteTextures(1, &black_cube_texture_id_);
1861 }
1862 if (attrib_0_buffer_id_) {
1863 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
1864 }
1865
[email protected]4bedba72010-04-20 22:08:541866 // Remove the saved frame buffer mapping from the parent decoder. The
1867 // parent pointer is a weak pointer so it will be null if the parent has
1868 // already been destroyed.
1869 if (parent_) {
1870 // First check the texture has been mapped into the parent. This might not
1871 // be the case if initialization failed midway through.
1872 GLuint service_id = offscreen_saved_color_texture_->id();
[email protected]ae51d192010-04-27 00:48:031873 GLuint client_id = 0;
1874 if (parent_->texture_manager()->GetClientId(service_id, &client_id)) {
1875 parent_->texture_manager()->RemoveTextureInfo(client_id);
[email protected]4bedba72010-04-20 22:08:541876 }
[email protected]6217d392010-03-25 22:08:351877 }
[email protected]6217d392010-03-25 22:08:351878
[email protected]4bedba72010-04-20 22:08:541879 if (offscreen_target_frame_buffer_.get()) {
1880 offscreen_target_frame_buffer_->Destroy();
1881 offscreen_target_frame_buffer_.reset();
1882 }
[email protected]6217d392010-03-25 22:08:351883
[email protected]4bedba72010-04-20 22:08:541884 if (offscreen_target_color_texture_.get()) {
1885 offscreen_target_color_texture_->Destroy();
1886 offscreen_target_color_texture_.reset();
1887 }
[email protected]6217d392010-03-25 22:08:351888
[email protected]4bedba72010-04-20 22:08:541889 if (offscreen_target_depth_stencil_render_buffer_.get()) {
1890 offscreen_target_depth_stencil_render_buffer_->Destroy();
1891 offscreen_target_depth_stencil_render_buffer_.reset();
1892 }
[email protected]6217d392010-03-25 22:08:351893
[email protected]4bedba72010-04-20 22:08:541894 if (offscreen_saved_color_texture_.get()) {
1895 offscreen_saved_color_texture_->Destroy();
1896 offscreen_saved_color_texture_.reset();
1897 }
[email protected]d37231fa2010-04-09 21:16:021898 }
[email protected]2f2d7042010-04-14 21:45:581899
1900 if (default_context_.get()) {
1901 default_context_->Destroy();
1902 default_context_.reset();
1903 }
[email protected]de17df392010-04-23 21:09:411904
[email protected]bc10076c2010-05-14 19:14:061905#if !defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2) && !defined(UNIT_TEST)
[email protected]de17df392010-04-23 21:09:411906#if defined(GLES2_GPU_SERVICE_TRANSLATE_SHADER)
1907 // Terminate GLSL translator.
1908 ShFinalize();
1909#endif // GLES2_GPU_SERVICE_TRANSLATE_SHADER
1910#endif // GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2
[email protected]96449d2c2009-11-25 00:01:321911}
1912
[email protected]6217d392010-03-25 22:08:351913void GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
1914 // We can't resize the render buffers immediately because there might be a
1915 // partial frame rendered into them and we don't want the tail end of that
1916 // rendered into the reallocated storage. Defer until the next SwapBuffers.
[email protected]d37231fa2010-04-09 21:16:021917 pending_offscreen_size_ = size;
[email protected]6217d392010-03-25 22:08:351918}
1919
[email protected]96449d2c2009-11-25 00:01:321920const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
1921 if (command_id > kStartPoint && command_id < kNumCommands) {
1922 return gles2::GetCommandName(static_cast<CommandId>(command_id));
1923 }
1924 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
1925}
1926
1927// Decode command with its arguments, and call the corresponding GL function.
1928// Note: args is a pointer to the command buffer. As such, it could be changed
1929// by a (malicious) client at any time, so if validation has to happen, it
1930// should operate on a copy of them.
[email protected]f7a64ee2010-02-01 22:24:141931error::Error GLES2DecoderImpl::DoCommand(
[email protected]96449d2c2009-11-25 00:01:321932 unsigned int command,
1933 unsigned int arg_count,
1934 const void* cmd_data) {
[email protected]f7a64ee2010-02-01 22:24:141935 error::Error result = error::kNoError;
[email protected]b9849abf2009-11-25 19:13:191936 if (debug()) {
1937 // TODO(gman): Change output to something useful for NaCl.
[email protected]f39f4b3f2010-05-12 17:04:081938 DLOG(INFO) << "cmd: " << GetCommandName(command);
[email protected]b9849abf2009-11-25 19:13:191939 }
[email protected]96449d2c2009-11-25 00:01:321940 unsigned int command_index = command - kStartPoint - 1;
1941 if (command_index < arraysize(g_command_info)) {
1942 const CommandInfo& info = g_command_info[command_index];
1943 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
1944 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
1945 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
[email protected]b9849abf2009-11-25 19:13:191946 uint32 immediate_data_size =
1947 (arg_count - info_arg_count) * sizeof(CommandBufferEntry); // NOLINT
[email protected]96449d2c2009-11-25 00:01:321948 switch (command) {
1949 #define GLES2_CMD_OP(name) \
1950 case name::kCmdId: \
[email protected]b9849abf2009-11-25 19:13:191951 result = Handle ## name( \
1952 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:321953 *static_cast<const name*>(cmd_data)); \
[email protected]b9849abf2009-11-25 19:13:191954 break; \
[email protected]96449d2c2009-11-25 00:01:321955
1956 GLES2_COMMAND_LIST(GLES2_CMD_OP)
[email protected]96449d2c2009-11-25 00:01:321957 #undef GLES2_CMD_OP
[email protected]bf0985e2009-12-17 03:04:381958 }
1959 if (debug()) {
[email protected]07f54fcc2009-12-22 02:46:301960 GLenum error;
1961 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]bf0985e2009-12-17 03:04:381962 // TODO(gman): Change output to something useful for NaCl.
[email protected]8eee29c2010-04-29 03:38:291963 SetGLError(error, NULL);
[email protected]f39f4b3f2010-05-12 17:04:081964 DLOG(INFO) << "GL ERROR: " << error
1965 << " : " << GetCommandName(command);
[email protected]b9849abf2009-11-25 19:13:191966 }
[email protected]96449d2c2009-11-25 00:01:321967 }
1968 } else {
[email protected]f7a64ee2010-02-01 22:24:141969 result = error::kInvalidArguments;
[email protected]96449d2c2009-11-25 00:01:321970 }
[email protected]b9849abf2009-11-25 19:13:191971 } else {
1972 result = DoCommonCommand(command, arg_count, cmd_data);
[email protected]96449d2c2009-11-25 00:01:321973 }
[email protected]b9849abf2009-11-25 19:13:191974 return result;
[email protected]96449d2c2009-11-25 00:01:321975}
1976
[email protected]ae51d192010-04-27 00:48:031977void GLES2DecoderImpl::RemoveBufferInfo(GLuint client_id) {
1978 buffer_manager()->RemoveBufferInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:501979}
1980
[email protected]ae51d192010-04-27 00:48:031981bool GLES2DecoderImpl::CreateProgramHelper(GLuint client_id) {
1982 if (GetProgramInfo(client_id)) {
1983 return false;
1984 }
[email protected]96449d2c2009-11-25 00:01:321985 GLuint service_id = glCreateProgram();
[email protected]ae51d192010-04-27 00:48:031986 if (service_id != 0) {
1987 CreateProgramInfo(client_id, service_id);
[email protected]96449d2c2009-11-25 00:01:321988 }
[email protected]ae51d192010-04-27 00:48:031989 return true;
[email protected]96449d2c2009-11-25 00:01:321990}
1991
[email protected]ae51d192010-04-27 00:48:031992bool GLES2DecoderImpl::CreateShaderHelper(GLenum type, GLuint client_id) {
1993 if (GetShaderInfo(client_id)) {
1994 return false;
[email protected]96449d2c2009-11-25 00:01:321995 }
[email protected]ae51d192010-04-27 00:48:031996 GLuint service_id = glCreateShader(type);
1997 if (service_id != 0) {
[email protected]7cea56d92010-04-28 17:21:381998 CreateShaderInfo(client_id, service_id, type);
[email protected]ae51d192010-04-27 00:48:031999 }
2000 return true;
[email protected]96449d2c2009-11-25 00:01:322001}
2002
[email protected]86093972010-03-11 00:13:562003bool GLES2DecoderImpl::ValidateGLenumCompressedTextureInternalFormat(GLenum) {
2004 // TODO(gman): Add support for compressed texture formats.
2005 return false;
2006}
2007
[email protected]3916c97e2010-02-25 03:20:502008void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
[email protected]36cef8ce2010-03-16 07:34:452009 GLuint texture_index = texture_unit - GL_TEXTURE0;
2010 if (texture_index > group_->max_texture_units()) {
[email protected]8eee29c2010-04-29 03:38:292011 SetGLError(GL_INVALID_ENUM, "glActiveTexture: texture_unit out of range.");
[email protected]3916c97e2010-02-25 03:20:502012 return;
2013 }
[email protected]36cef8ce2010-03-16 07:34:452014 active_texture_unit_ = texture_index;
2015 glActiveTexture(texture_unit);
[email protected]3916c97e2010-02-25 03:20:502016}
2017
[email protected]051b1372010-04-12 02:42:082018void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:502019 BufferManager::BufferInfo* info = NULL;
[email protected]051b1372010-04-12 02:42:082020 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:032021 if (client_id != 0) {
2022 info = GetBufferInfo(client_id);
2023 if (!info) {
2024 // It's a new id so make a buffer info for it.
2025 glGenBuffersARB(1, &service_id);
2026 CreateBufferInfo(client_id, service_id);
2027 info = GetBufferInfo(client_id);
[email protected]066849e32010-05-03 19:14:102028 IdAllocator* id_allocator =
2029 group_->GetIdAllocator(id_namespaces::kBuffers);
2030 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:032031 }
[email protected]051b1372010-04-12 02:42:082032 }
[email protected]ae51d192010-04-27 00:48:032033 if (info) {
[email protected]4e8a5b122010-05-08 22:00:102034 if (!buffer_manager()->SetTarget(info, target)) {
[email protected]8eee29c2010-04-29 03:38:292035 SetGLError(GL_INVALID_OPERATION,
2036 "glBindBuffer: buffer bound to more than 1 target");
[email protected]a93bb842010-02-16 23:03:472037 return;
2038 }
[email protected]ae51d192010-04-27 00:48:032039 service_id = info->service_id();
[email protected]a93bb842010-02-16 23:03:472040 }
[email protected]96449d2c2009-11-25 00:01:322041 switch (target) {
2042 case GL_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:502043 bound_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:322044 break;
2045 case GL_ELEMENT_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:502046 bound_element_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:322047 break;
2048 default:
[email protected]a93bb842010-02-16 23:03:472049 NOTREACHED(); // Validation should prevent us getting here.
[email protected]96449d2c2009-11-25 00:01:322050 break;
2051 }
[email protected]051b1372010-04-12 02:42:082052 glBindBuffer(target, service_id);
[email protected]96449d2c2009-11-25 00:01:322053}
2054
[email protected]051b1372010-04-12 02:42:082055void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
2056 FramebufferManager::FramebufferInfo* info = NULL;
2057 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:032058 if (client_id != 0) {
2059 info = GetFramebufferInfo(client_id);
[email protected]051b1372010-04-12 02:42:082060 if (!info) {
[email protected]ae51d192010-04-27 00:48:032061 // It's a new id so make a framebuffer info for it.
2062 glGenFramebuffersEXT(1, &service_id);
2063 CreateFramebufferInfo(client_id, service_id);
2064 info = GetFramebufferInfo(client_id);
[email protected]066849e32010-05-03 19:14:102065 IdAllocator* id_allocator =
2066 group_->GetIdAllocator(id_namespaces::kFramebuffers);
2067 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:032068 } else {
2069 service_id = info->service_id();
[email protected]051b1372010-04-12 02:42:082070 }
2071 }
2072 bound_framebuffer_ = info;
[email protected]6217d392010-03-25 22:08:352073
2074 // When rendering to an offscreen frame buffer, instead of unbinding from
2075 // the current frame buffer, bind to the offscreen target frame buffer.
[email protected]051b1372010-04-12 02:42:082076 if (info == NULL && offscreen_target_frame_buffer_.get())
2077 service_id = offscreen_target_frame_buffer_->id();
[email protected]6217d392010-03-25 22:08:352078
[email protected]051b1372010-04-12 02:42:082079 glBindFramebufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:562080}
2081
[email protected]051b1372010-04-12 02:42:082082void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
2083 RenderbufferManager::RenderbufferInfo* info = NULL;
2084 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:032085 if (client_id != 0) {
2086 info = GetRenderbufferInfo(client_id);
[email protected]051b1372010-04-12 02:42:082087 if (!info) {
[email protected]ae51d192010-04-27 00:48:032088 // It's a new id so make a renderbuffer info for it.
2089 glGenRenderbuffersEXT(1, &service_id);
2090 CreateRenderbufferInfo(client_id, service_id);
[email protected]066849e32010-05-03 19:14:102091 info = GetRenderbufferInfo(client_id);
2092 IdAllocator* id_allocator =
2093 group_->GetIdAllocator(id_namespaces::kRenderbuffers);
2094 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:032095 } else {
2096 service_id = info->service_id();
[email protected]051b1372010-04-12 02:42:082097 }
2098 }
2099 bound_renderbuffer_ = info;
2100 glBindRenderbufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:562101}
2102
[email protected]051b1372010-04-12 02:42:082103void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:032104 TextureManager::TextureInfo* info = NULL;
[email protected]051b1372010-04-12 02:42:082105 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:032106 if (client_id != 0) {
2107 info = GetTextureInfo(client_id);
2108 if (!info) {
2109 // It's a new id so make a texture info for it.
2110 glGenTextures(1, &service_id);
2111 CreateTextureInfo(client_id, service_id);
2112 info = GetTextureInfo(client_id);
[email protected]066849e32010-05-03 19:14:102113 IdAllocator* id_allocator =
2114 group_->GetIdAllocator(id_namespaces::kTextures);
2115 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:032116 }
2117 } else {
2118 info = texture_manager()->GetDefaultTextureInfo(target);
[email protected]051b1372010-04-12 02:42:082119 }
[email protected]ae51d192010-04-27 00:48:032120
[email protected]1958e0e2010-04-22 05:17:152121 // Check the texture exists
2122 // Check that we are not trying to bind it to a different target.
[email protected]ae51d192010-04-27 00:48:032123 if (info->target() != 0 && info->target() != target) {
[email protected]8eee29c2010-04-29 03:38:292124 SetGLError(GL_INVALID_OPERATION,
2125 "glBindTexture: texture bound to more than 1 target.");
[email protected]1958e0e2010-04-22 05:17:152126 return;
2127 }
2128 if (info->target() == 0) {
2129 texture_manager()->SetInfoTarget(info, target);
[email protected]a93bb842010-02-16 23:03:472130 }
[email protected]ae51d192010-04-27 00:48:032131 glBindTexture(target, info->service_id());
[email protected]3916c97e2010-02-25 03:20:502132 TextureUnit& unit = texture_units_[active_texture_unit_];
2133 unit.bind_target = target;
[email protected]a93bb842010-02-16 23:03:472134 switch (target) {
2135 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:502136 unit.bound_texture_2d = info;
[email protected]a93bb842010-02-16 23:03:472137 break;
2138 case GL_TEXTURE_CUBE_MAP:
[email protected]3916c97e2010-02-25 03:20:502139 unit.bound_texture_cube_map = info;
[email protected]a93bb842010-02-16 23:03:472140 break;
2141 default:
2142 NOTREACHED(); // Validation should prevent us getting here.
2143 break;
2144 }
2145}
2146
[email protected]07f54fcc2009-12-22 02:46:302147void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
[email protected]f39f4b3f2010-05-12 17:04:082148 if (vertex_attrib_manager_.Enable(index, false)) {
[email protected]b1122982010-05-17 23:04:242149 if (index != 0) {
2150 glDisableVertexAttribArray(index);
2151 }
[email protected]07f54fcc2009-12-22 02:46:302152 } else {
[email protected]8eee29c2010-04-29 03:38:292153 SetGLError(GL_INVALID_VALUE,
2154 "glDisableVertexAttribArray: index out of range");
[email protected]07f54fcc2009-12-22 02:46:302155 }
2156}
2157
2158void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
[email protected]f39f4b3f2010-05-12 17:04:082159 if (vertex_attrib_manager_.Enable(index, true)) {
[email protected]07f54fcc2009-12-22 02:46:302160 glEnableVertexAttribArray(index);
2161 } else {
[email protected]8eee29c2010-04-29 03:38:292162 SetGLError(GL_INVALID_VALUE,
2163 "glEnableVertexAttribArray: index out of range");
[email protected]07f54fcc2009-12-22 02:46:302164 }
2165}
2166
[email protected]a93bb842010-02-16 23:03:472167void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
[email protected]3916c97e2010-02-25 03:20:502168 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]ef526492010-06-02 23:12:252169 if (!info || !texture_manager()->MarkMipmapsGenerated(info)) {
[email protected]8eee29c2010-04-29 03:38:292170 SetGLError(GL_INVALID_OPERATION,
2171 "glGenerateMipmaps: Can not generate mips for npot textures");
[email protected]a93bb842010-02-16 23:03:472172 return;
2173 }
2174 glGenerateMipmapEXT(target);
[email protected]a93bb842010-02-16 23:03:472175}
2176
[email protected]b273e432010-04-12 17:23:582177bool GLES2DecoderImpl::GetHelper(
2178 GLenum pname, GLint* params, GLsizei* num_written) {
[email protected]b273e432010-04-12 17:23:582179 DCHECK(num_written);
2180 switch (pname) {
[email protected]58ae32f2010-04-14 01:26:042181#if !defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
[email protected]b273e432010-04-12 17:23:582182 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
2183 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102184 if (params) {
2185 *params = GL_RGBA; // TODO(gman): get correct format.
2186 }
[email protected]b273e432010-04-12 17:23:582187 return true;
2188 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2189 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102190 if (params) {
2191 *params = GL_UNSIGNED_BYTE; // TODO(gman): get correct type.
2192 }
[email protected]b273e432010-04-12 17:23:582193 return true;
2194 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
2195 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102196 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:482197 *params = group_->max_fragment_uniform_vectors();
[email protected]4e8a5b122010-05-08 22:00:102198 }
[email protected]b273e432010-04-12 17:23:582199 return true;
2200 case GL_MAX_VARYING_VECTORS:
2201 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102202 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:482203 *params = group_->max_varying_vectors();
[email protected]4e8a5b122010-05-08 22:00:102204 }
[email protected]b273e432010-04-12 17:23:582205 return true;
2206 case GL_MAX_VERTEX_UNIFORM_VECTORS:
2207 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102208 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:482209 *params = group_->max_vertex_uniform_vectors();
[email protected]4e8a5b122010-05-08 22:00:102210 }
[email protected]b273e432010-04-12 17:23:582211 return true;
[email protected]58ae32f2010-04-14 01:26:042212#endif
[email protected]656dcaad2010-05-07 17:18:372213 case GL_COMPRESSED_TEXTURE_FORMATS:
2214 *num_written = 0;
2215 // We don't support compressed textures.
2216 return true;
[email protected]b273e432010-04-12 17:23:582217 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
2218 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102219 if (params) {
2220 *params = 0; // We don't support compressed textures.
2221 }
[email protected]b273e432010-04-12 17:23:582222 return true;
2223 case GL_NUM_SHADER_BINARY_FORMATS:
2224 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102225 if (params) {
2226 *params = 0; // We don't support binary shader formats.
2227 }
[email protected]b273e432010-04-12 17:23:582228 return true;
2229 case GL_SHADER_BINARY_FORMATS:
2230 *num_written = 0;
2231 return true; // We don't support binary shader format.s
2232 case GL_SHADER_COMPILER:
2233 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102234 if (params) {
2235 *params = GL_TRUE;
2236 }
[email protected]b273e432010-04-12 17:23:582237 return true;
[email protected]6b8cf1a2010-05-06 16:13:582238 case GL_ARRAY_BUFFER_BINDING:
2239 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102240 if (params) {
2241 if (bound_array_buffer_) {
2242 GLuint client_id = 0;
2243 buffer_manager()->GetClientId(bound_array_buffer_->service_id(),
2244 &client_id);
2245 *params = client_id;
2246 } else {
2247 *params = 0;
2248 }
[email protected]6b8cf1a2010-05-06 16:13:582249 }
2250 return true;
2251 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
2252 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102253 if (params) {
2254 if (bound_element_array_buffer_) {
2255 GLuint client_id = 0;
2256 buffer_manager()->GetClientId(
2257 bound_element_array_buffer_->service_id(),
2258 &client_id);
2259 *params = client_id;
2260 } else {
2261 *params = 0;
2262 }
[email protected]6b8cf1a2010-05-06 16:13:582263 }
2264 return true;
2265 case GL_FRAMEBUFFER_BINDING:
2266 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102267 if (params) {
2268 if (bound_framebuffer_) {
2269 GLuint client_id = 0;
2270 framebuffer_manager()->GetClientId(
2271 bound_framebuffer_->service_id(), &client_id);
2272 *params = client_id;
2273 } else {
2274 *params = 0;
2275 }
[email protected]6b8cf1a2010-05-06 16:13:582276 }
2277 return true;
2278 case GL_RENDERBUFFER_BINDING:
2279 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102280 if (params) {
2281 if (bound_renderbuffer_) {
2282 GLuint client_id = 0;
2283 renderbuffer_manager()->GetClientId(
2284 bound_renderbuffer_->service_id(), &client_id);
2285 *params = client_id;
2286 } else {
2287 *params = 0;
2288 }
[email protected]6b8cf1a2010-05-06 16:13:582289 }
2290 return true;
2291 case GL_CURRENT_PROGRAM:
2292 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102293 if (params) {
2294 if (current_program_) {
2295 GLuint client_id = 0;
2296 program_manager()->GetClientId(
2297 current_program_->service_id(), &client_id);
2298 *params = client_id;
2299 } else {
2300 *params = 0;
2301 }
[email protected]6b8cf1a2010-05-06 16:13:582302 }
2303 return true;
[email protected]4e8a5b122010-05-08 22:00:102304 case GL_TEXTURE_BINDING_2D:
2305 *num_written = 1;
2306 if (params) {
[email protected]6b8cf1a2010-05-06 16:13:582307 TextureUnit& unit = texture_units_[active_texture_unit_];
2308 if (unit.bound_texture_2d) {
2309 GLuint client_id = 0;
2310 texture_manager()->GetClientId(
2311 unit.bound_texture_2d->service_id(), &client_id);
2312 *params = client_id;
2313 } else {
2314 *params = 0;
2315 }
[email protected]6b8cf1a2010-05-06 16:13:582316 }
[email protected]4e8a5b122010-05-08 22:00:102317 return true;
2318 case GL_TEXTURE_BINDING_CUBE_MAP:
2319 *num_written = 1;
2320 if (params) {
[email protected]6b8cf1a2010-05-06 16:13:582321 TextureUnit& unit = texture_units_[active_texture_unit_];
2322 if (unit.bound_texture_cube_map) {
2323 GLuint client_id = 0;
2324 texture_manager()->GetClientId(
2325 unit.bound_texture_cube_map->service_id(), &client_id);
2326 *params = client_id;
2327 } else {
2328 *params = 0;
2329 }
[email protected]6b8cf1a2010-05-06 16:13:582330 }
[email protected]4e8a5b122010-05-08 22:00:102331 return true;
[email protected]b273e432010-04-12 17:23:582332 default:
[email protected]4e8a5b122010-05-08 22:00:102333 *num_written = util_.GLGetNumValuesReturned(pname);
2334 if (params) {
2335 glGetIntegerv(pname, params);
2336 }
2337 return true;
[email protected]b273e432010-04-12 17:23:582338 }
2339}
2340
[email protected]4e8a5b122010-05-08 22:00:102341bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
2342 GLenum pname, GLsizei* num_values) {
2343 return GetHelper(pname, NULL, num_values);
2344}
2345
[email protected]b273e432010-04-12 17:23:582346void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
2347 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:102348 GLsizei num_written = 0;
2349 if (GetHelper(pname, NULL, &num_written)) {
2350 scoped_array<GLint> values(new GLint[num_written]);
2351 GetHelper(pname, values.get(), &num_written);
[email protected]b273e432010-04-12 17:23:582352 for (GLsizei ii = 0; ii < num_written; ++ii) {
2353 params[ii] = static_cast<GLboolean>(values[ii]);
2354 }
2355 } else {
2356 glGetBooleanv(pname, params);
2357 }
2358}
2359
2360void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
2361 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:102362 GLsizei num_written = 0;
2363 if (GetHelper(pname, NULL, &num_written)) {
2364 scoped_array<GLint> values(new GLint[num_written]);
2365 GetHelper(pname, values.get(), &num_written);
[email protected]b273e432010-04-12 17:23:582366 for (GLsizei ii = 0; ii < num_written; ++ii) {
2367 params[ii] = static_cast<GLfloat>(values[ii]);
2368 }
2369 } else {
2370 glGetFloatv(pname, params);
2371 }
2372}
2373
2374void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
2375 DCHECK(params);
2376 GLsizei num_written;
2377 if (!GetHelper(pname, params, &num_written)) {
2378 glGetIntegerv(pname, params);
2379 }
2380}
2381
[email protected]a0c3e972010-04-21 00:49:132382void GLES2DecoderImpl::DoGetProgramiv(
2383 GLuint program_id, GLenum pname, GLint* params) {
[email protected]6b8cf1a2010-05-06 16:13:582384 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
2385 program_id, "glGetProgramiv");
[email protected]a0c3e972010-04-21 00:49:132386 if (!info) {
[email protected]a0c3e972010-04-21 00:49:132387 return;
2388 }
2389 info->GetProgramiv(pname, params);
2390}
2391
[email protected]558847a2010-03-24 07:02:542392error::Error GLES2DecoderImpl::HandleBindAttribLocation(
2393 uint32 immediate_data_size, const gles2::BindAttribLocation& c) {
[email protected]6b8cf1a2010-05-06 16:13:582394 GLuint program = static_cast<GLuint>(c.program);
2395 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
2396 program, "glBindAttribLocation");
[email protected]ae51d192010-04-27 00:48:032397 if (!info) {
[email protected]558847a2010-03-24 07:02:542398 return error::kNoError;
2399 }
2400 GLuint index = static_cast<GLuint>(c.index);
2401 uint32 name_size = c.data_size;
2402 const char* name = GetSharedMemoryAs<const char*>(
2403 c.name_shm_id, c.name_shm_offset, name_size);
2404 if (name == NULL) {
2405 return error::kOutOfBounds;
2406 }
2407 String name_str(name, name_size);
[email protected]ae51d192010-04-27 00:48:032408 glBindAttribLocation(info->service_id(), index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:542409 return error::kNoError;
2410}
2411
2412error::Error GLES2DecoderImpl::HandleBindAttribLocationImmediate(
2413 uint32 immediate_data_size, const gles2::BindAttribLocationImmediate& c) {
[email protected]6b8cf1a2010-05-06 16:13:582414 GLuint program = static_cast<GLuint>(c.program);
2415 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
2416 program, "glBindAttribLocation");
[email protected]ae51d192010-04-27 00:48:032417 if (!info) {
[email protected]558847a2010-03-24 07:02:542418 return error::kNoError;
2419 }
2420 GLuint index = static_cast<GLuint>(c.index);
2421 uint32 name_size = c.data_size;
2422 const char* name = GetImmediateDataAs<const char*>(
2423 c, name_size, immediate_data_size);
2424 if (name == NULL) {
2425 return error::kOutOfBounds;
2426 }
2427 String name_str(name, name_size);
[email protected]ae51d192010-04-27 00:48:032428 glBindAttribLocation(info->service_id(), index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:542429 return error::kNoError;
2430}
2431
2432error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
2433 uint32 immediate_data_size, const gles2::BindAttribLocationBucket& c) {
[email protected]6b8cf1a2010-05-06 16:13:582434 GLuint program = static_cast<GLuint>(c.program);
2435 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
2436 program, "glBindAttribLocation");
[email protected]ae51d192010-04-27 00:48:032437 if (!info) {
[email protected]558847a2010-03-24 07:02:542438 return error::kNoError;
2439 }
2440 GLuint index = static_cast<GLuint>(c.index);
2441 Bucket* bucket = GetBucket(c.name_bucket_id);
2442 if (!bucket || bucket->size() == 0) {
2443 return error::kInvalidArguments;
2444 }
2445 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:182446 if (!bucket->GetAsString(&name_str)) {
2447 return error::kInvalidArguments;
2448 }
[email protected]ae51d192010-04-27 00:48:032449 glBindAttribLocation(info->service_id(), index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:542450 return error::kNoError;
2451}
2452
[email protected]f7a64ee2010-02-01 22:24:142453error::Error GLES2DecoderImpl::HandleDeleteShader(
[email protected]ba3176a2009-12-16 18:19:462454 uint32 immediate_data_size, const gles2::DeleteShader& c) {
[email protected]ae51d192010-04-27 00:48:032455 GLuint client_id = c.shader;
2456 if (client_id) {
2457 ShaderManager::ShaderInfo* info = GetShaderInfo(client_id);
2458 if (info) {
2459 glDeleteShader(info->service_id());
2460 RemoveShaderInfo(client_id);
2461 } else {
[email protected]8eee29c2010-04-29 03:38:292462 SetGLError(GL_INVALID_VALUE, "glDeleteShader: unknown shader");
[email protected]ae51d192010-04-27 00:48:032463 }
[email protected]96449d2c2009-11-25 00:01:322464 }
[email protected]f7a64ee2010-02-01 22:24:142465 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322466}
2467
[email protected]f7a64ee2010-02-01 22:24:142468error::Error GLES2DecoderImpl::HandleDeleteProgram(
[email protected]ba3176a2009-12-16 18:19:462469 uint32 immediate_data_size, const gles2::DeleteProgram& c) {
[email protected]ae51d192010-04-27 00:48:032470 GLuint client_id = c.program;
2471 if (client_id) {
2472 ProgramManager::ProgramInfo* info = GetProgramInfo(client_id);
2473 if (info) {
2474 glDeleteProgram(info->service_id());
2475 RemoveProgramInfo(client_id);
2476 } else {
[email protected]8eee29c2010-04-29 03:38:292477 SetGLError(GL_INVALID_VALUE, "glDeleteProgram: unknown program");
[email protected]ae51d192010-04-27 00:48:032478 }
[email protected]96449d2c2009-11-25 00:01:322479 }
[email protected]f7a64ee2010-02-01 22:24:142480 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322481}
2482
[email protected]066849e32010-05-03 19:14:102483void GLES2DecoderImpl::DoDeleteSharedIds(
2484 GLuint namespace_id, GLsizei n, const GLuint* ids) {
2485 IdAllocator* id_allocator = group_->GetIdAllocator(namespace_id);
2486 for (GLsizei ii = 0; ii < n; ++ii) {
2487 id_allocator->FreeID(ids[ii]);
2488 }
2489}
2490
2491error::Error GLES2DecoderImpl::HandleDeleteSharedIds(
2492 uint32 immediate_data_size, const gles2::DeleteSharedIds& c) {
2493 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
2494 GLsizei n = static_cast<GLsizei>(c.n);
2495 uint32 data_size;
2496 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
2497 return error::kOutOfBounds;
2498 }
2499 const GLuint* ids = GetSharedMemoryAs<const GLuint*>(
2500 c.ids_shm_id, c.ids_shm_offset, data_size);
2501 if (n < 0) {
2502 SetGLError(GL_INVALID_VALUE, "DeleteSharedIds: n < 0");
2503 return error::kNoError;
2504 }
2505 if (ids == NULL) {
2506 return error::kOutOfBounds;
2507 }
2508 DoDeleteSharedIds(namespace_id, n, ids);
2509 return error::kNoError;
2510}
2511
2512void GLES2DecoderImpl::DoGenSharedIds(
2513 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids) {
2514 IdAllocator* id_allocator = group_->GetIdAllocator(namespace_id);
2515 if (id_offset == 0) {
2516 for (GLsizei ii = 0; ii < n; ++ii) {
2517 ids[ii] = id_allocator->AllocateID();
2518 }
2519 } else {
2520 for (GLsizei ii = 0; ii < n; ++ii) {
2521 ids[ii] = id_allocator->AllocateIDAtOrAbove(id_offset);
2522 id_offset = ids[ii] + 1;
2523 }
2524 }
2525}
2526
2527error::Error GLES2DecoderImpl::HandleGenSharedIds(
2528 uint32 immediate_data_size, const gles2::GenSharedIds& c) {
2529 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
2530 GLuint id_offset = static_cast<GLuint>(c.id_offset);
2531 GLsizei n = static_cast<GLsizei>(c.n);
2532 uint32 data_size;
2533 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
2534 return error::kOutOfBounds;
2535 }
2536 GLuint* ids = GetSharedMemoryAs<GLuint*>(
2537 c.ids_shm_id, c.ids_shm_offset, data_size);
2538 if (n < 0) {
2539 SetGLError(GL_INVALID_VALUE, "GenSharedIds: n < 0");
2540 return error::kNoError;
2541 }
2542 if (ids == NULL) {
2543 return error::kOutOfBounds;
2544 }
2545 DoGenSharedIds(namespace_id, id_offset, n, ids);
2546 return error::kNoError;
2547}
2548
2549void GLES2DecoderImpl::DoRegisterSharedIds(
2550 GLuint namespace_id, GLsizei n, const GLuint* ids) {
2551 IdAllocator* id_allocator = group_->GetIdAllocator(namespace_id);
2552 for (GLsizei ii = 0; ii < n; ++ii) {
2553 if (!id_allocator->MarkAsUsed(ids[ii])) {
2554 for (GLsizei jj = 0; jj < ii; ++jj) {
2555 id_allocator->FreeID(ids[jj]);
2556 }
2557 SetGLError(
2558 GL_INVALID_VALUE,
2559 "RegisterSharedIds: attempt to register id that already exists");
2560 return;
2561 }
2562 }
2563}
2564
2565error::Error GLES2DecoderImpl::HandleRegisterSharedIds(
2566 uint32 immediate_data_size, const gles2::RegisterSharedIds& c) {
2567 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
2568 GLsizei n = static_cast<GLsizei>(c.n);
2569 uint32 data_size;
2570 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
2571 return error::kOutOfBounds;
2572 }
2573 GLuint* ids = GetSharedMemoryAs<GLuint*>(
2574 c.ids_shm_id, c.ids_shm_offset, data_size);
2575 if (n < 0) {
2576 SetGLError(GL_INVALID_VALUE, "RegisterSharedIds: n < 0");
2577 return error::kNoError;
2578 }
2579 if (ids == NULL) {
2580 return error::kOutOfBounds;
2581 }
2582 DoRegisterSharedIds(namespace_id, n, ids);
2583 return error::kNoError;
2584}
2585
[email protected]07f54fcc2009-12-22 02:46:302586void GLES2DecoderImpl::DoDrawArrays(
2587 GLenum mode, GLint first, GLsizei count) {
2588 if (IsDrawValid(first + count - 1)) {
[email protected]b1122982010-05-17 23:04:242589 bool simulated_attrib_0 = SimulateAttrib0(first + count - 1);
[email protected]ef526492010-06-02 23:12:252590 bool textures_set = SetBlackTextureForNonRenderableTextures();
[email protected]07f54fcc2009-12-22 02:46:302591 glDrawArrays(mode, first, count);
[email protected]ef526492010-06-02 23:12:252592 if (textures_set) {
[email protected]3916c97e2010-02-25 03:20:502593 RestoreStateForNonRenderableTextures();
2594 }
[email protected]b1122982010-05-17 23:04:242595 if (simulated_attrib_0) {
2596 RestoreStateForSimulatedAttrib0();
2597 }
[email protected]07f54fcc2009-12-22 02:46:302598 }
2599}
2600
[email protected]36cef8ce2010-03-16 07:34:452601void GLES2DecoderImpl::DoFramebufferRenderbuffer(
2602 GLenum target, GLenum attachment, GLenum renderbuffertarget,
[email protected]ae51d192010-04-27 00:48:032603 GLuint client_renderbuffer_id) {
[email protected]051b1372010-04-12 02:42:082604 if (!bound_framebuffer_) {
[email protected]8eee29c2010-04-29 03:38:292605 SetGLError(GL_INVALID_OPERATION,
2606 "glFramebufferRenderbuffer: no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:452607 return;
2608 }
[email protected]ae51d192010-04-27 00:48:032609 GLuint service_id = 0;
2610 if (client_renderbuffer_id) {
2611 RenderbufferManager::RenderbufferInfo* info =
2612 GetRenderbufferInfo(client_renderbuffer_id);
2613 if (!info) {
[email protected]8eee29c2010-04-29 03:38:292614 SetGLError(GL_INVALID_OPERATION,
2615 "glFramebufferRenderbuffer: unknown renderbuffer");
[email protected]ae51d192010-04-27 00:48:032616 return;
2617 }
2618 service_id = info->service_id();
2619 }
2620 glFramebufferRenderbufferEXT(
2621 target, attachment, renderbuffertarget, service_id);
[email protected]36cef8ce2010-03-16 07:34:452622}
2623
2624GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
[email protected]051b1372010-04-12 02:42:082625 if (!bound_framebuffer_) {
[email protected]36cef8ce2010-03-16 07:34:452626 return GL_FRAMEBUFFER_COMPLETE;
2627 }
2628 return glCheckFramebufferStatusEXT(target);
2629}
2630
2631void GLES2DecoderImpl::DoFramebufferTexture2D(
[email protected]ae51d192010-04-27 00:48:032632 GLenum target, GLenum attachment, GLenum textarget,
2633 GLuint client_texture_id, GLint level) {
[email protected]051b1372010-04-12 02:42:082634 if (!bound_framebuffer_) {
[email protected]8eee29c2010-04-29 03:38:292635 SetGLError(GL_INVALID_OPERATION,
2636 "glFramebufferTexture2D: no framebuffer bound.");
[email protected]36cef8ce2010-03-16 07:34:452637 return;
2638 }
[email protected]ae51d192010-04-27 00:48:032639 GLuint service_id = 0;
2640 if (client_texture_id) {
2641 TextureManager::TextureInfo* info = GetTextureInfo(client_texture_id);
2642 if (!info) {
[email protected]8eee29c2010-04-29 03:38:292643 SetGLError(GL_INVALID_OPERATION,
2644 "glFramebufferTexture2D: unknown texture");
[email protected]ae51d192010-04-27 00:48:032645 return;
2646 }
2647 service_id = info->service_id();
2648 }
2649 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
[email protected]36cef8ce2010-03-16 07:34:452650}
2651
2652void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
2653 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
[email protected]051b1372010-04-12 02:42:082654 if (!bound_framebuffer_) {
[email protected]8eee29c2010-04-29 03:38:292655 SetGLError(GL_INVALID_OPERATION,
2656 "glFramebufferAttachmentParameteriv: no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:452657 return;
2658 }
2659 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
2660}
2661
2662void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
2663 GLenum target, GLenum pname, GLint* params) {
[email protected]051b1372010-04-12 02:42:082664 if (!bound_renderbuffer_) {
[email protected]8eee29c2010-04-29 03:38:292665 SetGLError(GL_INVALID_OPERATION,
2666 "glGetRenderbufferParameteriv: no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:452667 return;
2668 }
2669 glGetRenderbufferParameterivEXT(target, pname, params);
2670}
2671
2672void GLES2DecoderImpl::DoRenderbufferStorage(
2673 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
[email protected]051b1372010-04-12 02:42:082674 if (!bound_renderbuffer_) {
[email protected]8eee29c2010-04-29 03:38:292675 SetGLError(GL_INVALID_OPERATION,
2676 "glGetRenderbufferStorage: no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:452677 return;
2678 }
2679 glRenderbufferStorageEXT(target, internalformat, width, height);
2680}
2681
[email protected]07f54fcc2009-12-22 02:46:302682void GLES2DecoderImpl::DoLinkProgram(GLuint program) {
[email protected]6b8cf1a2010-05-06 16:13:582683 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
2684 program, "glLinkProgram");
[email protected]a93bb842010-02-16 23:03:472685 if (!info) {
[email protected]a93bb842010-02-16 23:03:472686 return;
2687 }
[email protected]ae51d192010-04-27 00:48:032688 glLinkProgram(info->service_id());
[email protected]6b8cf1a2010-05-06 16:13:582689 GLint success = 0;
2690 glGetProgramiv(info->service_id(), GL_LINK_STATUS, &success);
2691 if (success) {
[email protected]a93bb842010-02-16 23:03:472692 info->Update();
[email protected]6b8cf1a2010-05-06 16:13:582693 } else {
2694 info->Reset();
[email protected]07f54fcc2009-12-22 02:46:302695 }
2696};
2697
[email protected]3916c97e2010-02-25 03:20:502698void GLES2DecoderImpl::DoTexParameterf(
2699 GLenum target, GLenum pname, GLfloat param) {
2700 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]07f54fcc2009-12-22 02:46:302701 if (!info) {
[email protected]8eee29c2010-04-29 03:38:292702 SetGLError(GL_INVALID_VALUE, "glTexParameterf: unknown texture");
[email protected]07f54fcc2009-12-22 02:46:302703 } else {
[email protected]ef526492010-06-02 23:12:252704 texture_manager()->SetParameter(info, pname, static_cast<GLint>(param));
[email protected]3916c97e2010-02-25 03:20:502705 glTexParameterf(target, pname, param);
[email protected]07f54fcc2009-12-22 02:46:302706 }
2707}
2708
[email protected]3916c97e2010-02-25 03:20:502709void GLES2DecoderImpl::DoTexParameteri(
2710 GLenum target, GLenum pname, GLint param) {
2711 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
2712 if (!info) {
[email protected]8eee29c2010-04-29 03:38:292713 SetGLError(GL_INVALID_VALUE, "glTexParameteri: unknown texture");
[email protected]3916c97e2010-02-25 03:20:502714 } else {
[email protected]ef526492010-06-02 23:12:252715 texture_manager()->SetParameter(info, pname, param);
[email protected]3916c97e2010-02-25 03:20:502716 glTexParameteri(target, pname, param);
2717 }
2718}
2719
2720void GLES2DecoderImpl::DoTexParameterfv(
2721 GLenum target, GLenum pname, const GLfloat* params) {
2722 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
2723 if (!info) {
[email protected]8eee29c2010-04-29 03:38:292724 SetGLError(GL_INVALID_VALUE, "glTexParameterfv: unknown texture");
[email protected]3916c97e2010-02-25 03:20:502725 } else {
[email protected]ef526492010-06-02 23:12:252726 texture_manager()->SetParameter(
2727 info, pname, *reinterpret_cast<const GLint*>(params));
[email protected]3916c97e2010-02-25 03:20:502728 glTexParameterfv(target, pname, params);
2729 }
2730}
2731
2732void GLES2DecoderImpl::DoTexParameteriv(
2733 GLenum target, GLenum pname, const GLint* params) {
2734 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
2735 if (!info) {
[email protected]8eee29c2010-04-29 03:38:292736 SetGLError(GL_INVALID_VALUE, "glTexParameteriv: unknown texture");
[email protected]3916c97e2010-02-25 03:20:502737 } else {
[email protected]ef526492010-06-02 23:12:252738 texture_manager()->SetParameter(info, pname, *params);
[email protected]3916c97e2010-02-25 03:20:502739 glTexParameteriv(target, pname, params);
2740 }
2741}
2742
[email protected]939e7362010-05-13 20:49:102743bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
[email protected]3916c97e2010-02-25 03:20:502744 if (!current_program_ || current_program_->IsDeleted()) {
[email protected]939e7362010-05-13 20:49:102745 // The program does not exist.
2746 SetGLError(GL_INVALID_OPERATION,
2747 (std::string(function_name) + ": no program in use").c_str());
2748 return false;
2749 }
2750 if (!current_program_->IsValid()) {
2751 SetGLError(GL_INVALID_OPERATION,
2752 (std::string(function_name) + ": program not linked").c_str());
2753 return false;
2754 }
2755 return true;
2756}
2757
2758bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
2759 GLint location, const char* function_name) {
2760 if (!CheckCurrentProgram(function_name)) {
2761 return false;
2762 }
2763 return location != -1;
2764}
2765
2766bool GLES2DecoderImpl::GetUniformTypeByLocation(
2767 GLint location, const char* function_name, GLenum* type) {
2768 if (!CheckCurrentProgramForUniform(location, function_name)) {
2769 return false;
2770 }
2771 if (!current_program_->GetUniformTypeByLocation(location, type)) {
2772 SetGLError(GL_INVALID_OPERATION,
2773 (std::string(function_name) + ": program not linked").c_str());
2774 return false;
2775 }
2776 return true;
2777}
2778
2779
2780void GLES2DecoderImpl::DoUniform1i(GLint location, GLint v0) {
2781 if (!CheckCurrentProgramForUniform(location, "glUniform1i")) {
[email protected]3916c97e2010-02-25 03:20:502782 return;
2783 }
2784 current_program_->SetSamplers(location, 1, &v0);
2785 glUniform1i(location, v0);
2786}
2787
2788void GLES2DecoderImpl::DoUniform1iv(
2789 GLint location, GLsizei count, const GLint *value) {
[email protected]939e7362010-05-13 20:49:102790 if (!CheckCurrentProgramForUniform(location, "glUniform1iv")) {
[email protected]3916c97e2010-02-25 03:20:502791 return;
2792 }
2793 current_program_->SetSamplers(location, count, value);
2794 glUniform1iv(location, count, value);
2795}
2796
[email protected]939e7362010-05-13 20:49:102797void GLES2DecoderImpl::DoUniform1fv(
2798 GLint location, GLsizei count, const GLfloat* value) {
2799 GLenum type;
2800 if (!GetUniformTypeByLocation(location, "glUniform1fv", &type)) {
2801 return;
2802 }
2803 if (type == GL_BOOL) {
2804 scoped_array<GLint> temp(new GLint[count]);
2805 for (GLsizei ii = 0; ii < count; ++ii) {
2806 temp[ii] = static_cast<GLint>(value[ii]);
2807 }
2808 DoUniform1iv(location, count, temp.get());
2809 } else {
2810 glUniform1fv(location, count, value);
2811 }
2812}
2813
2814void GLES2DecoderImpl::DoUniform2fv(
2815 GLint location, GLsizei count, const GLfloat* value) {
2816 GLenum type;
2817 if (!GetUniformTypeByLocation(location, "glUniform2fv", &type)) {
2818 return;
2819 }
2820 if (type == GL_BOOL_VEC2) {
2821 GLsizei num_values = count * 2;
2822 scoped_array<GLint> temp(new GLint[num_values]);
2823 for (GLsizei ii = 0; ii < num_values; ++ii) {
2824 temp[ii] = static_cast<GLint>(value[ii]);
2825 }
2826 glUniform2iv(location, count, temp.get());
2827 } else {
2828 glUniform2fv(location, count, value);
2829 }
2830}
2831
2832void GLES2DecoderImpl::DoUniform3fv(
2833 GLint location, GLsizei count, const GLfloat* value) {
2834 GLenum type;
2835 if (!GetUniformTypeByLocation(location, "glUniform3fv", &type)) {
2836 return;
2837 }
2838 if (type == GL_BOOL_VEC3) {
2839 GLsizei num_values = count * 3;
2840 scoped_array<GLint> temp(new GLint[num_values]);
2841 for (GLsizei ii = 0; ii < num_values; ++ii) {
2842 temp[ii] = static_cast<GLint>(value[ii]);
2843 }
2844 glUniform3iv(location, count, temp.get());
2845 } else {
2846 glUniform3fv(location, count, value);
2847 }
2848}
2849
2850void GLES2DecoderImpl::DoUniform4fv(
2851 GLint location, GLsizei count, const GLfloat* value) {
2852 GLenum type;
2853 if (!GetUniformTypeByLocation(location, "glUniform4fv", &type)) {
2854 return;
2855 }
2856 if (type == GL_BOOL_VEC4) {
2857 GLsizei num_values = count * 4;
2858 scoped_array<GLint> temp(new GLint[num_values]);
2859 for (GLsizei ii = 0; ii < num_values; ++ii) {
2860 temp[ii] = static_cast<GLint>(value[ii]);
2861 }
2862 glUniform4iv(location, count, temp.get());
2863 } else {
2864 glUniform4fv(location, count, value);
2865 }
2866}
2867
[email protected]3916c97e2010-02-25 03:20:502868void GLES2DecoderImpl::DoUseProgram(GLuint program) {
[email protected]ae51d192010-04-27 00:48:032869 GLuint service_id = 0;
[email protected]3916c97e2010-02-25 03:20:502870 ProgramManager::ProgramInfo* info = NULL;
2871 if (program) {
[email protected]6b8cf1a2010-05-06 16:13:582872 info = GetProgramInfoNotShader(program, "glUseProgram");
[email protected]3916c97e2010-02-25 03:20:502873 if (!info) {
[email protected]ae51d192010-04-27 00:48:032874 return;
2875 }
2876 if (!info->IsValid()) {
[email protected]3916c97e2010-02-25 03:20:502877 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]8eee29c2010-04-29 03:38:292878 SetGLError(GL_INVALID_OPERATION, "glUseProgram: program not linked");
[email protected]3916c97e2010-02-25 03:20:502879 return;
2880 }
[email protected]ae51d192010-04-27 00:48:032881 service_id = info->service_id();
[email protected]3916c97e2010-02-25 03:20:502882 }
2883 current_program_ = info;
[email protected]ae51d192010-04-27 00:48:032884 glUseProgram(service_id);
[email protected]3916c97e2010-02-25 03:20:502885}
2886
[email protected]96449d2c2009-11-25 00:01:322887GLenum GLES2DecoderImpl::GetGLError() {
2888 // Check the GL error first, then our wrapped error.
2889 GLenum error = glGetError();
2890 if (error == GL_NO_ERROR && error_bits_ != 0) {
[email protected]03f882a2010-01-08 20:46:372891 for (uint32 mask = 1; mask != 0; mask = mask << 1) {
[email protected]96449d2c2009-11-25 00:01:322892 if ((error_bits_ & mask) != 0) {
[email protected]ddd968b82010-03-02 00:44:292893 error = GLES2Util::GLErrorBitToGLError(mask);
[email protected]96449d2c2009-11-25 00:01:322894 break;
2895 }
2896 }
2897 }
2898
2899 if (error != GL_NO_ERROR) {
2900 // There was an error, clear the corresponding wrapped error.
[email protected]ddd968b82010-03-02 00:44:292901 error_bits_ &= ~GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:322902 }
2903 return error;
2904}
2905
[email protected]8eee29c2010-04-29 03:38:292906void GLES2DecoderImpl::SetGLError(GLenum error, const char* msg) {
2907 if (msg) {
2908 last_error_ = msg;
2909 DLOG(ERROR) << last_error_;
2910 }
[email protected]ddd968b82010-03-02 00:44:292911 error_bits_ |= GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:322912}
2913
[email protected]07f54fcc2009-12-22 02:46:302914void GLES2DecoderImpl::CopyRealGLErrorsToWrapper() {
2915 GLenum error;
2916 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]8eee29c2010-04-29 03:38:292917 SetGLError(error, NULL);
[email protected]07f54fcc2009-12-22 02:46:302918 }
2919}
2920
[email protected]6217d392010-03-25 22:08:352921void GLES2DecoderImpl::ClearRealGLErrors() {
2922 GLenum error;
2923 while ((error = glGetError()) != GL_NO_ERROR) {
2924 NOTREACHED() << "GL error " << error << " was unhandled.";
2925 }
2926}
2927
[email protected]ef526492010-06-02 23:12:252928bool GLES2DecoderImpl::SetBlackTextureForNonRenderableTextures() {
[email protected]3916c97e2010-02-25 03:20:502929 DCHECK(current_program_);
2930 DCHECK(!current_program_->IsDeleted());
[email protected]ef526492010-06-02 23:12:252931 // Only check if there are some unrenderable textures.
2932 if (!texture_manager()->HaveUnrenderableTextures()) {
2933 return false;
2934 }
2935 bool textures_set = false;
[email protected]3916c97e2010-02-25 03:20:502936 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
2937 current_program_->sampler_indices();
2938 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
2939 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
2940 current_program_->GetUniformInfo(sampler_indices[ii]);
2941 DCHECK(uniform_info);
2942 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
2943 GLuint texture_unit_index = uniform_info->texture_units[jj];
2944 if (texture_unit_index < group_->max_texture_units()) {
2945 TextureUnit& texture_unit = texture_units_[texture_unit_index];
2946 TextureManager::TextureInfo* texture_info =
2947 uniform_info->type == GL_SAMPLER_2D ?
2948 texture_unit.bound_texture_2d :
2949 texture_unit.bound_texture_cube_map;
2950 if (!texture_info || !texture_info->CanRender()) {
[email protected]ef526492010-06-02 23:12:252951 textures_set = true;
[email protected]3916c97e2010-02-25 03:20:502952 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
2953 glBindTexture(
2954 uniform_info->type == GL_SAMPLER_2D ? GL_TEXTURE_2D :
2955 GL_TEXTURE_CUBE_MAP,
2956 uniform_info->type == GL_SAMPLER_2D ? black_2d_texture_id_ :
2957 black_cube_texture_id_);
2958 }
2959 }
2960 // else: should this be an error?
2961 }
2962 }
[email protected]ef526492010-06-02 23:12:252963 return textures_set;
[email protected]3916c97e2010-02-25 03:20:502964}
2965
2966void GLES2DecoderImpl::RestoreStateForNonRenderableTextures() {
2967 DCHECK(current_program_);
2968 DCHECK(!current_program_->IsDeleted());
2969 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
2970 current_program_->sampler_indices();
2971 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
2972 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
2973 current_program_->GetUniformInfo(sampler_indices[ii]);
2974 DCHECK(uniform_info);
2975 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
2976 GLuint texture_unit_index = uniform_info->texture_units[jj];
2977 if (texture_unit_index < group_->max_texture_units()) {
2978 TextureUnit& texture_unit = texture_units_[texture_unit_index];
2979 TextureManager::TextureInfo* texture_info =
2980 uniform_info->type == GL_SAMPLER_2D ?
2981 texture_unit.bound_texture_2d :
2982 texture_unit.bound_texture_cube_map;
2983 if (!texture_info || !texture_info->CanRender()) {
2984 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
2985 // Get the texture info that was previously bound here.
2986 texture_info = texture_unit.bind_target == GL_TEXTURE_2D ?
2987 texture_unit.bound_texture_2d :
2988 texture_unit.bound_texture_cube_map;
2989 glBindTexture(texture_unit.bind_target,
[email protected]ae51d192010-04-27 00:48:032990 texture_info ? texture_info->service_id() : 0);
[email protected]3916c97e2010-02-25 03:20:502991 }
2992 }
2993 }
2994 }
2995 // Set the active texture back to whatever the user had it as.
2996 glActiveTexture(GL_TEXTURE0 + active_texture_unit_);
[email protected]07f54fcc2009-12-22 02:46:302997}
2998
2999bool GLES2DecoderImpl::IsDrawValid(GLuint max_vertex_accessed) {
[email protected]939e7362010-05-13 20:49:103000 if (!current_program_ || current_program_->IsDeleted() ||
3001 !current_program_->IsValid()) {
[email protected]3916c97e2010-02-25 03:20:503002 // The program does not exist.
3003 // But GL says no ERROR.
3004 return false;
3005 }
[email protected]f39f4b3f2010-05-12 17:04:083006 // Validate all attribs currently enabled. If they are used by the current
3007 // program then check that they have enough elements to handle the draw call.
3008 // If they are not used by the current program check that they have a buffer
3009 // assigned.
3010 const VertexAttribManager::VertexAttribInfoList& infos =
3011 vertex_attrib_manager_.GetEnabledVertexAttribInfos();
3012 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
3013 infos.begin(); it != infos.end(); ++it) {
3014 const VertexAttribManager::VertexAttribInfo* info = *it;
3015 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
3016 current_program_->GetAttribInfoByLocation(info->index());
3017 if (attrib_info) {
3018 // This attrib is used in the current program.
3019 if (!info->CanAccess(max_vertex_accessed)) {
3020 SetGLError(GL_INVALID_OPERATION,
3021 "glDrawXXX: attempt to access out of range vertices");
3022 return false;
3023 }
3024 } else {
3025 // This attrib is not used in the current program.
3026 if (!info->buffer() || info->buffer()->IsDeleted()) {
3027 SetGLError(
3028 GL_INVALID_OPERATION,
3029 "glDrawXXX: attempt to render with no buffer attached to enabled "
3030 "attrib");
3031 return false;
3032 }
[email protected]1d32bc82010-01-13 22:06:463033 }
[email protected]07f54fcc2009-12-22 02:46:303034 }
[email protected]3916c97e2010-02-25 03:20:503035 return true;
[email protected]b1122982010-05-17 23:04:243036}
3037
3038bool GLES2DecoderImpl::SimulateAttrib0(GLuint max_vertex_accessed) {
3039#if !defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
3040 const VertexAttribManager::VertexAttribInfo* info =
3041 vertex_attrib_manager_.GetVertexAttribInfo(0);
3042 // If it's enabled or it's not used then we don't need to do anything.
3043 if (info->enabled() || !current_program_->GetAttribInfoByLocation(0)) {
3044 return false;
3045 }
3046
3047 typedef VertexAttribManager::VertexAttribInfo::Vec4 Vec4;
3048
3049 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
3050
3051 // Make a buffer with a single repeated vec4 value enough to
3052 // simulate the constant value that is supposed to be here.
3053 // This is required to emulate GLES2 on GL.
3054 GLsizei num_vertices = max_vertex_accessed + 1;
3055 GLsizei size_needed = num_vertices * sizeof(Vec4); // NOLINT
3056 if (size_needed > attrib_0_size_ ||
3057 info->value().v[0] != attrib_0_value_.v[0] ||
3058 info->value().v[1] != attrib_0_value_.v[1] ||
3059 info->value().v[2] != attrib_0_value_.v[2] ||
3060 info->value().v[3] != attrib_0_value_.v[3]) {
3061 scoped_array<Vec4> temp(new Vec4[num_vertices]);
3062 for (GLsizei ii = 0; ii < num_vertices; ++ii) {
3063 temp[ii] = info->value();
3064 }
3065 glBufferData(
3066 GL_ARRAY_BUFFER,
3067 size_needed,
3068 &temp[0].v[0],
3069 GL_DYNAMIC_DRAW);
3070 attrib_0_value_ = info->value();
3071 attrib_0_size_ = size_needed;
3072 }
3073
3074 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
3075
3076 return true;
3077#else // GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2
3078 return false;
3079#endif // GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2
3080}
3081
3082void GLES2DecoderImpl::RestoreStateForSimulatedAttrib0() {
3083 const VertexAttribManager::VertexAttribInfo* info =
3084 vertex_attrib_manager_.GetVertexAttribInfo(0);
3085 const void* ptr = reinterpret_cast<const void*>(info->offset());
3086 BufferManager::BufferInfo* buffer_info = info->buffer();
3087 glBindBuffer(GL_ARRAY_BUFFER, buffer_info ? buffer_info->service_id() : 0);
3088 glVertexAttribPointer(
3089 0, info->size(), info->type(), info->normalized(), info->gl_stride(),
3090 ptr);
3091 glBindBuffer(GL_ARRAY_BUFFER,
3092 bound_array_buffer_ ? bound_array_buffer_->service_id() : 0);
3093}
[email protected]07f54fcc2009-12-22 02:46:303094
[email protected]f7a64ee2010-02-01 22:24:143095error::Error GLES2DecoderImpl::HandleDrawElements(
[email protected]b9849abf2009-11-25 19:13:193096 uint32 immediate_data_size, const gles2::DrawElements& c) {
[email protected]3916c97e2010-02-25 03:20:503097 if (!bound_element_array_buffer_ ||
3098 bound_element_array_buffer_->IsDeleted()) {
[email protected]8eee29c2010-04-29 03:38:293099 SetGLError(GL_INVALID_OPERATION,
3100 "glDrawElements: No element array buffer bound");
3101 return error::kNoError;
3102 }
3103
3104 GLenum mode = c.mode;
3105 GLsizei count = c.count;
3106 GLenum type = c.type;
3107 int32 offset = c.index_offset;
3108 if (count < 0) {
3109 SetGLError(GL_INVALID_VALUE, "glDrawElements: count < 0");
3110 return error::kNoError;
3111 }
3112 if (offset < 0) {
3113 SetGLError(GL_INVALID_VALUE, "glDrawElements: offset < 0");
3114 return error::kNoError;
3115 }
3116 if (!ValidateGLenumDrawMode(mode)) {
3117 SetGLError(GL_INVALID_ENUM, "glDrawElements: mode GL_INVALID_ENUM");
3118 return error::kNoError;
3119 }
3120 if (!ValidateGLenumIndexType(type)) {
3121 SetGLError(GL_INVALID_ENUM, "glDrawElements: type GL_INVALID_ENUM");
3122 return error::kNoError;
3123 }
3124
3125 GLuint max_vertex_accessed;
3126 if (!bound_element_array_buffer_->GetMaxValueForRange(
3127 offset, count, type, &max_vertex_accessed)) {
3128 SetGLError(GL_INVALID_OPERATION,
3129 "glDrawElements: range out of bounds for buffer");
3130 return error::kNoError;
3131 }
3132
3133 if (IsDrawValid(max_vertex_accessed)) {
[email protected]b1122982010-05-17 23:04:243134 bool simulated_attrib_0 = SimulateAttrib0(max_vertex_accessed);
[email protected]ef526492010-06-02 23:12:253135 bool textures_set = SetBlackTextureForNonRenderableTextures();
[email protected]8eee29c2010-04-29 03:38:293136 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
3137 glDrawElements(mode, count, type, indices);
[email protected]ef526492010-06-02 23:12:253138 if (textures_set) {
[email protected]8eee29c2010-04-29 03:38:293139 RestoreStateForNonRenderableTextures();
[email protected]ba3176a2009-12-16 18:19:463140 }
[email protected]b1122982010-05-17 23:04:243141 if (simulated_attrib_0) {
3142 RestoreStateForSimulatedAttrib0();
3143 }
[email protected]96449d2c2009-11-25 00:01:323144 }
[email protected]f7a64ee2010-02-01 22:24:143145 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323146}
3147
[email protected]29a9eb52010-04-13 09:04:233148GLuint GLES2DecoderImpl::DoGetMaxValueInBuffer(
3149 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
3150 GLuint max_vertex_accessed = 0;
3151 BufferManager::BufferInfo* info = GetBufferInfo(buffer_id);
[email protected]8eee29c2010-04-29 03:38:293152 if (!info) {
[email protected]ae51d192010-04-27 00:48:033153 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]8eee29c2010-04-29 03:38:293154 SetGLError(GL_INVALID_VALUE,
3155 "GetMaxValueInBuffer: unknown buffer");
[email protected]29a9eb52010-04-13 09:04:233156 } else {
3157 if (!info->GetMaxValueForRange(offset, count, type, &max_vertex_accessed)) {
[email protected]ae51d192010-04-27 00:48:033158 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]8eee29c2010-04-29 03:38:293159 SetGLError(GL_INVALID_OPERATION,
3160 "GetMaxValueInBuffer: range out of bounds for buffer");
[email protected]29a9eb52010-04-13 09:04:233161 }
3162 }
3163 return max_vertex_accessed;
3164}
3165
[email protected]96449d2c2009-11-25 00:01:323166// Calls glShaderSource for the various versions of the ShaderSource command.
3167// Assumes that data / data_size points to a piece of memory that is in range
3168// of whatever context it came from (shared memory, immediate memory, bucket
3169// memory.)
[email protected]45bf5152010-02-12 00:11:313170error::Error GLES2DecoderImpl::ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:033171 GLuint client_id, const char* data, uint32 data_size) {
[email protected]6b8cf1a2010-05-06 16:13:583172 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
3173 client_id, "glShaderSource");
[email protected]45bf5152010-02-12 00:11:313174 if (!info) {
[email protected]45bf5152010-02-12 00:11:313175 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323176 }
[email protected]45bf5152010-02-12 00:11:313177 // Note: We don't actually call glShaderSource here. We wait until
3178 // the call to glCompileShader.
3179 info->Update(std::string(data, data + data_size));
[email protected]f7a64ee2010-02-01 22:24:143180 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323181}
3182
[email protected]f7a64ee2010-02-01 22:24:143183error::Error GLES2DecoderImpl::HandleShaderSource(
[email protected]b9849abf2009-11-25 19:13:193184 uint32 immediate_data_size, const gles2::ShaderSource& c) {
[email protected]96449d2c2009-11-25 00:01:323185 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:313186 const char* data = GetSharedMemoryAs<const char*>(
[email protected]96449d2c2009-11-25 00:01:323187 c.data_shm_id, c.data_shm_offset, data_size);
[email protected]ba3176a2009-12-16 18:19:463188 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:143189 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:323190 }
[email protected]ae51d192010-04-27 00:48:033191 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]96449d2c2009-11-25 00:01:323192}
3193
[email protected]f7a64ee2010-02-01 22:24:143194error::Error GLES2DecoderImpl::HandleShaderSourceImmediate(
[email protected]b9849abf2009-11-25 19:13:193195 uint32 immediate_data_size, const gles2::ShaderSourceImmediate& c) {
[email protected]96449d2c2009-11-25 00:01:323196 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:313197 const char* data = GetImmediateDataAs<const char*>(
[email protected]07f54fcc2009-12-22 02:46:303198 c, data_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:463199 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:143200 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:323201 }
[email protected]ae51d192010-04-27 00:48:033202 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]45bf5152010-02-12 00:11:313203}
3204
[email protected]558847a2010-03-24 07:02:543205error::Error GLES2DecoderImpl::HandleShaderSourceBucket(
3206 uint32 immediate_data_size, const gles2::ShaderSourceBucket& c) {
[email protected]558847a2010-03-24 07:02:543207 Bucket* bucket = GetBucket(c.data_bucket_id);
3208 if (!bucket || bucket->size() == 0) {
3209 return error::kInvalidArguments;
3210 }
3211 return ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:033212 c.shader, bucket->GetDataAs<const char*>(0, bucket->size() - 1),
[email protected]558847a2010-03-24 07:02:543213 bucket->size() - 1);
3214}
3215
[email protected]ae51d192010-04-27 00:48:033216void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
[email protected]6b8cf1a2010-05-06 16:13:583217 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
3218 client_id, "glCompileShader");
[email protected]45bf5152010-02-12 00:11:313219 if (!info) {
[email protected]45bf5152010-02-12 00:11:313220 return;
3221 }
[email protected]de17df392010-04-23 21:09:413222 // Translate GL ES 2.0 shader to Desktop GL shader and pass that to
3223 // glShaderSource and then glCompileShader.
3224 const char* shader_src = info->source().c_str();
[email protected]bc10076c2010-05-14 19:14:063225#if !defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2) && !defined(UNIT_TEST)
[email protected]de17df392010-04-23 21:09:413226#if defined(GLES2_GPU_SERVICE_TRANSLATE_SHADER)
[email protected]8f1ccdac2010-05-19 21:01:483227 ShHandle compiler = 0;
[email protected]b1d2dcb2010-05-17 19:24:183228 if (use_shader_translator_) {
3229 int dbg_options = 0;
3230 EShLanguage language = info->shader_type() == GL_VERTEX_SHADER ?
3231 EShLangVertex : EShLangFragment;
3232 TBuiltInResource resources;
[email protected]b1d2dcb2010-05-17 19:24:183233 resources.maxVertexAttribs = group_->max_vertex_attribs();
[email protected]8f1ccdac2010-05-19 21:01:483234 resources.maxVertexUniformVectors =
3235 group_->max_vertex_uniform_vectors();
3236 resources.maxVaryingVectors = group_->max_varying_vectors();
3237 resources.maxVertexTextureImageUnits =
3238 group_->max_vertex_texture_image_units();
[email protected]b1d2dcb2010-05-17 19:24:183239 resources.maxCombinedTextureImageUnits = group_->max_texture_units();
[email protected]8f1ccdac2010-05-19 21:01:483240 resources.maxTextureImageUnits = group_->max_texture_image_units();
3241 resources.maxFragmentUniformVectors =
3242 group_->max_fragment_uniform_vectors();
[email protected]b1d2dcb2010-05-17 19:24:183243 resources.maxDrawBuffers = 1;
3244 compiler = ShConstructCompiler(language, dbg_options);
3245 if (!ShCompile(compiler, &shader_src, 1, EShOptNone, &resources,
3246 dbg_options)) {
[email protected]8f1ccdac2010-05-19 21:01:483247 info->SetTranslationStatus(false, ShGetInfoLog(compiler));
[email protected]b1d2dcb2010-05-17 19:24:183248 ShDestruct(compiler);
3249 return;
3250 }
[email protected]8f1ccdac2010-05-19 21:01:483251 info->SetTranslationStatus(true, "");
[email protected]b1d2dcb2010-05-17 19:24:183252 shader_src = ShGetObjectCode(compiler);
[email protected]de17df392010-04-23 21:09:413253 }
[email protected]de17df392010-04-23 21:09:413254#endif // GLES2_GPU_SERVICE_TRANSLATE_SHADER
3255#endif // GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2
3256
[email protected]ae51d192010-04-27 00:48:033257 glShaderSource(info->service_id(), 1, &shader_src, NULL);
3258 glCompileShader(info->service_id());
[email protected]bc10076c2010-05-14 19:14:063259#if !defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2) && !defined(UNIT_TEST)
[email protected]de17df392010-04-23 21:09:413260#ifdef GLES2_GPU_SERVICE_TRANSLATE_SHADER
[email protected]b1d2dcb2010-05-17 19:24:183261 if (use_shader_translator_) {
3262 ShDestruct(compiler);
3263 }
[email protected]de17df392010-04-23 21:09:413264#endif // GLES2_GPU_SERVICE_TRANSLATE_SHADER
3265#endif // GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2
[email protected]45bf5152010-02-12 00:11:313266};
3267
[email protected]ddd968b82010-03-02 00:44:293268void GLES2DecoderImpl::DoGetShaderiv(
3269 GLuint shader, GLenum pname, GLint* params) {
[email protected]6b8cf1a2010-05-06 16:13:583270 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
3271 shader, "glGetShaderiv");
[email protected]ddd968b82010-03-02 00:44:293272 if (!info) {
[email protected]ddd968b82010-03-02 00:44:293273 return;
3274 }
[email protected]8f1ccdac2010-05-19 21:01:483275 switch (pname) {
3276 case GL_SHADER_SOURCE_LENGTH:
3277 *params = info->source().size();
3278 return;
3279 case GL_COMPILE_STATUS:
3280 if (!info->translation_valid()) {
3281 *params = GL_FALSE;
3282 return;
3283 }
3284 break;
3285 case GL_INFO_LOG_LENGTH:
3286 if (!info->translation_valid()) {
3287 *params = info->translation_log().size() + 1;
3288 return;
3289 }
3290 break;
3291 default:
3292 break;
[email protected]ddd968b82010-03-02 00:44:293293 }
[email protected]8f1ccdac2010-05-19 21:01:483294 glGetShaderiv(info->service_id(), pname, params);
[email protected]ddd968b82010-03-02 00:44:293295}
3296
[email protected]ae51d192010-04-27 00:48:033297error::Error GLES2DecoderImpl::HandleGetShaderSource(
3298 uint32 immediate_data_size, const gles2::GetShaderSource& c) {
3299 GLuint shader = c.shader;
[email protected]ae51d192010-04-27 00:48:033300 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
3301 Bucket* bucket = CreateBucket(bucket_id);
[email protected]6b8cf1a2010-05-06 16:13:583302 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
3303 shader, "glGetShaderSource");
[email protected]8eee29c2010-04-29 03:38:293304 if (!info) {
3305 bucket->SetSize(0);
[email protected]8eee29c2010-04-29 03:38:293306 return error::kNoError;
3307 }
[email protected]ae51d192010-04-27 00:48:033308 bucket->SetFromString(info->source());
3309 return error::kNoError;
3310}
3311
3312error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
3313 uint32 immediate_data_size, const gles2::GetProgramInfoLog& c) {
3314 GLuint program = c.program;
[email protected]6b8cf1a2010-05-06 16:13:583315 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
3316 Bucket* bucket = CreateBucket(bucket_id);
3317 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3318 program, "glGetProgramInfoLog");
[email protected]ae51d192010-04-27 00:48:033319 if (!info) {
[email protected]ae51d192010-04-27 00:48:033320 return error::kNoError;
[email protected]45bf5152010-02-12 00:11:313321 }
[email protected]ae51d192010-04-27 00:48:033322 GLint len = 0;
3323 glGetProgramiv(info->service_id(), GL_INFO_LOG_LENGTH, &len);
[email protected]8f1ccdac2010-05-19 21:01:483324 bucket->SetSize(len);
[email protected]ae51d192010-04-27 00:48:033325 glGetProgramInfoLog(
3326 info->service_id(),
[email protected]8f1ccdac2010-05-19 21:01:483327 len, &len, bucket->GetDataAs<GLchar*>(0, len));
[email protected]ae51d192010-04-27 00:48:033328 return error::kNoError;
3329}
3330
3331error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
3332 uint32 immediate_data_size, const gles2::GetShaderInfoLog& c) {
3333 GLuint shader = c.shader;
[email protected]6b8cf1a2010-05-06 16:13:583334 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
3335 Bucket* bucket = CreateBucket(bucket_id);
3336 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
3337 shader, "glGetShaderInfoLog");
[email protected]ae51d192010-04-27 00:48:033338 if (!info) {
[email protected]6b8cf1a2010-05-06 16:13:583339 bucket->SetSize(0);
[email protected]ae51d192010-04-27 00:48:033340 return error::kNoError;
3341 }
[email protected]8f1ccdac2010-05-19 21:01:483342 if (!info->translation_valid()) {
3343 bucket->SetFromString(info->translation_log());
3344 } else {
3345 GLint len = 0;
3346 glGetShaderiv(info->service_id(), GL_INFO_LOG_LENGTH, &len);
3347 bucket->SetSize(len);
3348 glGetShaderInfoLog(
3349 info->service_id(),
3350 len, &len, bucket->GetDataAs<GLchar*>(0, len));
3351 }
[email protected]ae51d192010-04-27 00:48:033352 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323353}
3354
[email protected]1958e0e2010-04-22 05:17:153355bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:033356 return GetBufferInfo(client_id) != NULL;
[email protected]1958e0e2010-04-22 05:17:153357}
3358
3359bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:033360 return GetFramebufferInfo(client_id) != NULL;
[email protected]1958e0e2010-04-22 05:17:153361}
3362
3363bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:033364 return GetProgramInfo(client_id) != NULL;
[email protected]1958e0e2010-04-22 05:17:153365}
3366
3367bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:033368 return GetRenderbufferInfo(client_id) != NULL;
[email protected]1958e0e2010-04-22 05:17:153369}
3370
3371bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:033372 return GetShaderInfo(client_id) != NULL;
[email protected]1958e0e2010-04-22 05:17:153373}
3374
3375bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:033376 return GetTextureInfo(client_id) != NULL;
3377}
3378
3379void GLES2DecoderImpl::DoAttachShader(
3380 GLuint program_client_id, GLint shader_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:583381 ProgramManager::ProgramInfo* program_info = GetProgramInfoNotShader(
3382 program_client_id, "glAttachShader");
[email protected]ae51d192010-04-27 00:48:033383 if (!program_info) {
[email protected]ae51d192010-04-27 00:48:033384 return;
[email protected]1958e0e2010-04-22 05:17:153385 }
[email protected]6b8cf1a2010-05-06 16:13:583386 ShaderManager::ShaderInfo* shader_info = GetShaderInfoNotProgram(
3387 shader_client_id, "glAttachShader");
[email protected]ae51d192010-04-27 00:48:033388 if (!shader_info) {
[email protected]ae51d192010-04-27 00:48:033389 return;
3390 }
3391 glAttachShader(program_info->service_id(), shader_info->service_id());
3392}
3393
3394void GLES2DecoderImpl::DoDetachShader(
3395 GLuint program_client_id, GLint shader_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:583396 ProgramManager::ProgramInfo* program_info = GetProgramInfoNotShader(
3397 program_client_id, "glDetachShader");
[email protected]ae51d192010-04-27 00:48:033398 if (!program_info) {
[email protected]ae51d192010-04-27 00:48:033399 return;
3400 }
[email protected]6b8cf1a2010-05-06 16:13:583401 ShaderManager::ShaderInfo* shader_info = GetShaderInfoNotProgram(
3402 shader_client_id, "glDetachShader");
[email protected]ae51d192010-04-27 00:48:033403 if (!shader_info) {
[email protected]ae51d192010-04-27 00:48:033404 return;
3405 }
3406 glDetachShader(program_info->service_id(), shader_info->service_id());
3407}
3408
3409void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:583410 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3411 program_client_id, "glValidateProgram");
[email protected]ae51d192010-04-27 00:48:033412 if (!info) {
[email protected]ae51d192010-04-27 00:48:033413 return;
3414 }
3415 glValidateProgram(info->service_id());
[email protected]1958e0e2010-04-22 05:17:153416}
3417
[email protected]b1122982010-05-17 23:04:243418void GLES2DecoderImpl::DoGetVertexAttribfv(
3419 GLuint index, GLenum pname, GLfloat* params) {
3420 VertexAttribManager::VertexAttribInfo* info =
3421 vertex_attrib_manager_.GetVertexAttribInfo(index);
3422 if (!info) {
3423 SetGLError(GL_INVALID_VALUE, "glGetVertexAttribfv: index out of range");
3424 return;
3425 }
3426 switch (pname) {
3427 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
3428 BufferManager::BufferInfo* buffer = info->buffer();
3429 if (buffer && !buffer->IsDeleted()) {
3430 GLuint client_id;
3431 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
3432 *params = static_cast<GLfloat>(client_id);
3433 }
3434 break;
3435 }
3436 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
3437 *params = static_cast<GLfloat>(info->enabled());
3438 break;
3439 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
3440 *params = static_cast<GLfloat>(info->size());
3441 break;
3442 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
3443 *params = static_cast<GLfloat>(info->gl_stride());
3444 break;
3445 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
3446 *params = static_cast<GLfloat>(info->type());
3447 break;
3448 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
3449 *params = static_cast<GLfloat>(info->normalized());
3450 break;
3451 case GL_CURRENT_VERTEX_ATTRIB:
3452 params[0] = info->value().v[0];
3453 params[1] = info->value().v[1];
3454 params[2] = info->value().v[2];
3455 params[3] = info->value().v[3];
3456 break;
3457 default:
3458 NOTREACHED();
3459 break;
3460 }
3461}
3462
3463void GLES2DecoderImpl::DoGetVertexAttribiv(
3464 GLuint index, GLenum pname, GLint* params) {
3465 VertexAttribManager::VertexAttribInfo* info =
3466 vertex_attrib_manager_.GetVertexAttribInfo(index);
3467 if (!info) {
3468 SetGLError(GL_INVALID_VALUE, "glGetVertexAttribiv: index out of range");
3469 return;
3470 }
3471 switch (pname) {
3472 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
3473 BufferManager::BufferInfo* buffer = info->buffer();
3474 if (buffer && !buffer->IsDeleted()) {
3475 GLuint client_id;
3476 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
3477 *params = client_id;
3478 }
3479 break;
3480 }
3481 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
3482 *params = info->enabled();
3483 break;
3484 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
3485 *params = info->size();
3486 break;
3487 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
3488 *params = info->gl_stride();
3489 break;
3490 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
3491 *params = info->type();
3492 break;
3493 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
3494 *params = static_cast<GLint>(info->normalized());
3495 break;
3496 case GL_CURRENT_VERTEX_ATTRIB:
3497 params[0] = static_cast<GLint>(info->value().v[0]);
3498 params[1] = static_cast<GLint>(info->value().v[1]);
3499 params[2] = static_cast<GLint>(info->value().v[2]);
3500 params[3] = static_cast<GLint>(info->value().v[3]);
3501 break;
3502 default:
3503 NOTREACHED();
3504 break;
3505 }
3506}
3507
3508void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
3509 VertexAttribManager::VertexAttribInfo* info =
3510 vertex_attrib_manager_.GetVertexAttribInfo(index);
3511 if (!info) {
3512 SetGLError(GL_INVALID_VALUE, "glVertexAttrib1f: index out of range");
3513 return;
3514 }
3515 VertexAttribManager::VertexAttribInfo::Vec4 value;
3516 value.v[0] = v0;
3517 value.v[1] = 0.0f;
3518 value.v[2] = 0.0f;
3519 value.v[3] = 1.0f;
3520 info->set_value(value);
3521 glVertexAttrib1f(index, v0);
3522}
3523
3524void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
3525 VertexAttribManager::VertexAttribInfo* info =
3526 vertex_attrib_manager_.GetVertexAttribInfo(index);
3527 if (!info) {
3528 SetGLError(GL_INVALID_VALUE, "glVertexAttrib2f: index out of range");
3529 return;
3530 }
3531 VertexAttribManager::VertexAttribInfo::Vec4 value;
3532 value.v[0] = v0;
3533 value.v[1] = v1;
3534 value.v[2] = 0.0f;
3535 value.v[3] = 1.0f;
3536 info->set_value(value);
3537 glVertexAttrib2f(index, v0, v1);
3538}
3539
3540void GLES2DecoderImpl::DoVertexAttrib3f(
3541 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
3542 VertexAttribManager::VertexAttribInfo* info =
3543 vertex_attrib_manager_.GetVertexAttribInfo(index);
3544 if (!info) {
3545 SetGLError(GL_INVALID_VALUE, "glVertexAttrib3f: index out of range");
3546 return;
3547 }
3548 VertexAttribManager::VertexAttribInfo::Vec4 value;
3549 value.v[0] = v0;
3550 value.v[1] = v1;
3551 value.v[2] = v2;
3552 value.v[3] = 1.0f;
3553 info->set_value(value);
3554 glVertexAttrib3f(index, v0, v1, v2);
3555}
3556
3557void GLES2DecoderImpl::DoVertexAttrib4f(
3558 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
3559 VertexAttribManager::VertexAttribInfo* info =
3560 vertex_attrib_manager_.GetVertexAttribInfo(index);
3561 if (!info) {
3562 SetGLError(GL_INVALID_VALUE, "glVertexAttrib4f: index out of range");
3563 return;
3564 }
3565 VertexAttribManager::VertexAttribInfo::Vec4 value;
3566 value.v[0] = v0;
3567 value.v[1] = v1;
3568 value.v[2] = v2;
3569 value.v[3] = v3;
3570 info->set_value(value);
3571 glVertexAttrib4f(index, v0, v1, v2, v3);
3572}
3573
3574void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
3575 VertexAttribManager::VertexAttribInfo* info =
3576 vertex_attrib_manager_.GetVertexAttribInfo(index);
3577 if (!info) {
3578 SetGLError(GL_INVALID_VALUE, "glVertexAttrib1fv: index out of range");
3579 return;
3580 }
3581 VertexAttribManager::VertexAttribInfo::Vec4 value;
3582 value.v[0] = v[0];
3583 value.v[1] = 0.0f;
3584 value.v[2] = 0.0f;
3585 value.v[3] = 1.0f;
3586 info->set_value(value);
3587 glVertexAttrib1fv(index, v);
3588}
3589
3590void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
3591 VertexAttribManager::VertexAttribInfo* info =
3592 vertex_attrib_manager_.GetVertexAttribInfo(index);
3593 if (!info) {
3594 SetGLError(GL_INVALID_VALUE, "glVertexAttrib2fv: index out of range");
3595 return;
3596 }
3597 VertexAttribManager::VertexAttribInfo::Vec4 value;
3598 value.v[0] = v[0];
3599 value.v[1] = v[1];
3600 value.v[2] = 0.0f;
3601 value.v[3] = 1.0f;
3602 info->set_value(value);
3603 glVertexAttrib2fv(index, v);
3604}
3605
3606void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
3607 VertexAttribManager::VertexAttribInfo* info =
3608 vertex_attrib_manager_.GetVertexAttribInfo(index);
3609 if (!info) {
3610 SetGLError(GL_INVALID_VALUE, "glVertexAttrib3fv: index out of range");
3611 return;
3612 }
3613 VertexAttribManager::VertexAttribInfo::Vec4 value;
3614 value.v[0] = v[0];
3615 value.v[1] = v[1];
3616 value.v[2] = v[2];
3617 value.v[3] = 1.0f;
3618 info->set_value(value);
3619 glVertexAttrib3fv(index, v);
3620}
3621
3622void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
3623 VertexAttribManager::VertexAttribInfo* info =
3624 vertex_attrib_manager_.GetVertexAttribInfo(index);
3625 if (!info) {
3626 SetGLError(GL_INVALID_VALUE, "glVertexAttrib4fv: index out of range");
3627 return;
3628 }
3629 VertexAttribManager::VertexAttribInfo::Vec4 value;
3630 value.v[0] = v[0];
3631 value.v[1] = v[1];
3632 value.v[2] = v[2];
3633 value.v[3] = v[3];
3634 info->set_value(value);
3635 glVertexAttrib4fv(index, v);
3636}
3637
[email protected]f7a64ee2010-02-01 22:24:143638error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
[email protected]b9849abf2009-11-25 19:13:193639 uint32 immediate_data_size, const gles2::VertexAttribPointer& c) {
[email protected]8eee29c2010-04-29 03:38:293640 if (!bound_array_buffer_ || bound_array_buffer_->IsDeleted()) {
3641 SetGLError(GL_INVALID_VALUE,
3642 "glVertexAttribPointer: no array buffer bound");
3643 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323644 }
[email protected]8eee29c2010-04-29 03:38:293645
3646 GLuint indx = c.indx;
3647 GLint size = c.size;
3648 GLenum type = c.type;
3649 GLboolean normalized = c.normalized;
3650 GLsizei stride = c.stride;
3651 GLsizei offset = c.offset;
3652 const void* ptr = reinterpret_cast<const void*>(offset);
3653 if (!ValidateGLenumVertexAttribType(type)) {
3654 SetGLError(GL_INVALID_ENUM,
3655 "glVertexAttribPointer: type GL_INVALID_ENUM");
3656 return error::kNoError;
3657 }
3658 if (!ValidateGLintVertexAttribSize(size)) {
3659 SetGLError(GL_INVALID_ENUM,
3660 "glVertexAttribPointer: size GL_INVALID_VALUE");
3661 return error::kNoError;
3662 }
3663 if (indx >= group_->max_vertex_attribs()) {
3664 SetGLError(GL_INVALID_VALUE, "glVertexAttribPointer: index out of range");
3665 return error::kNoError;
3666 }
3667 if (stride < 0) {
3668 SetGLError(GL_INVALID_VALUE,
3669 "glVertexAttribPointer: stride < 0");
3670 return error::kNoError;
3671 }
3672 if (stride > 255) {
3673 SetGLError(GL_INVALID_VALUE,
3674 "glVertexAttribPointer: stride > 255");
3675 return error::kNoError;
3676 }
3677 if (offset < 0) {
3678 SetGLError(GL_INVALID_VALUE,
3679 "glVertexAttribPointer: offset < 0");
3680 return error::kNoError;
3681 }
3682 GLsizei component_size =
3683 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
[email protected]8eee29c2010-04-29 03:38:293684 if (offset % component_size > 0) {
3685 SetGLError(GL_INVALID_VALUE,
3686 "glVertexAttribPointer: stride not valid for type");
3687 return error::kNoError;
3688 }
[email protected]f39f4b3f2010-05-12 17:04:083689 vertex_attrib_manager_.GetVertexAttribInfo(indx)->SetInfo(
[email protected]8eee29c2010-04-29 03:38:293690 bound_array_buffer_,
3691 size,
3692 type,
[email protected]b1122982010-05-17 23:04:243693 normalized,
3694 stride,
3695 stride != 0 ? stride : component_size * size,
[email protected]8eee29c2010-04-29 03:38:293696 offset);
3697 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
[email protected]f7a64ee2010-02-01 22:24:143698 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323699}
3700
[email protected]f7a64ee2010-02-01 22:24:143701error::Error GLES2DecoderImpl::HandleReadPixels(
[email protected]b9849abf2009-11-25 19:13:193702 uint32 immediate_data_size, const gles2::ReadPixels& c) {
[email protected]612d2f82009-12-08 20:49:313703 GLint x = c.x;
3704 GLint y = c.y;
3705 GLsizei width = c.width;
3706 GLsizei height = c.height;
3707 GLenum format = c.format;
3708 GLenum type = c.type;
[email protected]57f223832010-03-19 01:57:563709 if (width < 0 || height < 0) {
[email protected]8eee29c2010-04-29 03:38:293710 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions < 0");
[email protected]57f223832010-03-19 01:57:563711 return error::kNoError;
3712 }
[email protected]a51788e2010-02-24 21:54:253713 typedef gles2::ReadPixels::Result Result;
[email protected]a76b0052010-03-05 00:33:183714 uint32 pixels_size;
3715 if (!GLES2Util::ComputeImageDataSize(
3716 width, height, format, type, pack_alignment_, &pixels_size)) {
3717 return error::kOutOfBounds;
3718 }
[email protected]612d2f82009-12-08 20:49:313719 void* pixels = GetSharedMemoryAs<void*>(
3720 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
[email protected]a51788e2010-02-24 21:54:253721 Result* result = GetSharedMemoryAs<Result*>(
3722 c.result_shm_id, c.result_shm_offset, sizeof(*result));
3723 if (!pixels || !result) {
[email protected]f7a64ee2010-02-01 22:24:143724 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:463725 }
[email protected]a51788e2010-02-24 21:54:253726
[email protected]8eee29c2010-04-29 03:38:293727 if (!ValidateGLenumReadPixelFormat(format)) {
3728 SetGLError(GL_INVALID_ENUM, "glReadPixels: format GL_INVALID_ENUM");
3729 return error::kNoError;
3730 }
3731 if (!ValidateGLenumPixelType(type)) {
3732 SetGLError(GL_INVALID_ENUM, "glReadPixels: type GL_INVALID_ENUM");
[email protected]d2cf0a2d2010-02-25 21:36:123733 return error::kNoError;
3734 }
[email protected]57f223832010-03-19 01:57:563735 if (width == 0 || height == 0) {
3736 return error::kNoError;
3737 }
3738
3739 CopyRealGLErrorsToWrapper();
3740
3741 // Get the size of the current fbo or backbuffer.
[email protected]d37231fa2010-04-09 21:16:023742 gfx::Size max_size = GetBoundFrameBufferSize();
[email protected]57f223832010-03-19 01:57:563743
3744 GLint max_x;
3745 GLint max_y;
3746 if (!SafeAdd(x, width, &max_x) || !SafeAdd(y, height, &max_y)) {
[email protected]8eee29c2010-04-29 03:38:293747 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]f7a64ee2010-02-01 22:24:143748 return error::kNoError;
[email protected]612d2f82009-12-08 20:49:313749 }
[email protected]57f223832010-03-19 01:57:563750
[email protected]d37231fa2010-04-09 21:16:023751 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
[email protected]57f223832010-03-19 01:57:563752 // The user requested an out of range area. Get the results 1 line
3753 // at a time.
3754 uint32 temp_size;
3755 if (!GLES2Util::ComputeImageDataSize(
3756 width, 1, format, type, pack_alignment_, &temp_size)) {
[email protected]8eee29c2010-04-29 03:38:293757 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:563758 return error::kNoError;
3759 }
3760 GLsizei unpadded_row_size = temp_size;
3761 if (!GLES2Util::ComputeImageDataSize(
3762 width, 2, format, type, pack_alignment_, &temp_size)) {
[email protected]8eee29c2010-04-29 03:38:293763 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:563764 return error::kNoError;
3765 }
3766 GLsizei padded_row_size = temp_size - unpadded_row_size;
3767 if (padded_row_size < 0 || unpadded_row_size < 0) {
[email protected]8eee29c2010-04-29 03:38:293768 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:563769 return error::kNoError;
3770 }
3771
3772 GLint dest_x_offset = std::max(-x, 0);
3773 uint32 dest_row_offset;
3774 if (!GLES2Util::ComputeImageDataSize(
3775 dest_x_offset, 1, format, type, pack_alignment_, &dest_row_offset)) {
[email protected]8eee29c2010-04-29 03:38:293776 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:563777 return error::kNoError;
3778 }
3779
3780 // Copy each row into the larger dest rect.
3781 int8* dst = static_cast<int8*>(pixels);
3782 GLint read_x = std::max(0, x);
[email protected]d37231fa2010-04-09 21:16:023783 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
[email protected]57f223832010-03-19 01:57:563784 GLint read_width = read_end_x - read_x;
3785 for (GLint yy = 0; yy < height; ++yy) {
3786 GLint ry = y + yy;
3787
3788 // Clear the row.
3789 memset(dst, 0, unpadded_row_size);
3790
3791 // If the row is in range, copy it.
[email protected]d37231fa2010-04-09 21:16:023792 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
[email protected]57f223832010-03-19 01:57:563793 glReadPixels(
3794 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
3795 }
3796 dst += padded_row_size;
3797 }
3798 } else {
3799 glReadPixels(x, y, width, height, format, type, pixels);
3800 }
[email protected]a51788e2010-02-24 21:54:253801 GLenum error = glGetError();
3802 if (error == GL_NO_ERROR) {
3803 *result = true;
3804 } else {
[email protected]8eee29c2010-04-29 03:38:293805 SetGLError(error, NULL);
[email protected]a51788e2010-02-24 21:54:253806 }
[email protected]f7a64ee2010-02-01 22:24:143807 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323808}
3809
[email protected]f7a64ee2010-02-01 22:24:143810error::Error GLES2DecoderImpl::HandlePixelStorei(
[email protected]b9849abf2009-11-25 19:13:193811 uint32 immediate_data_size, const gles2::PixelStorei& c) {
3812 GLenum pname = c.pname;
3813 GLenum param = c.param;
[email protected]d2cf0a2d2010-02-25 21:36:123814 if (!ValidateGLenumPixelStore(pname)) {
[email protected]8eee29c2010-04-29 03:38:293815 SetGLError(GL_INVALID_ENUM, "glPixelStorei: pname GL_INVALID_ENUM");
[email protected]d2cf0a2d2010-02-25 21:36:123816 return error::kNoError;
3817 }
3818 if (!ValidateGLintPixelStoreAlignment(param)) {
[email protected]8eee29c2010-04-29 03:38:293819 SetGLError(GL_INVALID_VALUE, "glPixelSTore: param GL_INVALID_VALUE");
[email protected]f7a64ee2010-02-01 22:24:143820 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:193821 }
3822 glPixelStorei(pname, param);
3823 switch (pname) {
3824 case GL_PACK_ALIGNMENT:
3825 pack_alignment_ = param;
3826 break;
3827 case GL_UNPACK_ALIGNMENT:
3828 unpack_alignment_ = param;
3829 break;
3830 default:
3831 // Validation should have prevented us from getting here.
[email protected]656dcaad2010-05-07 17:18:373832 NOTREACHED();
[email protected]b9849abf2009-11-25 19:13:193833 break;
3834 }
[email protected]f7a64ee2010-02-01 22:24:143835 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:193836}
3837
[email protected]558847a2010-03-24 07:02:543838error::Error GLES2DecoderImpl::GetAttribLocationHelper(
3839 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
3840 const std::string& name_str) {
[email protected]6b8cf1a2010-05-06 16:13:583841 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3842 client_id, "glGetAttribLocation");
[email protected]ae51d192010-04-27 00:48:033843 if (!info) {
[email protected]f7a64ee2010-02-01 22:24:143844 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:193845 }
[email protected]ae51d192010-04-27 00:48:033846 if (!info->IsValid()) {
[email protected]8eee29c2010-04-29 03:38:293847 SetGLError(GL_INVALID_OPERATION, "glGetAttribLocation: program not linked");
[email protected]0bfd9882010-02-05 23:02:253848 return error::kNoError;
3849 }
[email protected]b9849abf2009-11-25 19:13:193850 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:543851 location_shm_id, location_shm_offset, sizeof(GLint));
3852 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:143853 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:193854 }
[email protected]558847a2010-03-24 07:02:543855 // Require the client to init this incase the context is lost and we are no
3856 // longer executing commands.
3857 if (*location != -1) {
3858 return error::kGenericError;
3859 }
[email protected]0bfd9882010-02-05 23:02:253860 *location = info->GetAttribLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:143861 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:193862}
3863
[email protected]558847a2010-03-24 07:02:543864error::Error GLES2DecoderImpl::HandleGetAttribLocation(
3865 uint32 immediate_data_size, const gles2::GetAttribLocation& c) {
3866 uint32 name_size = c.data_size;
3867 const char* name = GetSharedMemoryAs<const char*>(
3868 c.name_shm_id, c.name_shm_offset, name_size);
3869 if (!name) {
3870 return error::kOutOfBounds;
3871 }
3872 String name_str(name, name_size);
3873 return GetAttribLocationHelper(
3874 c.program, c.location_shm_id, c.location_shm_offset, name_str);
3875}
3876
[email protected]f7a64ee2010-02-01 22:24:143877error::Error GLES2DecoderImpl::HandleGetAttribLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:193878 uint32 immediate_data_size, const gles2::GetAttribLocationImmediate& c) {
[email protected]558847a2010-03-24 07:02:543879 uint32 name_size = c.data_size;
3880 const char* name = GetImmediateDataAs<const char*>(
3881 c, name_size, immediate_data_size);
3882 if (!name) {
3883 return error::kOutOfBounds;
3884 }
3885 String name_str(name, name_size);
3886 return GetAttribLocationHelper(
3887 c.program, c.location_shm_id, c.location_shm_offset, name_str);
3888}
3889
3890error::Error GLES2DecoderImpl::HandleGetAttribLocationBucket(
3891 uint32 immediate_data_size, const gles2::GetAttribLocationBucket& c) {
3892 Bucket* bucket = GetBucket(c.name_bucket_id);
3893 if (!bucket) {
3894 return error::kInvalidArguments;
3895 }
3896 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:183897 if (!bucket->GetAsString(&name_str)) {
3898 return error::kInvalidArguments;
3899 }
[email protected]558847a2010-03-24 07:02:543900 return GetAttribLocationHelper(
3901 c.program, c.location_shm_id, c.location_shm_offset, name_str);
3902}
3903
3904error::Error GLES2DecoderImpl::GetUniformLocationHelper(
3905 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
3906 const std::string& name_str) {
[email protected]6b8cf1a2010-05-06 16:13:583907 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3908 client_id, "glUniformLocation");
[email protected]ae51d192010-04-27 00:48:033909 if (!info) {
[email protected]f7a64ee2010-02-01 22:24:143910 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:193911 }
[email protected]ae51d192010-04-27 00:48:033912 if (!info->IsValid()) {
[email protected]8eee29c2010-04-29 03:38:293913 SetGLError(GL_INVALID_OPERATION,
3914 "glGetUniformLocation: program not linked");
[email protected]0bfd9882010-02-05 23:02:253915 return error::kNoError;
3916 }
[email protected]b9849abf2009-11-25 19:13:193917 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:543918 location_shm_id, location_shm_offset, sizeof(GLint));
3919 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:143920 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:193921 }
[email protected]558847a2010-03-24 07:02:543922 // Require the client to init this incase the context is lost an we are no
3923 // longer executing commands.
3924 if (*location != -1) {
3925 return error::kGenericError;
3926 }
3927 *location = info->GetUniformLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:143928 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:193929}
3930
[email protected]f7a64ee2010-02-01 22:24:143931error::Error GLES2DecoderImpl::HandleGetUniformLocation(
[email protected]b9849abf2009-11-25 19:13:193932 uint32 immediate_data_size, const gles2::GetUniformLocation& c) {
[email protected]b9849abf2009-11-25 19:13:193933 uint32 name_size = c.data_size;
3934 const char* name = GetSharedMemoryAs<const char*>(
3935 c.name_shm_id, c.name_shm_offset, name_size);
[email protected]558847a2010-03-24 07:02:543936 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:143937 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:193938 }
3939 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:543940 return GetUniformLocationHelper(
3941 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:193942}
3943
[email protected]f7a64ee2010-02-01 22:24:143944error::Error GLES2DecoderImpl::HandleGetUniformLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:193945 uint32 immediate_data_size, const gles2::GetUniformLocationImmediate& c) {
[email protected]b9849abf2009-11-25 19:13:193946 uint32 name_size = c.data_size;
[email protected]07f54fcc2009-12-22 02:46:303947 const char* name = GetImmediateDataAs<const char*>(
3948 c, name_size, immediate_data_size);
[email protected]558847a2010-03-24 07:02:543949 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:143950 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:193951 }
3952 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:543953 return GetUniformLocationHelper(
3954 c.program, c.location_shm_id, c.location_shm_offset, name_str);
3955}
3956
3957error::Error GLES2DecoderImpl::HandleGetUniformLocationBucket(
3958 uint32 immediate_data_size, const gles2::GetUniformLocationBucket& c) {
3959 Bucket* bucket = GetBucket(c.name_bucket_id);
3960 if (!bucket) {
3961 return error::kInvalidArguments;
3962 }
3963 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:183964 if (!bucket->GetAsString(&name_str)) {
3965 return error::kInvalidArguments;
3966 }
[email protected]558847a2010-03-24 07:02:543967 return GetUniformLocationHelper(
3968 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:193969}
3970
[email protected]ddd968b82010-03-02 00:44:293971error::Error GLES2DecoderImpl::HandleGetString(
3972 uint32 immediate_data_size, const gles2::GetString& c) {
3973 GLenum name = static_cast<GLenum>(c.name);
3974 if (!ValidateGLenumStringType(name)) {
[email protected]8eee29c2010-04-29 03:38:293975 SetGLError(GL_INVALID_ENUM, "glGetString: name GL_INVALID_ENUM");
[email protected]ddd968b82010-03-02 00:44:293976 return error::kNoError;
3977 }
[email protected]1958e0e2010-04-22 05:17:153978 const char* gl_str = reinterpret_cast<const char*>(glGetString(name));
3979 const char* str = NULL;
3980 switch (name) {
3981 case GL_VERSION:
3982 str = "OpenGL ES 2.0 Chromium";
3983 break;
3984 case GL_SHADING_LANGUAGE_VERSION:
3985 str = "OpenGL ES GLSL ES 1.0 Chromium";
3986 break;
3987 case GL_EXTENSIONS:
3988 str = "";
3989 break;
3990 default:
3991 str = gl_str;
3992 break;
3993 }
[email protected]ddd968b82010-03-02 00:44:293994 Bucket* bucket = CreateBucket(c.bucket_id);
[email protected]1958e0e2010-04-22 05:17:153995 bucket->SetFromString(str);
[email protected]ddd968b82010-03-02 00:44:293996 return error::kNoError;
3997}
3998
[email protected]0c86dbf2010-03-05 08:14:113999void GLES2DecoderImpl::DoBufferData(
4000 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage) {
[email protected]8eee29c2010-04-29 03:38:294001 if (!ValidateGLenumBufferTarget(target)) {
4002 SetGLError(GL_INVALID_ENUM, "glBufferData: target GL_INVALID_ENUM");
4003 return;
4004 }
4005 if (!ValidateGLenumBufferUsage(usage)) {
4006 SetGLError(GL_INVALID_ENUM, "glBufferData: usage GL_INVALID_ENUM");
[email protected]0c86dbf2010-03-05 08:14:114007 return;
[email protected]3b6ec202010-03-05 05:16:234008 }
4009 if (size < 0) {
[email protected]8eee29c2010-04-29 03:38:294010 SetGLError(GL_INVALID_VALUE, "glBufferData: size < 0");
[email protected]037896bd2010-04-21 19:07:284011 return;
[email protected]3b6ec202010-03-05 05:16:234012 }
4013 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
4014 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294015 SetGLError(GL_INVALID_VALUE, "glBufferData: unknown buffer");
[email protected]037896bd2010-04-21 19:07:284016 return;
[email protected]3b6ec202010-03-05 05:16:234017 }
4018 // Clear the buffer to 0 if no initial data was passed in.
4019 scoped_array<int8> zero;
4020 if (!data) {
4021 zero.reset(new int8[size]);
4022 memset(zero.get(), 0, size);
4023 data = zero.get();
4024 }
4025 CopyRealGLErrorsToWrapper();
4026 glBufferData(target, size, data, usage);
4027 GLenum error = glGetError();
4028 if (error != GL_NO_ERROR) {
[email protected]8eee29c2010-04-29 03:38:294029 SetGLError(error, NULL);
[email protected]3b6ec202010-03-05 05:16:234030 } else {
[email protected]4e8a5b122010-05-08 22:00:104031 buffer_manager()->SetSize(info, size);
[email protected]0c86dbf2010-03-05 08:14:114032 info->SetRange(0, size, data);
[email protected]3b6ec202010-03-05 05:16:234033 }
[email protected]0c86dbf2010-03-05 08:14:114034}
4035
4036error::Error GLES2DecoderImpl::HandleBufferData(
4037 uint32 immediate_data_size, const gles2::BufferData& c) {
4038 GLenum target = static_cast<GLenum>(c.target);
4039 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
4040 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
4041 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
4042 GLenum usage = static_cast<GLenum>(c.usage);
4043 const void* data = NULL;
4044 if (data_shm_id != 0 || data_shm_offset != 0) {
4045 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
4046 if (!data) {
4047 return error::kOutOfBounds;
4048 }
4049 }
4050 DoBufferData(target, size, data, usage);
[email protected]f7a64ee2010-02-01 22:24:144051 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:194052}
4053
[email protected]f7a64ee2010-02-01 22:24:144054error::Error GLES2DecoderImpl::HandleBufferDataImmediate(
[email protected]b9849abf2009-11-25 19:13:194055 uint32 immediate_data_size, const gles2::BufferDataImmediate& c) {
4056 GLenum target = static_cast<GLenum>(c.target);
4057 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
[email protected]07f54fcc2009-12-22 02:46:304058 const void* data = GetImmediateDataAs<const void*>(
4059 c, size, immediate_data_size);
4060 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:144061 return error::kOutOfBounds;
[email protected]07f54fcc2009-12-22 02:46:304062 }
[email protected]b9849abf2009-11-25 19:13:194063 GLenum usage = static_cast<GLenum>(c.usage);
[email protected]0c86dbf2010-03-05 08:14:114064 DoBufferData(target, size, data, usage);
4065 return error::kNoError;
4066}
4067
4068void GLES2DecoderImpl::DoBufferSubData(
4069 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
[email protected]3916c97e2010-02-25 03:20:504070 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:474071 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294072 SetGLError(GL_INVALID_VALUE, "glBufferSubData: unknown buffer");
[email protected]037896bd2010-04-21 19:07:284073 return;
[email protected]a93bb842010-02-16 23:03:474074 }
[email protected]0c86dbf2010-03-05 08:14:114075 if (!info->SetRange(offset, size, data)) {
[email protected]8eee29c2010-04-29 03:38:294076 SetGLError(GL_INVALID_VALUE, "glBufferSubData: out of range");
[email protected]07f54fcc2009-12-22 02:46:304077 } else {
[email protected]0c86dbf2010-03-05 08:14:114078 glBufferSubData(target, offset, size, data);
[email protected]07f54fcc2009-12-22 02:46:304079 }
[email protected]b9849abf2009-11-25 19:13:194080}
4081
[email protected]a93bb842010-02-16 23:03:474082error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
4083 GLenum target,
4084 GLint level,
4085 GLenum internal_format,
4086 GLsizei width,
4087 GLsizei height,
4088 GLint border,
4089 GLsizei image_size,
4090 const void* data) {
[email protected]a93bb842010-02-16 23:03:474091 // TODO(gman): Validate image_size is correct for width, height and format.
[email protected]8eee29c2010-04-29 03:38:294092 if (!ValidateGLenumTextureTarget(target)) {
4093 SetGLError(GL_INVALID_ENUM,
4094 "glCompressedTexImage2D: target GL_INVALID_ENUM");
4095 return error::kNoError;
4096 }
4097 if (!ValidateGLenumCompressedTextureInternalFormat(internal_format)) {
4098 SetGLError(GL_INVALID_ENUM,
4099 "glCompressedTexImage2D: internal_format GL_INVALID_ENUM");
[email protected]a93bb842010-02-16 23:03:474100 return error::kNoError;
4101 }
[email protected]3916c97e2010-02-25 03:20:504102 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:474103 border != 0) {
[email protected]8eee29c2010-04-29 03:38:294104 SetGLError(GL_INVALID_VALUE,
4105 "glCompressedTexImage2D: dimensions out of range");
[email protected]a93bb842010-02-16 23:03:474106 return error::kNoError;
4107 }
[email protected]3916c97e2010-02-25 03:20:504108 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:474109 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294110 SetGLError(GL_INVALID_VALUE,
4111 "glCompressedTexImage2D: unknown texture target");
[email protected]a93bb842010-02-16 23:03:474112 return error::kNoError;
4113 }
4114 scoped_array<int8> zero;
4115 if (!data) {
4116 zero.reset(new int8[image_size]);
4117 memset(zero.get(), 0, image_size);
4118 data = zero.get();
4119 }
[email protected]ef526492010-06-02 23:12:254120 texture_manager()->SetLevelInfo(
4121 info, target, level, internal_format, width, height, 1, border, 0, 0);
[email protected]a93bb842010-02-16 23:03:474122 glCompressedTexImage2D(
4123 target, level, internal_format, width, height, border, image_size, data);
4124 return error::kNoError;
4125}
4126
[email protected]f7a64ee2010-02-01 22:24:144127error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:194128 uint32 immediate_data_size, const gles2::CompressedTexImage2D& c) {
4129 GLenum target = static_cast<GLenum>(c.target);
4130 GLint level = static_cast<GLint>(c.level);
4131 GLenum internal_format = static_cast<GLenum>(c.internalformat);
4132 GLsizei width = static_cast<GLsizei>(c.width);
4133 GLsizei height = static_cast<GLsizei>(c.height);
4134 GLint border = static_cast<GLint>(c.border);
4135 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
4136 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
4137 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
4138 const void* data = NULL;
4139 if (data_shm_id != 0 || data_shm_offset != 0) {
4140 data = GetSharedMemoryAs<const void*>(
4141 data_shm_id, data_shm_offset, image_size);
[email protected]ba3176a2009-12-16 18:19:464142 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:144143 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:194144 }
4145 }
[email protected]a93bb842010-02-16 23:03:474146 return DoCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:194147 target, level, internal_format, width, height, border, image_size, data);
[email protected]b9849abf2009-11-25 19:13:194148}
4149
[email protected]f7a64ee2010-02-01 22:24:144150error::Error GLES2DecoderImpl::HandleCompressedTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:194151 uint32 immediate_data_size, const gles2::CompressedTexImage2DImmediate& c) {
4152 GLenum target = static_cast<GLenum>(c.target);
4153 GLint level = static_cast<GLint>(c.level);
4154 GLenum internal_format = static_cast<GLenum>(c.internalformat);
4155 GLsizei width = static_cast<GLsizei>(c.width);
4156 GLsizei height = static_cast<GLsizei>(c.height);
4157 GLint border = static_cast<GLint>(c.border);
4158 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
[email protected]07f54fcc2009-12-22 02:46:304159 const void* data = GetImmediateDataAs<const void*>(
4160 c, image_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:464161 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:144162 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:464163 }
[email protected]a93bb842010-02-16 23:03:474164 return DoCompressedTexImage2D(
4165 target, level, internal_format, width, height, border, image_size, data);
4166}
4167
[email protected]b6140d02010-05-17 14:47:164168error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
4169 uint32 immediate_data_size, const gles2::CompressedTexImage2DBucket& c) {
4170 GLenum target = static_cast<GLenum>(c.target);
4171 GLint level = static_cast<GLint>(c.level);
4172 GLenum internal_format = static_cast<GLenum>(c.internalformat);
4173 GLsizei width = static_cast<GLsizei>(c.width);
4174 GLsizei height = static_cast<GLsizei>(c.height);
4175 GLint border = static_cast<GLint>(c.border);
4176 Bucket* bucket = GetBucket(c.bucket_id);
4177 return DoCompressedTexImage2D(
4178 target, level, internal_format, width, height, border,
4179 bucket->size(), bucket->GetData(0, bucket->size()));
4180}
4181
4182error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
4183 uint32 immediate_data_size,
4184 const gles2::CompressedTexSubImage2DBucket& c) {
4185 GLenum target = static_cast<GLenum>(c.target);
4186 GLint level = static_cast<GLint>(c.level);
4187 GLint xoffset = static_cast<GLint>(c.xoffset);
4188 GLint yoffset = static_cast<GLint>(c.yoffset);
4189 GLsizei width = static_cast<GLsizei>(c.width);
4190 GLsizei height = static_cast<GLsizei>(c.height);
4191 GLenum format = static_cast<GLenum>(c.format);
4192 Bucket* bucket = GetBucket(c.bucket_id);
4193 uint32 data_size = bucket->size();
4194 GLsizei imageSize = data_size;
4195 const void* data = bucket->GetData(0, data_size);
4196 if (!ValidateGLenumTextureTarget(target)) {
4197 SetGLError(
4198 GL_INVALID_ENUM, "glCompressedTexSubImage2D: target GL_INVALID_ENUM");
4199 return error::kNoError;
4200 }
4201 if (width < 0) {
4202 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: width < 0");
4203 return error::kNoError;
4204 }
4205 if (height < 0) {
4206 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: height < 0");
4207 return error::kNoError;
4208 }
4209 if (imageSize < 0) {
4210 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: imageSize < 0");
4211 return error::kNoError;
4212 }
4213 glCompressedTexSubImage2D(
4214 target, level, xoffset, yoffset, width, height, format, imageSize, data);
4215 return error::kNoError;
4216}
4217
[email protected]a93bb842010-02-16 23:03:474218error::Error GLES2DecoderImpl::DoTexImage2D(
4219 GLenum target,
4220 GLint level,
4221 GLenum internal_format,
4222 GLsizei width,
4223 GLsizei height,
4224 GLint border,
4225 GLenum format,
4226 GLenum type,
4227 const void* pixels,
4228 uint32 pixels_size) {
[email protected]8eee29c2010-04-29 03:38:294229 if (!ValidateGLenumTextureTarget(target)) {
4230 SetGLError(GL_INVALID_ENUM, "glTexImage2D: target GL_INVALID_ENUM");
4231 return error::kNoError;
4232 }
4233 if (!ValidateGLenumTextureFormat(internal_format)) {
4234 SetGLError(GL_INVALID_ENUM,
4235 "glTexImage2D: internal_format GL_INVALID_ENUM");
4236 return error::kNoError;
4237 }
4238 if (!ValidateGLenumTextureFormat(format)) {
4239 SetGLError(GL_INVALID_ENUM, "glTexImage2D: format GL_INVALID_ENUM");
4240 return error::kNoError;
4241 }
4242 if (!ValidateGLenumPixelType(type)) {
4243 SetGLError(GL_INVALID_ENUM, "glTexImage2D: type GL_INVALID_ENUM");
[email protected]f7a64ee2010-02-01 22:24:144244 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:194245 }
[email protected]3916c97e2010-02-25 03:20:504246 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:474247 border != 0) {
[email protected]8eee29c2010-04-29 03:38:294248 SetGLError(GL_INVALID_VALUE, "glTexImage2D: dimensions out of range");
[email protected]a93bb842010-02-16 23:03:474249 return error::kNoError;
4250 }
[email protected]3916c97e2010-02-25 03:20:504251 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:474252 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294253 SetGLError(GL_INVALID_OPERATION,
4254 "glTexImage2D: unknown texture for target");
[email protected]a93bb842010-02-16 23:03:474255 return error::kNoError;
4256 }
4257 scoped_array<int8> zero;
4258 if (!pixels) {
4259 zero.reset(new int8[pixels_size]);
4260 memset(zero.get(), 0, pixels_size);
4261 pixels = zero.get();
4262 }
[email protected]ef526492010-06-02 23:12:254263 texture_manager()->SetLevelInfo(info,
[email protected]a93bb842010-02-16 23:03:474264 target, level, internal_format, width, height, 1, border, format, type);
4265 glTexImage2D(
4266 target, level, internal_format, width, height, border, format, type,
4267 pixels);
[email protected]f7a64ee2010-02-01 22:24:144268 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:194269}
4270
[email protected]f7a64ee2010-02-01 22:24:144271error::Error GLES2DecoderImpl::HandleTexImage2D(
[email protected]b9849abf2009-11-25 19:13:194272 uint32 immediate_data_size, const gles2::TexImage2D& c) {
4273 GLenum target = static_cast<GLenum>(c.target);
4274 GLint level = static_cast<GLint>(c.level);
4275 GLint internal_format = static_cast<GLint>(c.internalformat);
4276 GLsizei width = static_cast<GLsizei>(c.width);
4277 GLsizei height = static_cast<GLsizei>(c.height);
4278 GLint border = static_cast<GLint>(c.border);
4279 GLenum format = static_cast<GLenum>(c.format);
4280 GLenum type = static_cast<GLenum>(c.type);
4281 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
4282 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
[email protected]a76b0052010-03-05 00:33:184283 uint32 pixels_size;
4284 if (!GLES2Util::ComputeImageDataSize(
4285 width, height, format, type, unpack_alignment_, &pixels_size)) {
4286 return error::kOutOfBounds;
4287 }
[email protected]b9849abf2009-11-25 19:13:194288 const void* pixels = NULL;
4289 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
4290 pixels = GetSharedMemoryAs<const void*>(
4291 pixels_shm_id, pixels_shm_offset, pixels_size);
[email protected]ba3176a2009-12-16 18:19:464292 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:144293 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:194294 }
4295 }
[email protected]a93bb842010-02-16 23:03:474296 return DoTexImage2D(
[email protected]b9849abf2009-11-25 19:13:194297 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:474298 pixels, pixels_size);
[email protected]b9849abf2009-11-25 19:13:194299}
4300
[email protected]f7a64ee2010-02-01 22:24:144301error::Error GLES2DecoderImpl::HandleTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:194302 uint32 immediate_data_size, const gles2::TexImage2DImmediate& c) {
4303 GLenum target = static_cast<GLenum>(c.target);
4304 GLint level = static_cast<GLint>(c.level);
[email protected]ba3176a2009-12-16 18:19:464305 GLint internal_format = static_cast<GLint>(c.internalformat);
[email protected]b9849abf2009-11-25 19:13:194306 GLsizei width = static_cast<GLsizei>(c.width);
4307 GLsizei height = static_cast<GLsizei>(c.height);
4308 GLint border = static_cast<GLint>(c.border);
4309 GLenum format = static_cast<GLenum>(c.format);
4310 GLenum type = static_cast<GLenum>(c.type);
[email protected]a76b0052010-03-05 00:33:184311 uint32 size;
4312 if (!GLES2Util::ComputeImageDataSize(
4313 width, height, format, type, unpack_alignment_, &size)) {
4314 return error::kOutOfBounds;
4315 }
[email protected]07f54fcc2009-12-22 02:46:304316 const void* pixels = GetImmediateDataAs<const void*>(
4317 c, size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:464318 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:144319 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:464320 }
[email protected]a93bb842010-02-16 23:03:474321 DoTexImage2D(
[email protected]ba3176a2009-12-16 18:19:464322 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:474323 pixels, size);
[email protected]f7a64ee2010-02-01 22:24:144324 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324325}
4326
[email protected]f7a64ee2010-02-01 22:24:144327error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
[email protected]b9849abf2009-11-25 19:13:194328 uint32 immediate_data_size, const gles2::GetVertexAttribPointerv& c) {
[email protected]8bf5a3e2010-01-29 04:21:364329 GLuint index = static_cast<GLuint>(c.index);
4330 GLenum pname = static_cast<GLenum>(c.pname);
[email protected]0bfd9882010-02-05 23:02:254331 typedef gles2::GetVertexAttribPointerv::Result Result;
4332 Result* result = GetSharedMemoryAs<Result*>(
4333 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
[email protected]8bf5a3e2010-01-29 04:21:364334 if (!result) {
[email protected]f7a64ee2010-02-01 22:24:144335 return error::kOutOfBounds;
[email protected]8bf5a3e2010-01-29 04:21:364336 }
[email protected]07d0cc82010-02-17 04:51:404337 // Check that the client initialized the result.
4338 if (result->size != 0) {
4339 return error::kInvalidArguments;
4340 }
[email protected]8bf5a3e2010-01-29 04:21:364341 if (!ValidateGLenumVertexPointer(pname)) {
[email protected]8eee29c2010-04-29 03:38:294342 SetGLError(GL_INVALID_ENUM,
4343 "glGetVertexAttribPointerv: pname GL_INVALID_ENUM");
[email protected]f7a64ee2010-02-01 22:24:144344 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:364345 }
[email protected]3916c97e2010-02-25 03:20:504346 if (index >= group_->max_vertex_attribs()) {
[email protected]8eee29c2010-04-29 03:38:294347 SetGLError(GL_INVALID_VALUE,
4348 "glGetVertexAttribPointerv: index out of range.");
[email protected]f7a64ee2010-02-01 22:24:144349 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:364350 }
[email protected]0bfd9882010-02-05 23:02:254351 result->SetNumResults(1);
[email protected]f39f4b3f2010-05-12 17:04:084352 *result->GetData() =
4353 vertex_attrib_manager_.GetVertexAttribInfo(index)->offset();
[email protected]f7a64ee2010-02-01 22:24:144354 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324355}
4356
[email protected]f7b85372010-02-03 01:11:374357bool GLES2DecoderImpl::GetUniformSetup(
4358 GLuint program, GLint location,
4359 uint32 shm_id, uint32 shm_offset,
[email protected]939e7362010-05-13 20:49:104360 error::Error* error, GLuint* service_id, void** result_pointer,
4361 GLenum* result_type) {
4362 DCHECK(error);
4363 DCHECK(service_id);
4364 DCHECK(result_pointer);
4365 DCHECK(result_type);
[email protected]f7b85372010-02-03 01:11:374366 *error = error::kNoError;
4367 // Make sure we have enough room for the result on failure.
[email protected]0bfd9882010-02-05 23:02:254368 SizedResult<GLint>* result;
4369 result = GetSharedMemoryAs<SizedResult<GLint>*>(
4370 shm_id, shm_offset, SizedResult<GLint>::ComputeSize(0));
4371 if (!result) {
[email protected]f7b85372010-02-03 01:11:374372 *error = error::kOutOfBounds;
4373 return false;
4374 }
[email protected]0bfd9882010-02-05 23:02:254375 *result_pointer = result;
[email protected]f7b85372010-02-03 01:11:374376 // Set the result size to 0 so the client does not have to check for success.
[email protected]0bfd9882010-02-05 23:02:254377 result->SetNumResults(0);
[email protected]6b8cf1a2010-05-06 16:13:584378 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
4379 program, "glGetUniform");
[email protected]f7b85372010-02-03 01:11:374380 if (!info) {
[email protected]ae51d192010-04-27 00:48:034381 return false;
4382 }
4383 if (!info->IsValid()) {
[email protected]f7b85372010-02-03 01:11:374384 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]8eee29c2010-04-29 03:38:294385 SetGLError(GL_INVALID_OPERATION, "glGetUniform: program not linked");
[email protected]f7b85372010-02-03 01:11:374386 return false;
4387 }
[email protected]ae51d192010-04-27 00:48:034388 *service_id = info->service_id();
[email protected]0bfd9882010-02-05 23:02:254389 GLenum type;
4390 if (!info->GetUniformTypeByLocation(location, &type)) {
[email protected]f7b85372010-02-03 01:11:374391 // No such location.
[email protected]8eee29c2010-04-29 03:38:294392 SetGLError(GL_INVALID_OPERATION, "glGetUniform: unknown location");
[email protected]f7b85372010-02-03 01:11:374393 return false;
4394 }
[email protected]3916c97e2010-02-25 03:20:504395 GLsizei size = GLES2Util::GetGLDataTypeSizeForUniforms(type);
[email protected]f7b85372010-02-03 01:11:374396 if (size == 0) {
[email protected]8eee29c2010-04-29 03:38:294397 SetGLError(GL_INVALID_OPERATION, "glGetUniform: unknown type");
[email protected]f7b85372010-02-03 01:11:374398 return false;
4399 }
[email protected]0bfd9882010-02-05 23:02:254400 result = GetSharedMemoryAs<SizedResult<GLint>*>(
4401 shm_id, shm_offset, SizedResult<GLint>::ComputeSizeFromBytes(size));
4402 if (!result) {
[email protected]f7b85372010-02-03 01:11:374403 *error = error::kOutOfBounds;
4404 return false;
4405 }
[email protected]0bfd9882010-02-05 23:02:254406 result->size = size;
[email protected]939e7362010-05-13 20:49:104407 *result_type = type;
[email protected]f7b85372010-02-03 01:11:374408 return true;
4409}
4410
[email protected]f7a64ee2010-02-01 22:24:144411error::Error GLES2DecoderImpl::HandleGetUniformiv(
[email protected]b9849abf2009-11-25 19:13:194412 uint32 immediate_data_size, const gles2::GetUniformiv& c) {
[email protected]f7b85372010-02-03 01:11:374413 GLuint program = c.program;
4414 GLint location = c.location;
4415 GLuint service_id;
[email protected]939e7362010-05-13 20:49:104416 GLenum result_type;
[email protected]f7b85372010-02-03 01:11:374417 Error error;
[email protected]0bfd9882010-02-05 23:02:254418 void* result;
[email protected]f7b85372010-02-03 01:11:374419 if (GetUniformSetup(
4420 program, location, c.params_shm_id, c.params_shm_offset,
[email protected]939e7362010-05-13 20:49:104421 &error, &service_id, &result, &result_type)) {
[email protected]0bfd9882010-02-05 23:02:254422 glGetUniformiv(
4423 service_id, location,
4424 static_cast<gles2::GetUniformiv::Result*>(result)->GetData());
[email protected]f7b85372010-02-03 01:11:374425 }
4426 return error;
[email protected]96449d2c2009-11-25 00:01:324427}
4428
[email protected]f7a64ee2010-02-01 22:24:144429error::Error GLES2DecoderImpl::HandleGetUniformfv(
[email protected]b9849abf2009-11-25 19:13:194430 uint32 immediate_data_size, const gles2::GetUniformfv& c) {
[email protected]f7b85372010-02-03 01:11:374431 GLuint program = c.program;
4432 GLint location = c.location;
4433 GLuint service_id;
4434 Error error;
[email protected]0bfd9882010-02-05 23:02:254435 typedef gles2::GetUniformfv::Result Result;
[email protected]939e7362010-05-13 20:49:104436 Result* result;
4437 GLenum result_type;
[email protected]f7b85372010-02-03 01:11:374438 if (GetUniformSetup(
4439 program, location, c.params_shm_id, c.params_shm_offset,
[email protected]939e7362010-05-13 20:49:104440 &error, &service_id, reinterpret_cast<void**>(&result), &result_type)) {
4441 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
4442 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
4443 GLsizei num_values = result->GetNumResults();
4444 scoped_array<GLint> temp(new GLint[num_values]);
4445 glGetUniformiv(service_id, location, temp.get());
4446 GLfloat* dst = result->GetData();
4447 for (GLsizei ii = 0; ii < num_values; ++ii) {
4448 dst[ii] = (temp[ii] != 0);
4449 }
4450 } else {
4451 glGetUniformfv(service_id, location, result->GetData());
4452 }
[email protected]f7b85372010-02-03 01:11:374453 }
4454 return error;
[email protected]96449d2c2009-11-25 00:01:324455}
4456
[email protected]f7a64ee2010-02-01 22:24:144457error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
[email protected]b9849abf2009-11-25 19:13:194458 uint32 immediate_data_size, const gles2::GetShaderPrecisionFormat& c) {
[email protected]0bfd9882010-02-05 23:02:254459 GLenum shader_type = static_cast<GLenum>(c.shadertype);
4460 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
4461 typedef gles2::GetShaderPrecisionFormat::Result Result;
4462 Result* result = GetSharedMemoryAs<Result*>(
4463 c.result_shm_id, c.result_shm_offset, sizeof(*result));
4464 if (!result) {
4465 return error::kOutOfBounds;
4466 }
[email protected]07d0cc82010-02-17 04:51:404467 // Check that the client initialized the result.
4468 if (result->success != 0) {
4469 return error::kInvalidArguments;
4470 }
[email protected]8eee29c2010-04-29 03:38:294471 if (!ValidateGLenumShaderType(shader_type)) {
4472 SetGLError(GL_INVALID_ENUM,
4473 "glGetShaderPrecisionFormat: shader_type GL_INVALID_ENUM");
4474 return error::kNoError;
4475 }
4476 if (!ValidateGLenumShaderPrecision(precision_type)) {
4477 SetGLError(GL_INVALID_ENUM,
4478 "glGetShaderPrecisionFormat: precision_type GL_INVALID_ENUM");
4479 return error::kNoError;
4480 }
4481
4482 result->success = 1; // true
4483 switch (precision_type) {
4484 case GL_LOW_INT:
4485 case GL_MEDIUM_INT:
4486 case GL_HIGH_INT:
4487 result->min_range = -31;
4488 result->max_range = 31;
4489 result->precision = 0;
[email protected]4e8a5b122010-05-08 22:00:104490 break;
[email protected]8eee29c2010-04-29 03:38:294491 case GL_LOW_FLOAT:
4492 case GL_MEDIUM_FLOAT:
4493 case GL_HIGH_FLOAT:
4494 result->min_range = -62;
4495 result->max_range = 62;
4496 result->precision = -16;
4497 break;
4498 default:
4499 NOTREACHED();
4500 break;
[email protected]0bfd9882010-02-05 23:02:254501 }
[email protected]f7a64ee2010-02-01 22:24:144502 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324503}
4504
[email protected]f7a64ee2010-02-01 22:24:144505error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
[email protected]b9849abf2009-11-25 19:13:194506 uint32 immediate_data_size, const gles2::GetAttachedShaders& c) {
[email protected]0bfd9882010-02-05 23:02:254507 uint32 result_size = c.result_size;
[email protected]6b8cf1a2010-05-06 16:13:584508 GLuint program = static_cast<GLuint>(c.program);
4509 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
4510 program, "glGetAttachedShaders");
[email protected]ae51d192010-04-27 00:48:034511 if (!info) {
[email protected]0bfd9882010-02-05 23:02:254512 return error::kNoError;
4513 }
4514 typedef gles2::GetAttachedShaders::Result Result;
4515 uint32 max_count = Result::ComputeMaxResults(result_size);
4516 Result* result = GetSharedMemoryAs<Result*>(
4517 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
4518 if (!result) {
4519 return error::kOutOfBounds;
4520 }
[email protected]07d0cc82010-02-17 04:51:404521 // Check that the client initialized the result.
4522 if (result->size != 0) {
4523 return error::kInvalidArguments;
4524 }
[email protected]0bfd9882010-02-05 23:02:254525 GLsizei count = 0;
[email protected]ae51d192010-04-27 00:48:034526 glGetAttachedShaders(
4527 info->service_id(), max_count, &count, result->GetData());
[email protected]0bfd9882010-02-05 23:02:254528 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]ae51d192010-04-27 00:48:034529 if (!shader_manager()->GetClientId(result->GetData()[ii],
4530 &result->GetData()[ii])) {
[email protected]0bfd9882010-02-05 23:02:254531 NOTREACHED();
4532 return error::kGenericError;
4533 }
4534 }
4535 result->SetNumResults(count);
[email protected]f7a64ee2010-02-01 22:24:144536 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324537}
4538
[email protected]f7a64ee2010-02-01 22:24:144539error::Error GLES2DecoderImpl::HandleGetActiveUniform(
[email protected]b9849abf2009-11-25 19:13:194540 uint32 immediate_data_size, const gles2::GetActiveUniform& c) {
[email protected]0bfd9882010-02-05 23:02:254541 GLuint program = c.program;
4542 GLuint index = c.index;
4543 uint32 name_bucket_id = c.name_bucket_id;
[email protected]0bfd9882010-02-05 23:02:254544 typedef gles2::GetActiveUniform::Result Result;
4545 Result* result = GetSharedMemoryAs<Result*>(
4546 c.result_shm_id, c.result_shm_offset, sizeof(*result));
4547 if (!result) {
4548 return error::kOutOfBounds;
4549 }
[email protected]07d0cc82010-02-17 04:51:404550 // Check that the client initialized the result.
4551 if (result->success != 0) {
4552 return error::kInvalidArguments;
4553 }
[email protected]6b8cf1a2010-05-06 16:13:584554 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
4555 program, "glGetActiveUniform");
[email protected]ae51d192010-04-27 00:48:034556 if (!info) {
[email protected]0bfd9882010-02-05 23:02:254557 return error::kNoError;
4558 }
4559 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
4560 info->GetUniformInfo(index);
4561 if (!uniform_info) {
[email protected]8eee29c2010-04-29 03:38:294562 SetGLError(GL_INVALID_VALUE, "glGetActiveUniform: index out of range");
[email protected]0bfd9882010-02-05 23:02:254563 return error::kNoError;
4564 }
4565 result->success = 1; // true.
4566 result->size = uniform_info->size;
4567 result->type = uniform_info->type;
4568 Bucket* bucket = CreateBucket(name_bucket_id);
4569 bucket->SetFromString(uniform_info->name);
[email protected]f7a64ee2010-02-01 22:24:144570 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324571}
4572
[email protected]f7a64ee2010-02-01 22:24:144573error::Error GLES2DecoderImpl::HandleGetActiveAttrib(
[email protected]b9849abf2009-11-25 19:13:194574 uint32 immediate_data_size, const gles2::GetActiveAttrib& c) {
[email protected]0bfd9882010-02-05 23:02:254575 GLuint program = c.program;
4576 GLuint index = c.index;
4577 uint32 name_bucket_id = c.name_bucket_id;
[email protected]0bfd9882010-02-05 23:02:254578 typedef gles2::GetActiveAttrib::Result Result;
4579 Result* result = GetSharedMemoryAs<Result*>(
4580 c.result_shm_id, c.result_shm_offset, sizeof(*result));
4581 if (!result) {
4582 return error::kOutOfBounds;
4583 }
[email protected]07d0cc82010-02-17 04:51:404584 // Check that the client initialized the result.
4585 if (result->success != 0) {
4586 return error::kInvalidArguments;
4587 }
[email protected]6b8cf1a2010-05-06 16:13:584588 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
4589 program, "glGetActiveAttrib");
[email protected]ae51d192010-04-27 00:48:034590 if (!info) {
[email protected]0bfd9882010-02-05 23:02:254591 return error::kNoError;
4592 }
4593 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
4594 info->GetAttribInfo(index);
4595 if (!attrib_info) {
[email protected]8eee29c2010-04-29 03:38:294596 SetGLError(GL_INVALID_VALUE, "glGetActiveAttrib: index out of range");
[email protected]0bfd9882010-02-05 23:02:254597 return error::kNoError;
4598 }
4599 result->success = 1; // true.
4600 result->size = attrib_info->size;
4601 result->type = attrib_info->type;
4602 Bucket* bucket = CreateBucket(name_bucket_id);
4603 bucket->SetFromString(attrib_info->name);
[email protected]f7a64ee2010-02-01 22:24:144604 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324605}
4606
[email protected]b273e432010-04-12 17:23:584607error::Error GLES2DecoderImpl::HandleShaderBinary(
4608 uint32 immediate_data_size, const gles2::ShaderBinary& c) {
4609#if 1 // No binary shader support.
[email protected]8eee29c2010-04-29 03:38:294610 SetGLError(GL_INVALID_OPERATION, "glShaderBinary: not supported");
[email protected]b273e432010-04-12 17:23:584611 return error::kNoError;
4612#else
4613 GLsizei n = static_cast<GLsizei>(c.n);
4614 if (n < 0) {
[email protected]8eee29c2010-04-29 03:38:294615 SetGLError(GL_INVALID_VALUE, "glShaderBinary: n < 0");
[email protected]b273e432010-04-12 17:23:584616 return error::kNoError;
4617 }
4618 GLsizei length = static_cast<GLsizei>(c.length);
4619 if (length < 0) {
[email protected]8eee29c2010-04-29 03:38:294620 SetGLError(GL_INVALID_VALUE, "glShaderBinary: length < 0");
[email protected]b273e432010-04-12 17:23:584621 return error::kNoError;
4622 }
4623 uint32 data_size;
4624 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4625 return error::kOutOfBounds;
4626 }
4627 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
4628 c.shaders_shm_id, c.shaders_shm_offset, data_size);
4629 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
4630 const void* binary = GetSharedMemoryAs<const void*>(
4631 c.binary_shm_id, c.binary_shm_offset, length);
4632 if (shaders == NULL || binary == NULL) {
4633 return error::kOutOfBounds;
4634 }
4635 scoped_array<GLuint> service_ids(new GLuint[n]);
4636 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:034637 ShaderManager::ShaderInfo* info = GetShaderInfo(shaders[ii]);
4638 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294639 SetGLError(GL_INVALID_VALUE, "glShaderBinary: unknown shader");
[email protected]b273e432010-04-12 17:23:584640 return error::kNoError;
4641 }
[email protected]ae51d192010-04-27 00:48:034642 service_ids[ii] = info->service_id();
[email protected]b273e432010-04-12 17:23:584643 }
4644 // TODO(gman): call glShaderBinary
4645 return error::kNoError;
4646#endif
4647}
4648
[email protected]6217d392010-03-25 22:08:354649error::Error GLES2DecoderImpl::HandleSwapBuffers(
4650 uint32 immediate_data_size, const gles2::SwapBuffers& c) {
[email protected]6217d392010-03-25 22:08:354651 // If offscreen then don't actually SwapBuffers to the display. Just copy
4652 // the rendered frame to another frame buffer.
4653 if (offscreen_target_frame_buffer_.get()) {
4654 ScopedGLErrorSuppressor suppressor(this);
4655
4656 // First check to see if a deferred offscreen render buffer resize is
4657 // pending.
4658 if (!UpdateOffscreenFrameBufferSize())
4659 return error::kLostContext;
4660
4661 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
[email protected]d37231fa2010-04-09 21:16:024662 offscreen_saved_color_texture_->Copy(
4663 offscreen_saved_color_texture_->size());
[email protected]6217d392010-03-25 22:08:354664 } else {
[email protected]d37231fa2010-04-09 21:16:024665#if !defined(UNIT_TEST)
4666 context_->SwapBuffers();
[email protected]6217d392010-03-25 22:08:354667#endif
4668 }
4669
[email protected]7d9ce4f2010-04-14 18:39:404670 // TODO(kbr): when the back buffer is multisampled, then at least on Mac
4671 // OS X (and probably on all platforms, for best semantics), we will need
4672 // to perform the resolve step and bind the offscreen_saved_color_texture_
4673 // as the color attachment before calling the swap buffers callback, which
4674 // expects a normal (non-multisampled) frame buffer for glCopyTexImage2D /
4675 // glReadPixels. After the callback runs, the multisampled frame buffer
4676 // needs to be bound again.
4677
[email protected]6217d392010-03-25 22:08:354678 if (swap_buffers_callback_.get()) {
4679 swap_buffers_callback_->Run();
4680 }
4681
4682 return error::kNoError;
4683}
4684
[email protected]b1d2dcb2010-05-17 19:24:184685error::Error GLES2DecoderImpl::HandleCommandBufferEnable(
4686 uint32 immediate_data_size, const gles2::CommandBufferEnable& c) {
4687 Bucket* bucket = GetBucket(c.bucket_id);
4688 typedef gles2::CommandBufferEnable::Result Result;
4689 Result* result = GetSharedMemoryAs<Result*>(
4690 c.result_shm_id, c.result_shm_offset, sizeof(*result));
4691 if (!result) {
4692 return error::kOutOfBounds;
[email protected]4e8a5b122010-05-08 22:00:104693 }
[email protected]b1d2dcb2010-05-17 19:24:184694 // Check that the client initialized the result.
4695 if (*result != 0) {
4696 return error::kInvalidArguments;
4697 }
4698 std::string feature_str;
4699 if (!bucket->GetAsString(&feature_str)) {
4700 return error::kInvalidArguments;
4701 }
4702
4703 // TODO(gman): make this some kind of table to function pointer thingy.
4704 if (feature_str.compare(PEPPER3D_ALLOW_BUFFERS_ON_MULTIPLE_TARGETS) == 0) {
4705 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
4706 } else if (feature_str.compare(PEPPER3D_SKIP_GLSL_TRANSLATION) == 0) {
4707 use_shader_translator_ = false;
4708 } else {
4709 return error::kNoError;
4710 }
4711
4712 *result = 1; // true.
4713 return error::kNoError;
[email protected]4e8a5b122010-05-08 22:00:104714}
4715
[email protected]96449d2c2009-11-25 00:01:324716// Include the auto-generated part of this file. We split this because it means
4717// we can easily edit the non-auto generated parts right here in this file
4718// instead of having to edit some template or the code generator.
4719#include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
4720
4721} // namespace gles2
[email protected]a7a27ace2009-12-12 00:11:254722} // namespace gpu