blob: e8deed62af8147d77d422dba4f9e4c32214fb42d [file] [log] [blame]
[email protected]4874aae2011-03-18 01:19:561// Copyright (c) 2011 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
[email protected]1e6f58d2011-03-24 00:00:4015#include "base/atomicops.h"
[email protected]00eb49a2010-08-12 20:46:5716#include "base/at_exit.h"
[email protected]9d37f062011-11-22 01:24:5217#include "base/bind.h"
[email protected]3b63f8f42011-03-28 01:54:1518#include "base/memory/scoped_ptr.h"
19#include "base/memory/weak_ptr.h"
[email protected]d37231fa2010-04-09 21:16:0220#include "build/build_config.h"
[email protected]96449d2c2009-11-25 00:01:3221#define GLES2_GPU_SERVICE 1
22#include "gpu/command_buffer/common/gles2_cmd_format.h"
23#include "gpu/command_buffer/common/gles2_cmd_utils.h"
[email protected]066849e32010-05-03 19:14:1024#include "gpu/command_buffer/common/id_allocator.h"
[email protected]366ae242011-05-10 02:23:5825#include "gpu/command_buffer/common/trace_event.h"
[email protected]3916c97e2010-02-25 03:20:5026#include "gpu/command_buffer/service/buffer_manager.h"
[email protected]96449d2c2009-11-25 00:01:3227#include "gpu/command_buffer/service/cmd_buffer_engine.h"
[email protected]3916c97e2010-02-25 03:20:5028#include "gpu/command_buffer/service/context_group.h"
[email protected]915a59a12010-09-30 21:29:1129#include "gpu/command_buffer/service/feature_info.h"
[email protected]a25fa872010-03-25 02:57:5830#include "gpu/command_buffer/service/framebuffer_manager.h"
[email protected]96449d2c2009-11-25 00:01:3231#include "gpu/command_buffer/service/gl_utils.h"
[email protected]ba3176a2009-12-16 18:19:4632#include "gpu/command_buffer/service/gles2_cmd_validation.h"
[email protected]a93bb842010-02-16 23:03:4733#include "gpu/command_buffer/service/program_manager.h"
[email protected]a25fa872010-03-25 02:57:5834#include "gpu/command_buffer/service/renderbuffer_manager.h"
[email protected]a93bb842010-02-16 23:03:4735#include "gpu/command_buffer/service/shader_manager.h"
[email protected]a550584e2010-09-17 18:01:4536#include "gpu/command_buffer/service/shader_translator.h"
[email protected]b0af4f52011-09-28 22:04:4237#include "gpu/command_buffer/service/stream_texture.h"
38#include "gpu/command_buffer/service/stream_texture_manager.h"
[email protected]a93bb842010-02-16 23:03:4739#include "gpu/command_buffer/service/texture_manager.h"
[email protected]d8ea9772011-07-11 18:11:4340#include "gpu/command_buffer/service/vertex_attrib_manager.h"
[email protected]5ae0b282011-03-28 19:24:4941#include "ui/gfx/gl/gl_context.h"
42#include "ui/gfx/gl/gl_implementation.h"
[email protected]f62a5ab2011-05-23 20:34:1543#include "ui/gfx/gl/gl_surface.h"
[email protected]de17df392010-04-23 21:09:4144
[email protected]6217d392010-03-25 22:08:3545#if !defined(GL_DEPTH24_STENCIL8)
46#define GL_DEPTH24_STENCIL8 0x88F0
47#endif
48
[email protected]a7a27ace2009-12-12 00:11:2549namespace gpu {
[email protected]96449d2c2009-11-25 00:01:3250namespace gles2 {
51
[email protected]f0d74742011-10-03 16:31:0452namespace {
53static const char kOESDerivativeExtension[] = "GL_OES_standard_derivatives";
54}
55
[email protected]6217d392010-03-25 22:08:3556class GLES2DecoderImpl;
57
[email protected]07f54fcc2009-12-22 02:46:3058// Check that certain assumptions the code makes are true. There are places in
59// the code where shared memory is passed direclty to GL. Example, glUniformiv,
60// glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
61// a few others) are 32bits. If they are not 32bits the code will have to change
62// to call those GL functions with service side memory and then copy the results
63// to shared memory, converting the sizes.
64COMPILE_ASSERT(sizeof(GLint) == sizeof(uint32), // NOLINT
65 GLint_not_same_size_as_uint32);
66COMPILE_ASSERT(sizeof(GLsizei) == sizeof(uint32), // NOLINT
67 GLint_not_same_size_as_uint32);
[email protected]f7b85372010-02-03 01:11:3768COMPILE_ASSERT(sizeof(GLfloat) == sizeof(float), // NOLINT
69 GLfloat_not_same_size_as_float);
[email protected]07f54fcc2009-12-22 02:46:3070
[email protected]43f28f832010-02-03 02:28:4871// TODO(kbr): the use of this anonymous namespace core dumps the
72// linker on Mac OS X 10.6 when the symbol ordering file is used
73// namespace {
[email protected]96449d2c2009-11-25 00:01:3274
75// Returns the address of the first byte after a struct.
76template <typename T>
77const void* AddressAfterStruct(const T& pod) {
78 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
79}
80
[email protected]07f54fcc2009-12-22 02:46:3081// Returns the address of the frst byte after the struct or NULL if size >
82// immediate_data_size.
[email protected]96449d2c2009-11-25 00:01:3283template <typename RETURN_TYPE, typename COMMAND_TYPE>
[email protected]07f54fcc2009-12-22 02:46:3084RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod,
85 uint32 size,
86 uint32 immediate_data_size) {
87 return (size <= immediate_data_size) ?
88 static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))) :
89 NULL;
[email protected]96449d2c2009-11-25 00:01:3290}
91
[email protected]07f54fcc2009-12-22 02:46:3092// Computes the data size for certain gl commands like glUniform.
[email protected]a76b0052010-03-05 00:33:1893bool ComputeDataSize(
[email protected]96449d2c2009-11-25 00:01:3294 GLuint count,
95 size_t size,
[email protected]a76b0052010-03-05 00:33:1896 unsigned int elements_per_unit,
97 uint32* dst) {
98 uint32 value;
99 if (!SafeMultiplyUint32(count, size, &value)) {
100 return false;
101 }
102 if (!SafeMultiplyUint32(value, elements_per_unit, &value)) {
103 return false;
104 }
105 *dst = value;
106 return true;
[email protected]96449d2c2009-11-25 00:01:32107}
108
109// A struct to hold info about each command.
110struct CommandInfo {
111 int arg_flags; // How to handle the arguments for this command
112 int arg_count; // How many arguments are expected for this command.
113};
114
115// A table of CommandInfo for all the commands.
116const CommandInfo g_command_info[] = {
117 #define GLES2_CMD_OP(name) { \
118 name::kArgFlags, \
119 sizeof(name) / sizeof(CommandBufferEntry) - 1, }, /* NOLINT */ \
120
121 GLES2_COMMAND_LIST(GLES2_CMD_OP)
122
123 #undef GLES2_CMD_OP
124};
125
[email protected]34ff8b0c2010-10-01 20:06:02126static bool IsAngle() {
127#if defined(OS_WIN)
128 return gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2;
129#else
130 return false;
131#endif
132}
133
[email protected]258a3313f2011-10-18 20:13:57134// Return true if a character belongs to the ASCII subset as defined in
135// GLSL ES 1.0 spec section 3.1.
136static bool CharacterIsValidForGLES(unsigned char c) {
137 // Printing characters are valid except " $ ` @ \ ' DEL.
138 if (c >= 32 && c <= 126 &&
139 c != '"' &&
140 c != '$' &&
141 c != '`' &&
142 c != '@' &&
143 c != '\\' &&
144 c != '\'') {
145 return true;
146 }
147 // Horizontal tab, line feed, vertical tab, form feed, carriage return
148 // are also valid.
149 if (c >= 9 && c <= 13) {
150 return true;
151 }
152
153 return false;
154}
155
156static bool StringIsValidForGLES(const char* str) {
157 for (; *str; ++str) {
158 if (!CharacterIsValidForGLES(*str)) {
159 return false;
160 }
161 }
162 return true;
163}
164
[email protected]297ca1c2011-06-20 23:08:46165static void WrappedTexImage2D(
[email protected]473c01ccb2011-06-07 01:33:30166 GLenum target,
167 GLint level,
168 GLenum internal_format,
169 GLsizei width,
170 GLsizei height,
171 GLint border,
172 GLenum format,
173 GLenum type,
174 const void* pixels) {
175 GLenum gl_internal_format = internal_format;
176 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
177 if (format == GL_BGRA_EXT && internal_format == GL_BGRA_EXT) {
178 gl_internal_format = GL_RGBA;
179 } else if (type == GL_FLOAT) {
180 if (format == GL_RGBA) {
181 gl_internal_format = GL_RGBA32F_ARB;
182 } else if (format == GL_RGB) {
183 gl_internal_format = GL_RGB32F_ARB;
184 }
185 } else if (type == GL_HALF_FLOAT_OES) {
186 if (format == GL_RGBA) {
187 gl_internal_format = GL_RGBA16F_ARB;
188 } else if (format == GL_RGB) {
189 gl_internal_format = GL_RGB16F_ARB;
190 }
191 }
192 }
193 glTexImage2D(
194 target, level, gl_internal_format, width, height, border, format, type,
195 pixels);
196}
197
[email protected]297ca1c2011-06-20 23:08:46198// Wrapper for glEnable/glDisable that doesn't suck.
199static void EnableDisable(GLenum pname, bool enable) {
200 if (enable) {
201 glEnable(pname);
202 } else {
203 glDisable(pname);
204 }
205}
206
[email protected]6217d392010-03-25 22:08:35207// This class prevents any GL errors that occur when it is in scope from
208// being reported to the client.
209class ScopedGLErrorSuppressor {
210 public:
211 explicit ScopedGLErrorSuppressor(GLES2DecoderImpl* decoder);
212 ~ScopedGLErrorSuppressor();
213 private:
214 GLES2DecoderImpl* decoder_;
215 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor);
216};
217
218// Temporarily changes a decoder's bound 2D texture and restore it when this
219// object goes out of scope. Also temporarily switches to using active texture
220// unit zero in case the client has changed that to something invalid.
221class ScopedTexture2DBinder {
222 public:
223 ScopedTexture2DBinder(GLES2DecoderImpl* decoder, GLuint id);
224 ~ScopedTexture2DBinder();
225
226 private:
227 GLES2DecoderImpl* decoder_;
228 DISALLOW_COPY_AND_ASSIGN(ScopedTexture2DBinder);
229};
230
231// Temporarily changes a decoder's bound render buffer and restore it when this
232// object goes out of scope.
233class ScopedRenderBufferBinder {
234 public:
235 ScopedRenderBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
236 ~ScopedRenderBufferBinder();
237
238 private:
239 GLES2DecoderImpl* decoder_;
240 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder);
241};
242
243// Temporarily changes a decoder's bound frame buffer and restore it when this
244// object goes out of scope.
245class ScopedFrameBufferBinder {
246 public:
247 ScopedFrameBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
248 ~ScopedFrameBufferBinder();
249
250 private:
251 GLES2DecoderImpl* decoder_;
252 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder);
253};
254
[email protected]34ff8b0c2010-10-01 20:06:02255// Temporarily changes a decoder's bound frame buffer to a resolved version of
[email protected]c0701082011-04-20 00:34:52256// the multisampled offscreen render buffer if that buffer is multisampled, and,
[email protected]de26b3c2011-08-03 21:54:27257// if it is bound or enforce_internal_framebuffer is true. If internal is
258// true, the resolved framebuffer is not visible to the parent.
[email protected]34ff8b0c2010-10-01 20:06:02259class ScopedResolvedFrameBufferBinder {
260 public:
[email protected]e7e38032011-07-26 17:25:25261 ScopedResolvedFrameBufferBinder(GLES2DecoderImpl* decoder,
[email protected]de26b3c2011-08-03 21:54:27262 bool enforce_internal_framebuffer,
263 bool internal);
[email protected]34ff8b0c2010-10-01 20:06:02264 ~ScopedResolvedFrameBufferBinder();
265
266 private:
267 GLES2DecoderImpl* decoder_;
268 bool resolve_and_bind_;
269 DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder);
270};
271
[email protected]6217d392010-03-25 22:08:35272// Encapsulates an OpenGL texture.
273class Texture {
274 public:
275 explicit Texture(GLES2DecoderImpl* decoder);
276 ~Texture();
277
278 // Create a new render texture.
279 void Create();
280
281 // Set the initial size and format of a render texture or resize it.
[email protected]34ff8b0c2010-10-01 20:06:02282 bool AllocateStorage(const gfx::Size& size, GLenum format);
[email protected]6217d392010-03-25 22:08:35283
284 // Copy the contents of the currently bound frame buffer.
[email protected]3a4d0c52011-06-29 23:11:58285 void Copy(const gfx::Size& size, GLenum format);
[email protected]6217d392010-03-25 22:08:35286
287 // Destroy the render texture. This must be explicitly called before
288 // destroying this object.
289 void Destroy();
290
[email protected]97872062010-11-03 19:07:05291 // Invalidate the texture. This can be used when a context is lost and it is
292 // not possible to make it current in order to free the resource.
293 void Invalidate();
294
[email protected]6217d392010-03-25 22:08:35295 GLuint id() const {
296 return id_;
297 }
298
[email protected]d37231fa2010-04-09 21:16:02299 gfx::Size size() const {
300 return size_;
301 }
302
[email protected]6217d392010-03-25 22:08:35303 private:
304 GLES2DecoderImpl* decoder_;
305 GLuint id_;
[email protected]d37231fa2010-04-09 21:16:02306 gfx::Size size_;
[email protected]6217d392010-03-25 22:08:35307 DISALLOW_COPY_AND_ASSIGN(Texture);
308};
309
310// Encapsulates an OpenGL render buffer of any format.
311class RenderBuffer {
312 public:
313 explicit RenderBuffer(GLES2DecoderImpl* decoder);
314 ~RenderBuffer();
315
316 // Create a new render buffer.
317 void Create();
318
319 // Set the initial size and format of a render buffer or resize it.
[email protected]34ff8b0c2010-10-01 20:06:02320 bool AllocateStorage(const gfx::Size& size, GLenum format, GLsizei samples);
[email protected]6217d392010-03-25 22:08:35321
322 // Destroy the render buffer. This must be explicitly called before destroying
323 // this object.
324 void Destroy();
325
[email protected]97872062010-11-03 19:07:05326 // Invalidate the render buffer. This can be used when a context is lost and
327 // it is not possible to make it current in order to free the resource.
328 void Invalidate();
329
[email protected]6217d392010-03-25 22:08:35330 GLuint id() const {
331 return id_;
332 }
333
334 private:
335 GLES2DecoderImpl* decoder_;
336 GLuint id_;
337 DISALLOW_COPY_AND_ASSIGN(RenderBuffer);
338};
339
340// Encapsulates an OpenGL frame buffer.
341class FrameBuffer {
342 public:
343 explicit FrameBuffer(GLES2DecoderImpl* decoder);
344 ~FrameBuffer();
345
346 // Create a new frame buffer.
347 void Create();
348
349 // Attach a color render buffer to a frame buffer.
350 void AttachRenderTexture(Texture* texture);
351
[email protected]b9363b22010-06-09 22:06:15352 // Attach a render buffer to a frame buffer. Note that this unbinds any
353 // currently bound frame buffer.
354 void AttachRenderBuffer(GLenum target, RenderBuffer* render_buffer);
[email protected]6217d392010-03-25 22:08:35355
[email protected]6217d392010-03-25 22:08:35356 // Destroy the frame buffer. This must be explicitly called before destroying
357 // this object.
358 void Destroy();
359
[email protected]97872062010-11-03 19:07:05360 // Invalidate the frame buffer. This can be used when a context is lost and it
361 // is not possible to make it current in order to free the resource.
362 void Invalidate();
363
[email protected]6217d392010-03-25 22:08:35364 // See glCheckFramebufferStatusEXT.
365 GLenum CheckStatus();
366
367 GLuint id() const {
368 return id_;
369 }
370
371 private:
372 GLES2DecoderImpl* decoder_;
373 GLuint id_;
374 DISALLOW_COPY_AND_ASSIGN(FrameBuffer);
375};
[email protected]34ff8b0c2010-10-01 20:06:02376
377class ContextCreationAttribParser {
378 public:
379 ContextCreationAttribParser();
380 bool Parse(const std::vector<int32>& attribs);
381
382 // -1 if invalid or unspecified.
383 int32 alpha_size_;
384 int32 blue_size_;
385 int32 green_size_;
386 int32 red_size_;
387 int32 depth_size_;
388 int32 stencil_size_;
389 int32 samples_;
390 int32 sample_buffers_;
391};
392
393ContextCreationAttribParser::ContextCreationAttribParser()
394 : alpha_size_(-1),
395 blue_size_(-1),
396 green_size_(-1),
397 red_size_(-1),
398 depth_size_(-1),
399 stencil_size_(-1),
400 samples_(-1),
401 sample_buffers_(-1) {
402}
403
404bool ContextCreationAttribParser::Parse(const std::vector<int32>& attribs) {
405 // From <EGL/egl.h>.
406 const int32 EGL_ALPHA_SIZE = 0x3021;
407 const int32 EGL_BLUE_SIZE = 0x3022;
408 const int32 EGL_GREEN_SIZE = 0x3023;
409 const int32 EGL_RED_SIZE = 0x3024;
410 const int32 EGL_DEPTH_SIZE = 0x3025;
411 const int32 EGL_STENCIL_SIZE = 0x3026;
412 const int32 EGL_SAMPLES = 0x3031;
413 const int32 EGL_SAMPLE_BUFFERS = 0x3032;
414 const int32 EGL_NONE = 0x3038;
415
416 for (size_t i = 0; i < attribs.size(); i += 2) {
417 const int32 attrib = attribs[i];
418 if (i + 1 >= attribs.size()) {
419 if (attrib == EGL_NONE)
420 return true;
421
422 DLOG(ERROR) << "Missing value after context creation attribute: "
423 << attrib;
424 return false;
425 }
426
427 const int32 value = attribs[i+1];
428 switch (attrib) {
429 case EGL_ALPHA_SIZE:
430 alpha_size_ = value;
431 break;
432 case EGL_BLUE_SIZE:
433 blue_size_ = value;
434 break;
435 case EGL_GREEN_SIZE:
436 green_size_ = value;
437 break;
438 case EGL_RED_SIZE:
439 red_size_ = value;
440 break;
441 case EGL_DEPTH_SIZE:
442 depth_size_ = value;
443 break;
444 case EGL_STENCIL_SIZE:
445 stencil_size_ = value;
446 break;
447 case EGL_SAMPLES:
448 samples_ = value;
449 break;
450 case EGL_SAMPLE_BUFFERS:
451 sample_buffers_ = value;
452 break;
453 case EGL_NONE:
454 // Terminate list, even if more attributes.
455 return true;
456 default:
457 DLOG(ERROR) << "Invalid context creation attribute: " << attrib;
458 return false;
459 }
460 }
461
462 return true;
463}
464
[email protected]43f28f832010-02-03 02:28:48465// } // anonymous namespace.
[email protected]96449d2c2009-11-25 00:01:32466
[email protected]ddb1e5a2010-12-13 20:10:45467bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id,
468 uint32* service_texture_id) {
469 return false;
470}
471
[email protected]a3ded6d2010-10-19 06:44:39472GLES2Decoder::GLES2Decoder()
473 : debug_(false) {
[email protected]96449d2c2009-11-25 00:01:32474}
475
[email protected]3916c97e2010-02-25 03:20:50476GLES2Decoder::~GLES2Decoder() {
477}
478
[email protected]f39f4b3f2010-05-12 17:04:08479// This class implements GLES2Decoder so we don't have to expose all the GLES2
480// cmd stuff to outside this class.
481class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
482 public GLES2Decoder {
483 public:
[email protected]aa7666122011-09-02 19:45:52484 explicit GLES2DecoderImpl(ContextGroup* group);
[email protected]f39f4b3f2010-05-12 17:04:08485
[email protected]96449d2c2009-11-25 00:01:32486 // Overridden from AsyncAPIInterface.
[email protected]f7a64ee2010-02-01 22:24:14487 virtual Error DoCommand(unsigned int command,
[email protected]3916c97e2010-02-25 03:20:50488 unsigned int arg_count,
489 const void* args);
[email protected]96449d2c2009-11-25 00:01:32490
491 // Overridden from AsyncAPIInterface.
492 virtual const char* GetCommandName(unsigned int command_id) const;
493
494 // Overridden from GLES2Decoder.
[email protected]fbe20372011-06-01 01:46:38495 virtual bool Initialize(const scoped_refptr<gfx::GLSurface>& surface,
496 const scoped_refptr<gfx::GLContext>& context,
[email protected]6217d392010-03-25 22:08:35497 const gfx::Size& size,
[email protected]e82fb792011-09-22 00:33:29498 const DisallowedFeatures& disallowed_features,
[email protected]a3ded6d2010-10-19 06:44:39499 const char* allowed_extensions,
[email protected]3c644d82011-06-20 19:58:24500 const std::vector<int32>& attribs);
[email protected]96449d2c2009-11-25 00:01:32501 virtual void Destroy();
[email protected]3c644d82011-06-20 19:58:24502 virtual bool SetParent(GLES2Decoder* parent_decoder,
503 uint32 parent_texture_id);
[email protected]799b4b22011-08-22 17:09:59504 virtual bool ResizeOffscreenFrameBuffer(const gfx::Size& size);
[email protected]9a5afa432011-07-22 18:16:39505 void UpdateParentTextureInfo();
[email protected]eb54a562010-01-20 21:55:18506 virtual bool MakeCurrent();
[email protected]a96a6022011-11-04 00:58:12507 virtual void ReleaseCurrent();
[email protected]56ac89b2010-03-17 21:16:55508 virtual GLES2Util* GetGLES2Util() { return &util_; }
[email protected]66791e382010-07-14 20:48:30509 virtual gfx::GLContext* GetGLContext() { return context_.get(); }
[email protected]f62a5ab2011-05-23 20:34:15510 virtual gfx::GLSurface* GetGLSurface() { return surface_.get(); }
[email protected]a3ded6d2010-10-19 06:44:39511 virtual ContextGroup* GetContextGroup() { return group_.get(); }
[email protected]43f28f832010-02-03 02:28:48512
[email protected]0d6bfdc2011-11-02 01:32:20513 virtual void SetGLError(GLenum error, const char* msg);
[email protected]9d37f062011-11-22 01:24:52514 virtual void SetResizeCallback(
515 const base::Callback<void(gfx::Size)>& callback);
[email protected]22f320a2011-08-30 01:17:00516
[email protected]9d37f062011-11-22 01:24:52517 virtual void SetSwapBuffersCallback(const base::Closure& callback);
[email protected]22f320a2011-08-30 01:17:00518
[email protected]b0af4f52011-09-28 22:04:42519 virtual void SetStreamTextureManager(StreamTextureManager* manager);
[email protected]1318e922010-09-17 22:03:16520 virtual bool GetServiceTextureId(uint32 client_texture_id,
521 uint32* service_texture_id);
[email protected]43f28f832010-02-03 02:28:48522
[email protected]8e3e0662010-08-23 18:46:30523 // Restores the current state to the user's settings.
524 void RestoreCurrentFramebufferBindings();
525 void RestoreCurrentRenderbufferBindings();
526 void RestoreCurrentTexture2DBindings();
527
[email protected]297ca1c2011-06-20 23:08:46528 // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
529 void ApplyDirtyState();
530
531 // These check the state of the currently bound framebuffer or the
532 // backbuffer if no framebuffer is bound.
533 bool BoundFramebufferHasColorAttachmentWithAlpha();
534 bool BoundFramebufferHasDepthAttachment();
535 bool BoundFramebufferHasStencilAttachment();
536
[email protected]38d139d2011-07-14 00:38:43537 virtual error::ContextLostReason GetContextLostReason();
538
[email protected]96449d2c2009-11-25 00:01:32539 private:
[email protected]6217d392010-03-25 22:08:35540 friend class ScopedGLErrorSuppressor;
[email protected]34ff8b0c2010-10-01 20:06:02541 friend class ScopedResolvedFrameBufferBinder;
[email protected]6217d392010-03-25 22:08:35542 friend class RenderBuffer;
543 friend class FrameBuffer;
544
[email protected]3916c97e2010-02-25 03:20:50545 // State associated with each texture unit.
546 struct TextureUnit {
547 TextureUnit() : bind_target(GL_TEXTURE_2D) { }
548
549 // The last target that was bound to this texture unit.
550 GLenum bind_target;
551
552 // texture currently bound to this unit's GL_TEXTURE_2D with glBindTexture
553 TextureManager::TextureInfo::Ref bound_texture_2d;
554
555 // texture currently bound to this unit's GL_TEXTURE_CUBE_MAP with
556 // glBindTexture
557 TextureManager::TextureInfo::Ref bound_texture_cube_map;
[email protected]61eeb33f2011-07-26 15:30:31558
559 // texture currently bound to this unit's GL_TEXTURE_EXTERNAL_OES with
560 // glBindTexture
561 TextureManager::TextureInfo::Ref bound_texture_external_oes;
562
563 TextureManager::TextureInfo::Ref GetInfoForSamplerType(GLenum type) {
564 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
565 type == GL_SAMPLER_EXTERNAL_OES);
566 return type == GL_SAMPLER_2D ? bound_texture_2d :
567 (type == GL_SAMPLER_EXTERNAL_OES ? bound_texture_external_oes :
568 bound_texture_cube_map);
569 }
[email protected]a0b78dc2011-11-11 10:43:10570
571 void Unbind(TextureManager::TextureInfo* texture) {
572 if (bound_texture_2d == texture) {
573 bound_texture_2d = NULL;
574 }
575 if (bound_texture_cube_map == texture) {
576 bound_texture_cube_map = NULL;
577 }
578 if (bound_texture_external_oes == texture) {
579 bound_texture_external_oes = NULL;
580 }
581 }
[email protected]3916c97e2010-02-25 03:20:50582 };
583
[email protected]c2f8c8402010-12-06 18:07:24584 // Initialize or re-initialize the shader translator.
585 bool InitializeShaderTranslator();
586
[email protected]302ce6d2011-07-07 23:28:11587 void UpdateCapabilities();
588
[email protected]ae51d192010-04-27 00:48:03589 // Helpers for the glGen and glDelete functions.
590 bool GenTexturesHelper(GLsizei n, const GLuint* client_ids);
591 void DeleteTexturesHelper(GLsizei n, const GLuint* client_ids);
592 bool GenBuffersHelper(GLsizei n, const GLuint* client_ids);
593 void DeleteBuffersHelper(GLsizei n, const GLuint* client_ids);
594 bool GenFramebuffersHelper(GLsizei n, const GLuint* client_ids);
595 void DeleteFramebuffersHelper(GLsizei n, const GLuint* client_ids);
596 bool GenRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
597 void DeleteRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
[email protected]a93bb842010-02-16 23:03:47598
[email protected]3916c97e2010-02-25 03:20:50599 // TODO(gman): Cache these pointers?
[email protected]3916c97e2010-02-25 03:20:50600 BufferManager* buffer_manager() {
601 return group_->buffer_manager();
602 }
603
[email protected]a25fa872010-03-25 02:57:58604 RenderbufferManager* renderbuffer_manager() {
605 return group_->renderbuffer_manager();
606 }
607
608 FramebufferManager* framebuffer_manager() {
609 return group_->framebuffer_manager();
610 }
611
[email protected]3916c97e2010-02-25 03:20:50612 ProgramManager* program_manager() {
613 return group_->program_manager();
614 }
615
616 ShaderManager* shader_manager() {
617 return group_->shader_manager();
618 }
619
620 TextureManager* texture_manager() {
621 return group_->texture_manager();
622 }
623
[email protected]34ff8b0c2010-10-01 20:06:02624 bool IsOffscreenBufferMultisampled() const {
625 return offscreen_target_samples_ > 1;
626 }
627
[email protected]a93bb842010-02-16 23:03:47628 // Creates a TextureInfo for the given texture.
[email protected]ae51d192010-04-27 00:48:03629 TextureManager::TextureInfo* CreateTextureInfo(
630 GLuint client_id, GLuint service_id) {
[email protected]915a59a12010-09-30 21:29:11631 return texture_manager()->CreateTextureInfo(
632 feature_info_, client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47633 }
634
635 // Gets the texture info for the given texture. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03636 TextureManager::TextureInfo* GetTextureInfo(GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:50637 TextureManager::TextureInfo* info =
[email protected]ae51d192010-04-27 00:48:03638 texture_manager()->GetTextureInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:10639 return info;
[email protected]a93bb842010-02-16 23:03:47640 }
641
642 // Deletes the texture info for the given texture.
[email protected]ae51d192010-04-27 00:48:03643 void RemoveTextureInfo(GLuint client_id) {
[email protected]915a59a12010-09-30 21:29:11644 texture_manager()->RemoveTextureInfo(feature_info_, client_id);
[email protected]3916c97e2010-02-25 03:20:50645 }
[email protected]a93bb842010-02-16 23:03:47646
[email protected]d37231fa2010-04-09 21:16:02647 // Get the size (in pixels) of the currently bound frame buffer (either FBO
648 // or regular back buffer).
[email protected]8e3e0662010-08-23 18:46:30649 gfx::Size GetBoundReadFrameBufferSize();
[email protected]d37231fa2010-04-09 21:16:02650
[email protected]9edc6b22010-12-23 02:00:26651 // Get the format of the currently bound frame buffer (either FBO or regular
652 // back buffer)
653 GLenum GetBoundReadFrameBufferInternalFormat();
[email protected]297ca1c2011-06-20 23:08:46654 GLenum GetBoundDrawFrameBufferInternalFormat();
[email protected]9edc6b22010-12-23 02:00:26655
[email protected]a93bb842010-02-16 23:03:47656 // Wrapper for CompressedTexImage2D commands.
657 error::Error DoCompressedTexImage2D(
658 GLenum target,
659 GLint level,
660 GLenum internal_format,
661 GLsizei width,
662 GLsizei height,
663 GLint border,
664 GLsizei image_size,
665 const void* data);
666
[email protected]cadde4a2010-07-31 17:10:43667 // Wrapper for CompressedTexSubImage2D.
668 void DoCompressedTexSubImage2D(
669 GLenum target,
670 GLint level,
671 GLint xoffset,
672 GLint yoffset,
673 GLsizei width,
674 GLsizei height,
675 GLenum format,
676 GLsizei imageSize,
677 const void * data);
678
679 // Wrapper for CopyTexImage2D.
680 void DoCopyTexImage2D(
681 GLenum target,
682 GLint level,
683 GLenum internal_format,
684 GLint x,
685 GLint y,
686 GLsizei width,
687 GLsizei height,
688 GLint border);
689
690 // Wrapper for CopyTexSubImage2D.
691 void DoCopyTexSubImage2D(
692 GLenum target,
693 GLint level,
694 GLint xoffset,
695 GLint yoffset,
696 GLint x,
697 GLint y,
698 GLsizei width,
699 GLsizei height);
700
[email protected]a93bb842010-02-16 23:03:47701 // Wrapper for TexImage2D commands.
702 error::Error DoTexImage2D(
703 GLenum target,
704 GLint level,
705 GLenum internal_format,
706 GLsizei width,
707 GLsizei height,
708 GLint border,
709 GLenum format,
710 GLenum type,
711 const void* pixels,
712 uint32 pixels_size);
713
[email protected]cadde4a2010-07-31 17:10:43714 // Wrapper for TexSubImage2D.
715 void DoTexSubImage2D(
716 GLenum target,
717 GLint level,
718 GLint xoffset,
719 GLint yoffset,
720 GLsizei width,
721 GLsizei height,
722 GLenum format,
723 GLenum type,
724 const void * data);
725
[email protected]a93bb842010-02-16 23:03:47726 // Creates a ProgramInfo for the given program.
[email protected]d685a682011-04-29 16:19:57727 ProgramManager::ProgramInfo* CreateProgramInfo(
728 GLuint client_id, GLuint service_id) {
729 return program_manager()->CreateProgramInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47730 }
731
[email protected]07f54fcc2009-12-22 02:46:30732 // Gets the program info for the given program. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03733 ProgramManager::ProgramInfo* GetProgramInfo(GLuint client_id) {
[email protected]ca488e12010-12-13 20:06:14734 return program_manager()->GetProgramInfo(client_id);
[email protected]1d32bc82010-01-13 22:06:46735 }
[email protected]07f54fcc2009-12-22 02:46:30736
[email protected]6b8cf1a2010-05-06 16:13:58737 // Gets the program info for the given program. If it's not a program
738 // generates a GL error. Returns NULL if not program.
739 ProgramManager::ProgramInfo* GetProgramInfoNotShader(
740 GLuint client_id, const char* function_name) {
741 ProgramManager::ProgramInfo* info = GetProgramInfo(client_id);
742 if (!info) {
743 if (GetShaderInfo(client_id)) {
744 SetGLError(GL_INVALID_OPERATION,
745 (std::string(function_name) +
746 ": shader passed for program").c_str());
747 } else {
748 SetGLError(GL_INVALID_VALUE,
749 (std::string(function_name) + ": unknown program").c_str());
750 }
751 }
752 return info;
753 }
754
755
[email protected]45bf5152010-02-12 00:11:31756 // Creates a ShaderInfo for the given shader.
[email protected]d685a682011-04-29 16:19:57757 ShaderManager::ShaderInfo* CreateShaderInfo(
758 GLuint client_id,
759 GLuint service_id,
760 GLenum shader_type) {
761 return shader_manager()->CreateShaderInfo(
762 client_id, service_id, shader_type);
[email protected]45bf5152010-02-12 00:11:31763 }
764
765 // Gets the shader info for the given shader. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03766 ShaderManager::ShaderInfo* GetShaderInfo(GLuint client_id) {
[email protected]ca488e12010-12-13 20:06:14767 return shader_manager()->GetShaderInfo(client_id);
[email protected]45bf5152010-02-12 00:11:31768 }
769
[email protected]6b8cf1a2010-05-06 16:13:58770 // Gets the shader info for the given shader. If it's not a shader generates a
771 // GL error. Returns NULL if not shader.
772 ShaderManager::ShaderInfo* GetShaderInfoNotProgram(
773 GLuint client_id, const char* function_name) {
774 ShaderManager::ShaderInfo* info = GetShaderInfo(client_id);
775 if (!info) {
776 if (GetProgramInfo(client_id)) {
777 SetGLError(
778 GL_INVALID_OPERATION,
779 (std::string(function_name) +
780 ": program passed for shader").c_str());
781 } else {
782 SetGLError(GL_INVALID_VALUE,
783 (std::string(function_name) + ": unknown shader").c_str());
784 }
785 }
786 return info;
787 }
788
[email protected]a93bb842010-02-16 23:03:47789 // Creates a buffer info for the given buffer.
[email protected]ae51d192010-04-27 00:48:03790 void CreateBufferInfo(GLuint client_id, GLuint service_id) {
791 return buffer_manager()->CreateBufferInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47792 }
793
[email protected]07f54fcc2009-12-22 02:46:30794 // Gets the buffer info for the given buffer.
[email protected]ae51d192010-04-27 00:48:03795 BufferManager::BufferInfo* GetBufferInfo(GLuint client_id) {
796 BufferManager::BufferInfo* info =
797 buffer_manager()->GetBufferInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:10798 return info;
[email protected]1d32bc82010-01-13 22:06:46799 }
[email protected]07f54fcc2009-12-22 02:46:30800
[email protected]a93bb842010-02-16 23:03:47801 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
802 // on glDeleteBuffers so we can make sure the user does not try to render
803 // with deleted buffers.
[email protected]ae51d192010-04-27 00:48:03804 void RemoveBufferInfo(GLuint client_id);
[email protected]a93bb842010-02-16 23:03:47805
[email protected]a25fa872010-03-25 02:57:58806 // Creates a framebuffer info for the given framebuffer.
[email protected]ae51d192010-04-27 00:48:03807 void CreateFramebufferInfo(GLuint client_id, GLuint service_id) {
808 return framebuffer_manager()->CreateFramebufferInfo(client_id, service_id);
[email protected]a25fa872010-03-25 02:57:58809 }
810
811 // Gets the framebuffer info for the given framebuffer.
812 FramebufferManager::FramebufferInfo* GetFramebufferInfo(
[email protected]ae51d192010-04-27 00:48:03813 GLuint client_id) {
[email protected]a25fa872010-03-25 02:57:58814 FramebufferManager::FramebufferInfo* info =
[email protected]ae51d192010-04-27 00:48:03815 framebuffer_manager()->GetFramebufferInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:10816 return info;
[email protected]a25fa872010-03-25 02:57:58817 }
818
819 // Removes the framebuffer info for the given framebuffer.
[email protected]ae51d192010-04-27 00:48:03820 void RemoveFramebufferInfo(GLuint client_id) {
821 framebuffer_manager()->RemoveFramebufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58822 }
823
824 // Creates a renderbuffer info for the given renderbuffer.
[email protected]ae51d192010-04-27 00:48:03825 void CreateRenderbufferInfo(GLuint client_id, GLuint service_id) {
826 return renderbuffer_manager()->CreateRenderbufferInfo(
827 client_id, service_id);
[email protected]a25fa872010-03-25 02:57:58828 }
829
830 // Gets the renderbuffer info for the given renderbuffer.
831 RenderbufferManager::RenderbufferInfo* GetRenderbufferInfo(
[email protected]ae51d192010-04-27 00:48:03832 GLuint client_id) {
[email protected]a25fa872010-03-25 02:57:58833 RenderbufferManager::RenderbufferInfo* info =
[email protected]ae51d192010-04-27 00:48:03834 renderbuffer_manager()->GetRenderbufferInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:10835 return info;
[email protected]a25fa872010-03-25 02:57:58836 }
837
838 // Removes the renderbuffer info for the given renderbuffer.
[email protected]ae51d192010-04-27 00:48:03839 void RemoveRenderbufferInfo(GLuint client_id) {
840 renderbuffer_manager()->RemoveRenderbufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58841 }
842
[email protected]258a3313f2011-10-18 20:13:57843 void DoBindAttribLocation(GLuint client_id, GLuint index, const char* name);
844
[email protected]558847a2010-03-24 07:02:54845 error::Error GetAttribLocationHelper(
846 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
847 const std::string& name_str);
848
849 error::Error GetUniformLocationHelper(
850 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
851 const std::string& name_str);
852
[email protected]3916c97e2010-02-25 03:20:50853 // Helper for glShaderSource.
854 error::Error ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:03855 GLuint client_id, const char* data, uint32 data_size);
[email protected]07f54fcc2009-12-22 02:46:30856
[email protected]0d6bfdc2011-11-02 01:32:20857 // Clear any textures used by the current program.
858 bool ClearUnclearedTextures();
859
860 // Clear any uncleared level in texture.
861 // Returns false if there was a generated GL error.
862 bool ClearTexture(TextureManager::TextureInfo* info);
863
864 // Clears any uncleared attachments attached to the given frame buffer.
865 // Returns false if there was a generated GL error.
866 void ClearUnclearedAttachments(
[email protected]8e3e0662010-08-23 18:46:30867 GLenum target, FramebufferManager::FramebufferInfo* info);
[email protected]3a2e7c7b2010-08-06 01:12:28868
[email protected]0d6bfdc2011-11-02 01:32:20869 // overridden from GLES2Decoder
870 virtual bool ClearLevel(
871 unsigned service_id,
872 unsigned bind_target,
873 unsigned target,
874 int level,
875 unsigned format,
876 unsigned type,
877 int width,
878 int height);
879
[email protected]c007aa02010-09-02 22:22:40880 // Restore all GL state that affects clearing.
881 void RestoreClearState();
882
[email protected]3a2e7c7b2010-08-06 01:12:28883 // Remembers the state of some capabilities.
[email protected]297ca1c2011-06-20 23:08:46884 // Returns: true if glEnable/glDisable should actually be called.
885 bool SetCapabilityState(GLenum cap, bool enabled);
[email protected]3a2e7c7b2010-08-06 01:12:28886
[email protected]0d6bfdc2011-11-02 01:32:20887 // Check that the currently bound framebuffers are valid.
888 // Generates GL error if not.
889 bool CheckBoundFramebuffersValid(const char* func_name);
890
891 // Check if a framebuffer meets our requirements.
892 bool CheckFramebufferValid(
893 FramebufferManager::FramebufferInfo* framebuffer,
894 GLenum target,
895 const char* func_name);
[email protected]3a03a8f2011-03-19 00:51:27896
[email protected]939e7362010-05-13 20:49:10897 // Checks if the current program exists and is valid. If not generates the
898 // appropriate GL error. Returns true if the current program is in a usable
899 // state.
900 bool CheckCurrentProgram(const char* function_name);
901
902 // Checks if the current program exists and is valid and that location is not
903 // -1. If the current program is not valid generates the appropriate GL
904 // error. Returns true if the current program is in a usable state and
905 // location is not -1.
906 bool CheckCurrentProgramForUniform(GLint location, const char* function_name);
907
908 // Gets the type of a uniform for a location in the current program. Sets GL
909 // errors if the current program is not valid. Returns true if the current
[email protected]43c2f1f2011-03-25 18:35:36910 // program is valid and the location exists. Adjusts count so it
911 // does not overflow the uniform.
912 bool PrepForSetUniformByLocation(
913 GLint location, const char* function_name, GLenum* type, GLsizei* count);
[email protected]939e7362010-05-13 20:49:10914
[email protected]b177ae22011-11-01 03:29:11915 // Gets the service id for any simulated backbuffer fbo.
916 GLuint GetBackbufferServiceId();
917
[email protected]b273e432010-04-12 17:23:58918 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
919 bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
920
[email protected]96449d2c2009-11-25 00:01:32921 // Wrapper for glCreateProgram
[email protected]ae51d192010-04-27 00:48:03922 bool CreateProgramHelper(GLuint client_id);
[email protected]96449d2c2009-11-25 00:01:32923
924 // Wrapper for glCreateShader
[email protected]ae51d192010-04-27 00:48:03925 bool CreateShaderHelper(GLenum type, GLuint client_id);
[email protected]96449d2c2009-11-25 00:01:32926
[email protected]3916c97e2010-02-25 03:20:50927 // Wrapper for glActiveTexture
928 void DoActiveTexture(GLenum texture_unit);
929
[email protected]ae51d192010-04-27 00:48:03930 // Wrapper for glAttachShader
931 void DoAttachShader(GLuint client_program_id, GLint client_shader_id);
932
[email protected]96449d2c2009-11-25 00:01:32933 // Wrapper for glBindBuffer since we need to track the current targets.
934 void DoBindBuffer(GLenum target, GLuint buffer);
935
[email protected]86093972010-03-11 00:13:56936 // Wrapper for glBindFramebuffer since we need to track the current targets.
937 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
938
939 // Wrapper for glBindRenderbuffer since we need to track the current targets.
940 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
941
[email protected]a93bb842010-02-16 23:03:47942 // Wrapper for glBindTexture since we need to track the current targets.
943 void DoBindTexture(GLenum target, GLuint texture);
944
[email protected]8e3e0662010-08-23 18:46:30945 // Wrapper for glBlitFramebufferEXT.
946 void DoBlitFramebufferEXT(
947 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
948 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
949 GLbitfield mask, GLenum filter);
950
[email protected]36cef8ce2010-03-16 07:34:45951 // Wrapper for glBufferData.
[email protected]0c86dbf2010-03-05 08:14:11952 void DoBufferData(
953 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage);
954
[email protected]36cef8ce2010-03-16 07:34:45955 // Wrapper for glBufferSubData.
[email protected]0c86dbf2010-03-05 08:14:11956 void DoBufferSubData(
957 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
958
[email protected]36cef8ce2010-03-16 07:34:45959 // Wrapper for glCheckFramebufferStatus
960 GLenum DoCheckFramebufferStatus(GLenum target);
961
[email protected]3a03a8f2011-03-19 00:51:27962 // Wrapper for glClear
963 void DoClear(GLbitfield mask);
964
[email protected]3a2e7c7b2010-08-06 01:12:28965 // Wrappers for clear and mask settings functions.
966 void DoClearColor(
967 GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
968 void DoClearDepthf(GLclampf depth);
969 void DoClearStencil(GLint s);
970 void DoColorMask(
971 GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
972 void DoDepthMask(GLboolean depth);
973 void DoStencilMask(GLuint mask);
974 void DoStencilMaskSeparate(GLenum face, GLuint mask);
975
[email protected]45bf5152010-02-12 00:11:31976 // Wrapper for glCompileShader.
977 void DoCompileShader(GLuint shader);
978
[email protected]269200b12010-11-18 22:53:06979 // Helper for DeleteSharedIdsCHROMIUM commands.
980 void DoDeleteSharedIdsCHROMIUM(
981 GLuint namespace_id, GLsizei n, const GLuint* ids);
[email protected]066849e32010-05-03 19:14:10982
[email protected]ae51d192010-04-27 00:48:03983 // Wrapper for glDetachShader
984 void DoDetachShader(GLuint client_program_id, GLint client_shader_id);
985
[email protected]3a2e7c7b2010-08-06 01:12:28986 // Wrapper for glDisable
987 void DoDisable(GLenum cap);
988
[email protected]07f54fcc2009-12-22 02:46:30989 // Wrapper for glDisableVertexAttribArray.
990 void DoDisableVertexAttribArray(GLuint index);
991
[email protected]3a2e7c7b2010-08-06 01:12:28992 // Wrapper for glEnable
993 void DoEnable(GLenum cap);
994
[email protected]07f54fcc2009-12-22 02:46:30995 // Wrapper for glEnableVertexAttribArray.
996 void DoEnableVertexAttribArray(GLuint index);
997
[email protected]36cef8ce2010-03-16 07:34:45998 // Wrapper for glFramebufferRenderbufffer.
999 void DoFramebufferRenderbuffer(
1000 GLenum target, GLenum attachment, GLenum renderbuffertarget,
1001 GLuint renderbuffer);
1002
1003 // Wrapper for glFramebufferTexture2D.
1004 void DoFramebufferTexture2D(
1005 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
1006 GLint level);
1007
[email protected]a93bb842010-02-16 23:03:471008 // Wrapper for glGenerateMipmap
1009 void DoGenerateMipmap(GLenum target);
1010
[email protected]269200b12010-11-18 22:53:061011 // Helper for GenSharedIdsCHROMIUM commands.
1012 void DoGenSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:101013 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids);
1014
[email protected]b273e432010-04-12 17:23:581015 // Wrapper for DoGetBooleanv.
1016 void DoGetBooleanv(GLenum pname, GLboolean* params);
1017
1018 // Wrapper for DoGetFloatv.
1019 void DoGetFloatv(GLenum pname, GLfloat* params);
1020
[email protected]36cef8ce2010-03-16 07:34:451021 // Wrapper for glGetFramebufferAttachmentParameteriv.
1022 void DoGetFramebufferAttachmentParameteriv(
1023 GLenum target, GLenum attachment, GLenum pname, GLint* params);
1024
[email protected]a0c3e972010-04-21 00:49:131025 // Wrapper for glGetIntegerv.
[email protected]b273e432010-04-12 17:23:581026 void DoGetIntegerv(GLenum pname, GLint* params);
1027
[email protected]29a9eb52010-04-13 09:04:231028 // Gets the max value in a range in a buffer.
[email protected]269200b12010-11-18 22:53:061029 GLuint DoGetMaxValueInBufferCHROMIUM(
[email protected]29a9eb52010-04-13 09:04:231030 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset);
1031
[email protected]a0c3e972010-04-21 00:49:131032 // Wrapper for glGetProgramiv.
1033 void DoGetProgramiv(
1034 GLuint program_id, GLenum pname, GLint* params);
1035
[email protected]36cef8ce2010-03-16 07:34:451036 // Wrapper for glRenderbufferParameteriv.
1037 void DoGetRenderbufferParameteriv(
1038 GLenum target, GLenum pname, GLint* params);
1039
[email protected]ddd968b82010-03-02 00:44:291040 // Wrapper for glGetShaderiv
1041 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
1042
[email protected]b1122982010-05-17 23:04:241043 // Wrappers for glGetVertexAttrib.
1044 void DoGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params);
1045 void DoGetVertexAttribiv(GLuint index, GLenum pname, GLint *params);
1046
[email protected]1958e0e2010-04-22 05:17:151047 // Wrappers for glIsXXX functions.
1048 bool DoIsBuffer(GLuint client_id);
1049 bool DoIsFramebuffer(GLuint client_id);
1050 bool DoIsProgram(GLuint client_id);
1051 bool DoIsRenderbuffer(GLuint client_id);
1052 bool DoIsShader(GLuint client_id);
1053 bool DoIsTexture(GLuint client_id);
1054
[email protected]07f54fcc2009-12-22 02:46:301055 // Wrapper for glLinkProgram
1056 void DoLinkProgram(GLuint program);
1057
[email protected]269200b12010-11-18 22:53:061058 // Helper for RegisterSharedIdsCHROMIUM.
1059 void DoRegisterSharedIdsCHROMIUM(
1060 GLuint namespace_id, GLsizei n, const GLuint* ids);
[email protected]066849e32010-05-03 19:14:101061
[email protected]36cef8ce2010-03-16 07:34:451062 // Wrapper for glRenderbufferStorage.
1063 void DoRenderbufferStorage(
[email protected]ae51d192010-04-27 00:48:031064 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
[email protected]36cef8ce2010-03-16 07:34:451065
[email protected]8e3e0662010-08-23 18:46:301066 // Wrapper for glRenderbufferStorageMultisampleEXT.
1067 void DoRenderbufferStorageMultisample(
1068 GLenum target, GLsizei samples, GLenum internalformat,
1069 GLsizei width, GLsizei height);
1070
[email protected]b273e432010-04-12 17:23:581071 // Wrapper for glReleaseShaderCompiler.
1072 void DoReleaseShaderCompiler() { }
1073
[email protected]3916c97e2010-02-25 03:20:501074 // Wrappers for glTexParameter functions.
1075 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
1076 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
1077 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
1078 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
1079
1080 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1081 // spec only these 2 functions can be used to set sampler uniforms.
1082 void DoUniform1i(GLint location, GLint v0);
[email protected]939e7362010-05-13 20:49:101083 void DoUniform1iv(GLint location, GLsizei count, const GLint* value);
[email protected]43c2f1f2011-03-25 18:35:361084 void DoUniform2iv(GLint location, GLsizei count, const GLint* value);
1085 void DoUniform3iv(GLint location, GLsizei count, const GLint* value);
1086 void DoUniform4iv(GLint location, GLsizei count, const GLint* value);
[email protected]939e7362010-05-13 20:49:101087
1088 // Wrappers for glUniformfv because some drivers don't correctly accept
1089 // bool uniforms.
1090 void DoUniform1fv(GLint location, GLsizei count, const GLfloat* value);
1091 void DoUniform2fv(GLint location, GLsizei count, const GLfloat* value);
1092 void DoUniform3fv(GLint location, GLsizei count, const GLfloat* value);
1093 void DoUniform4fv(GLint location, GLsizei count, const GLfloat* value);
[email protected]3916c97e2010-02-25 03:20:501094
[email protected]43c2f1f2011-03-25 18:35:361095 void DoUniformMatrix2fv(
1096 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
1097 void DoUniformMatrix3fv(
1098 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
1099 void DoUniformMatrix4fv(
1100 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
1101
[email protected]b1122982010-05-17 23:04:241102 // Wrappers for glVertexAttrib??
1103 void DoVertexAttrib1f(GLuint index, GLfloat v0);
1104 void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
1105 void DoVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
1106 void DoVertexAttrib4f(
1107 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
1108 void DoVertexAttrib1fv(GLuint index, const GLfloat *v);
1109 void DoVertexAttrib2fv(GLuint index, const GLfloat *v);
1110 void DoVertexAttrib3fv(GLuint index, const GLfloat *v);
1111 void DoVertexAttrib4fv(GLuint index, const GLfloat *v);
1112
[email protected]07f54fcc2009-12-22 02:46:301113 // Wrapper for glUseProgram
1114 void DoUseProgram(GLuint program);
1115
[email protected]ae51d192010-04-27 00:48:031116 // Wrapper for glValidateProgram.
1117 void DoValidateProgram(GLuint program_client_id);
1118
[email protected]4e8a5b122010-05-08 22:00:101119 // Gets the number of values that will be returned by glGetXXX. Returns
1120 // false if pname is unknown.
1121 bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
1122
[email protected]96449d2c2009-11-25 00:01:321123 // Gets the GLError through our wrapper.
1124 GLenum GetGLError();
1125
[email protected]1002c2d2011-06-28 22:39:041126 // Gets the GLError and stores it in our wrapper. Effectively
1127 // this lets us peek at the error without losing it.
1128 GLenum PeekGLError();
1129
[email protected]07f54fcc2009-12-22 02:46:301130 // Copies the real GL errors to the wrapper. This is so we can
1131 // make sure there are no native GL errors before calling some GL function
1132 // so that on return we know any error generated was for that specific
1133 // command.
1134 void CopyRealGLErrorsToWrapper();
1135
[email protected]6217d392010-03-25 22:08:351136 // Clear all real GL errors. This is to prevent the client from seeing any
1137 // errors caused by GL calls that it was not responsible for issuing.
1138 void ClearRealGLErrors();
1139
[email protected]07f54fcc2009-12-22 02:46:301140 // Checks if the current program and vertex attributes are valid for drawing.
1141 bool IsDrawValid(GLuint max_vertex_accessed);
1142
[email protected]c13e1da62011-09-09 21:48:301143 // Returns true if successful, simulated will be true if attrib0 was
1144 // simulated.
1145 bool SimulateAttrib0(GLuint max_vertex_accessed, bool* simulated);
[email protected]b1122982010-05-17 23:04:241146 void RestoreStateForSimulatedAttrib0();
1147
[email protected]ef526492010-06-02 23:12:251148 // Returns true if textures were set.
1149 bool SetBlackTextureForNonRenderableTextures();
[email protected]3916c97e2010-02-25 03:20:501150 void RestoreStateForNonRenderableTextures();
1151
[email protected]8fbedc02010-11-18 18:43:401152 // Returns true if GL_FIXED attribs were simulated.
1153 bool SimulateFixedAttribs(GLuint max_vertex_accessed, bool* simulated);
1154 void RestoreStateForSimulatedFixedAttribs();
1155
[email protected]07f54fcc2009-12-22 02:46:301156 // Gets the buffer id for a given target.
[email protected]3916c97e2010-02-25 03:20:501157 BufferManager::BufferInfo* GetBufferInfoForTarget(GLenum target) {
[email protected]07f54fcc2009-12-22 02:46:301158 DCHECK(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER);
[email protected]3916c97e2010-02-25 03:20:501159 BufferManager::BufferInfo* info = target == GL_ARRAY_BUFFER ?
1160 bound_array_buffer_ : bound_element_array_buffer_;
[email protected]a0b78dc2011-11-11 10:43:101161 return info;
[email protected]07f54fcc2009-12-22 02:46:301162 }
1163
[email protected]a93bb842010-02-16 23:03:471164 // Gets the texture id for a given target.
[email protected]3916c97e2010-02-25 03:20:501165 TextureManager::TextureInfo* GetTextureInfoForTarget(GLenum target) {
1166 TextureUnit& unit = texture_units_[active_texture_unit_];
1167 TextureManager::TextureInfo* info = NULL;
[email protected]a93bb842010-02-16 23:03:471168 switch (target) {
1169 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:501170 info = unit.bound_texture_2d;
1171 break;
[email protected]a93bb842010-02-16 23:03:471172 case GL_TEXTURE_CUBE_MAP:
1173 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1174 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1175 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1176 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1177 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1178 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
[email protected]3916c97e2010-02-25 03:20:501179 info = unit.bound_texture_cube_map;
1180 break;
[email protected]61eeb33f2011-07-26 15:30:311181 case GL_TEXTURE_EXTERNAL_OES:
1182 info = unit.bound_texture_external_oes;
1183 break;
[email protected]1aef98132010-02-23 18:00:071184 // Note: If we ever support TEXTURE_RECTANGLE as a target, be sure to
1185 // track |texture_| with the currently bound TEXTURE_RECTANGLE texture,
1186 // because |texture_| is used by the FBO rendering mechanism for readback
1187 // to the bits that get sent to the browser.
[email protected]a93bb842010-02-16 23:03:471188 default:
1189 NOTREACHED();
[email protected]3916c97e2010-02-25 03:20:501190 return NULL;
[email protected]a93bb842010-02-16 23:03:471191 }
[email protected]a0b78dc2011-11-11 10:43:101192 return info;
[email protected]a93bb842010-02-16 23:03:471193 }
1194
[email protected]61eeb33f2011-07-26 15:30:311195 GLenum GetBindTargetForSamplerType(GLenum type) {
1196 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
1197 type == GL_SAMPLER_EXTERNAL_OES);
1198 return type == GL_SAMPLER_2D ? GL_TEXTURE_2D :
1199 (type == GL_SAMPLER_EXTERNAL_OES ? GL_TEXTURE_EXTERNAL_OES :
1200 GL_TEXTURE_CUBE_MAP);
1201 }
1202
[email protected]8e3e0662010-08-23 18:46:301203 // Gets the framebuffer info for a particular target.
1204 FramebufferManager::FramebufferInfo* GetFramebufferInfoForTarget(
1205 GLenum target) {
1206 FramebufferManager::FramebufferInfo* info = NULL;
1207 switch (target) {
1208 case GL_FRAMEBUFFER:
1209 case GL_DRAW_FRAMEBUFFER:
1210 info = bound_draw_framebuffer_;
1211 break;
1212 case GL_READ_FRAMEBUFFER:
1213 info = bound_read_framebuffer_;
1214 break;
1215 default:
1216 NOTREACHED();
1217 break;
1218 }
[email protected]a0b78dc2011-11-11 10:43:101219 return info;
[email protected]8e3e0662010-08-23 18:46:301220 }
1221
[email protected]0d6bfdc2011-11-02 01:32:201222 RenderbufferManager::RenderbufferInfo* GetRenderbufferInfoForTarget(
1223 GLenum target) {
1224 RenderbufferManager::RenderbufferInfo* info = NULL;
1225 switch (target) {
1226 case GL_RENDERBUFFER:
1227 info = bound_renderbuffer_;
1228 break;
1229 default:
1230 NOTREACHED();
1231 break;
1232 }
[email protected]a0b78dc2011-11-11 10:43:101233 return info;
[email protected]0d6bfdc2011-11-02 01:32:201234 }
1235
[email protected]f7b85372010-02-03 01:11:371236 // Validates the program and location for a glGetUniform call and returns
1237 // a SizeResult setup to receive the result. Returns true if glGetUniform
1238 // should be called.
1239 bool GetUniformSetup(
1240 GLuint program, GLint location,
1241 uint32 shm_id, uint32 shm_offset,
[email protected]939e7362010-05-13 20:49:101242 error::Error* error, GLuint* service_id, void** result,
1243 GLenum* result_type);
[email protected]f7b85372010-02-03 01:11:371244
[email protected]38d139d2011-07-14 00:38:431245 // Returns true if the context was just lost due to e.g. GL_ARB_robustness.
1246 bool WasContextLost();
1247
[email protected]96449d2c2009-11-25 00:01:321248 // Generate a member function prototype for each command in an automated and
1249 // typesafe way.
1250 #define GLES2_CMD_OP(name) \
[email protected]f7a64ee2010-02-01 22:24:141251 Error Handle ## name( \
[email protected]b9849abf2009-11-25 19:13:191252 uint32 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:321253 const gles2::name& args); \
1254
1255 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1256
1257 #undef GLES2_CMD_OP
1258
[email protected]2f2d7042010-04-14 21:45:581259 // The GL context this decoder renders to on behalf of the client.
[email protected]fbe20372011-06-01 01:46:381260 scoped_refptr<gfx::GLSurface> surface_;
1261 scoped_refptr<gfx::GLContext> context_;
[email protected]d37231fa2010-04-09 21:16:021262
[email protected]a3ded6d2010-10-19 06:44:391263 // The ContextGroup for this decoder uses to track resources.
1264 ContextGroup::Ref group_;
1265
[email protected]6217d392010-03-25 22:08:351266 // A parent decoder can access this decoders saved offscreen frame buffer.
1267 // The parent pointer is reset if the parent is destroyed.
1268 base::WeakPtr<GLES2DecoderImpl> parent_;
1269
[email protected]34ff8b0c2010-10-01 20:06:021270 // Current width and height of the offscreen frame buffer.
1271 gfx::Size offscreen_size_;
1272
[email protected]96449d2c2009-11-25 00:01:321273 // Current GL error bits.
1274 uint32 error_bits_;
1275
[email protected]96449d2c2009-11-25 00:01:321276 // Util to help with GL.
1277 GLES2Util util_;
1278
1279 // pack alignment as last set by glPixelStorei
1280 GLint pack_alignment_;
1281
1282 // unpack alignment as last set by glPixelStorei
1283 GLint unpack_alignment_;
1284
1285 // The currently bound array buffer. If this is 0 it is illegal to call
1286 // glVertexAttribPointer.
[email protected]3916c97e2010-02-25 03:20:501287 BufferManager::BufferInfo::Ref bound_array_buffer_;
[email protected]96449d2c2009-11-25 00:01:321288
1289 // The currently bound element array buffer. If this is 0 it is illegal
1290 // to call glDrawElements.
[email protected]3916c97e2010-02-25 03:20:501291 BufferManager::BufferInfo::Ref bound_element_array_buffer_;
[email protected]07f54fcc2009-12-22 02:46:301292
[email protected]f39f4b3f2010-05-12 17:04:081293 // Class that manages vertex attribs.
1294 VertexAttribManager vertex_attrib_manager_;
[email protected]07f54fcc2009-12-22 02:46:301295
[email protected]b1122982010-05-17 23:04:241296 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1297 GLuint attrib_0_buffer_id_;
1298
1299 // The value currently in attrib_0.
1300 VertexAttribManager::VertexAttribInfo::Vec4 attrib_0_value_;
1301
[email protected]fc753442011-02-04 19:49:491302 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1303 bool attrib_0_buffer_matches_value_;
1304
[email protected]b1122982010-05-17 23:04:241305 // The size of attrib 0.
1306 GLsizei attrib_0_size_;
1307
[email protected]8fbedc02010-11-18 18:43:401308 // The buffer used to simulate GL_FIXED attribs.
1309 GLuint fixed_attrib_buffer_id_;
1310
1311 // The size of fiixed attrib buffer.
1312 GLsizei fixed_attrib_buffer_size_;
1313
[email protected]3916c97e2010-02-25 03:20:501314 // Current active texture by 0 - n index.
1315 // In other words, if we call glActiveTexture(GL_TEXTURE2) this value would
1316 // be 2.
1317 GLuint active_texture_unit_;
[email protected]07f54fcc2009-12-22 02:46:301318
[email protected]3916c97e2010-02-25 03:20:501319 // Which textures are bound to texture units through glActiveTexture.
1320 scoped_array<TextureUnit> texture_units_;
[email protected]a93bb842010-02-16 23:03:471321
[email protected]3a2e7c7b2010-08-06 01:12:281322 // state saved for clearing so we can clear render buffers and then
1323 // restore to these values.
1324 GLclampf clear_red_;
1325 GLclampf clear_green_;
1326 GLclampf clear_blue_;
1327 GLclampf clear_alpha_;
1328 GLboolean mask_red_;
1329 GLboolean mask_green_;
1330 GLboolean mask_blue_;
1331 GLboolean mask_alpha_;
1332 GLint clear_stencil_;
1333 GLuint mask_stencil_front_;
1334 GLuint mask_stencil_back_;
1335 GLclampf clear_depth_;
1336 GLboolean mask_depth_;
1337 bool enable_scissor_test_;
[email protected]297ca1c2011-06-20 23:08:461338 bool enable_depth_test_;
1339 bool enable_stencil_test_;
1340 bool state_dirty_;
[email protected]3a2e7c7b2010-08-06 01:12:281341
[email protected]1d32bc82010-01-13 22:06:461342 // The program in use by glUseProgram
[email protected]3916c97e2010-02-25 03:20:501343 ProgramManager::ProgramInfo::Ref current_program_;
[email protected]07f54fcc2009-12-22 02:46:301344
[email protected]8e3e0662010-08-23 18:46:301345 // The currently bound framebuffers
1346 FramebufferManager::FramebufferInfo::Ref bound_read_framebuffer_;
1347 FramebufferManager::FramebufferInfo::Ref bound_draw_framebuffer_;
[email protected]86093972010-03-11 00:13:561348
1349 // The currently bound renderbuffer
[email protected]051b1372010-04-12 02:42:081350 RenderbufferManager::RenderbufferInfo::Ref bound_renderbuffer_;
[email protected]86093972010-03-11 00:13:561351
[email protected]b9363b22010-06-09 22:06:151352 // The offscreen frame buffer that the client renders to. With EGL, the
1353 // depth and stencil buffers are separate. With regular GL there is a single
1354 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1355 // offscreen_target_stencil_render_buffer_ is unused.
[email protected]6217d392010-03-25 22:08:351356 scoped_ptr<FrameBuffer> offscreen_target_frame_buffer_;
1357 scoped_ptr<Texture> offscreen_target_color_texture_;
[email protected]34ff8b0c2010-10-01 20:06:021358 scoped_ptr<RenderBuffer> offscreen_target_color_render_buffer_;
[email protected]b9363b22010-06-09 22:06:151359 scoped_ptr<RenderBuffer> offscreen_target_depth_render_buffer_;
1360 scoped_ptr<RenderBuffer> offscreen_target_stencil_render_buffer_;
[email protected]34ff8b0c2010-10-01 20:06:021361 GLenum offscreen_target_color_format_;
1362 GLenum offscreen_target_depth_format_;
1363 GLenum offscreen_target_stencil_format_;
1364 GLsizei offscreen_target_samples_;
[email protected]6217d392010-03-25 22:08:351365
[email protected]de26b3c2011-08-03 21:54:271366 // The copy that is saved when SwapBuffers is called.
[email protected]34ff8b0c2010-10-01 20:06:021367 scoped_ptr<FrameBuffer> offscreen_saved_frame_buffer_;
[email protected]6217d392010-03-25 22:08:351368 scoped_ptr<Texture> offscreen_saved_color_texture_;
[email protected]de26b3c2011-08-03 21:54:271369
1370 // The copy that is used as the destination for multi-sample resolves.
1371 scoped_ptr<FrameBuffer> offscreen_resolved_frame_buffer_;
1372 scoped_ptr<Texture> offscreen_resolved_color_texture_;
[email protected]97872062010-11-03 19:07:051373 GLenum offscreen_saved_color_format_;
[email protected]6217d392010-03-25 22:08:351374
[email protected]9d37f062011-11-22 01:24:521375 base::Callback<void(gfx::Size)> resize_callback_;
[email protected]22f320a2011-08-30 01:17:001376
[email protected]9d37f062011-11-22 01:24:521377 base::Closure swap_buffers_callback_;
[email protected]43f28f832010-02-03 02:28:481378
[email protected]b0af4f52011-09-28 22:04:421379 StreamTextureManager* stream_texture_manager_;
1380
[email protected]32fe9aa2011-01-21 23:47:131381 // The format of the back buffer_
1382 GLenum back_buffer_color_format_;
[email protected]297ca1c2011-06-20 23:08:461383 bool back_buffer_has_depth_;
1384 bool back_buffer_has_stencil_;
[email protected]32fe9aa2011-01-21 23:47:131385
[email protected]473c01ccb2011-06-07 01:33:301386 bool teximage2d_faster_than_texsubimage2d_;
1387 bool bufferdata_faster_than_buffersubdata_;
1388
[email protected]8eee29c2010-04-29 03:38:291389 // The last error message set.
1390 std::string last_error_;
1391
[email protected]a3a93e7b2010-08-28 00:48:561392 // The current decoder error.
1393 error::Error current_decoder_error_;
1394
[email protected]b1d2dcb2010-05-17 19:24:181395 bool use_shader_translator_;
[email protected]a550584e2010-09-17 18:01:451396 scoped_ptr<ShaderTranslator> vertex_translator_;
1397 scoped_ptr<ShaderTranslator> fragment_translator_;
[email protected]b1d2dcb2010-05-17 19:24:181398
[email protected]e82fb792011-09-22 00:33:291399 DisallowedFeatures disallowed_features_;
[email protected]c410da802011-03-14 19:17:411400
[email protected]915a59a12010-09-30 21:29:111401 // Cached from ContextGroup
[email protected]9438b012010-06-15 22:55:051402 const Validators* validators_;
[email protected]915a59a12010-09-30 21:29:111403 FeatureInfo* feature_info_;
[email protected]9438b012010-06-15 22:55:051404
[email protected]b493ee622011-04-13 23:52:001405 // This indicates all the following texSubImage2D calls that are part of the
1406 // failed texImage2D call should be ignored.
1407 bool tex_image_2d_failed_;
1408
[email protected]65225772011-05-12 21:10:241409 int frame_number_;
1410
[email protected]38d139d2011-07-14 00:38:431411 bool has_arb_robustness_;
1412 GLenum reset_status_;
1413
[email protected]75c023c2011-08-22 23:54:511414 bool needs_mac_nvidia_driver_workaround_;
[email protected]a2a0fe762011-09-20 00:59:121415 bool needs_glsl_built_in_function_emulation_;
[email protected]75c023c2011-08-22 23:54:511416
[email protected]f0d74742011-10-03 16:31:041417 // These flags are used to override the state of the shared feature_info_
1418 // member. Because the same FeatureInfo instance may be shared among many
1419 // contexts, the assumptions on the availablity of extensions in WebGL
1420 // contexts may be broken. These flags override the shared state to preserve
1421 // WebGL semantics.
1422 bool force_webgl_glsl_validation_;
1423 bool derivatives_explicitly_enabled_;
1424
[email protected]96449d2c2009-11-25 00:01:321425 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
1426};
1427
[email protected]6217d392010-03-25 22:08:351428ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(GLES2DecoderImpl* decoder)
1429 : decoder_(decoder) {
1430 decoder_->CopyRealGLErrorsToWrapper();
1431}
1432
1433ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
1434 decoder_->ClearRealGLErrors();
1435}
1436
1437ScopedTexture2DBinder::ScopedTexture2DBinder(GLES2DecoderImpl* decoder,
1438 GLuint id)
1439 : decoder_(decoder) {
1440 ScopedGLErrorSuppressor suppressor(decoder_);
1441
1442 // TODO(apatrick): Check if there are any other states that need to be reset
1443 // before binding a new texture.
1444 glActiveTexture(GL_TEXTURE0);
1445 glBindTexture(GL_TEXTURE_2D, id);
1446}
1447
1448ScopedTexture2DBinder::~ScopedTexture2DBinder() {
1449 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301450 decoder_->RestoreCurrentTexture2DBindings();
[email protected]6217d392010-03-25 22:08:351451}
1452
1453ScopedRenderBufferBinder::ScopedRenderBufferBinder(GLES2DecoderImpl* decoder,
1454 GLuint id)
1455 : decoder_(decoder) {
1456 ScopedGLErrorSuppressor suppressor(decoder_);
1457 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
1458}
1459
1460ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
1461 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301462 decoder_->RestoreCurrentRenderbufferBindings();
[email protected]6217d392010-03-25 22:08:351463}
1464
1465ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
1466 GLuint id)
1467 : decoder_(decoder) {
1468 ScopedGLErrorSuppressor suppressor(decoder_);
1469 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
1470}
1471
1472ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
1473 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301474 decoder_->RestoreCurrentFramebufferBindings();
[email protected]6217d392010-03-25 22:08:351475}
1476
[email protected]34ff8b0c2010-10-01 20:06:021477ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
[email protected]de26b3c2011-08-03 21:54:271478 GLES2DecoderImpl* decoder, bool enforce_internal_framebuffer, bool internal)
[email protected]c0701082011-04-20 00:34:521479 : decoder_(decoder) {
[email protected]34ff8b0c2010-10-01 20:06:021480 resolve_and_bind_ = (decoder_->offscreen_target_frame_buffer_.get() &&
1481 decoder_->IsOffscreenBufferMultisampled() &&
[email protected]c0701082011-04-20 00:34:521482 (!decoder_->bound_read_framebuffer_.get() ||
1483 enforce_internal_framebuffer));
[email protected]34ff8b0c2010-10-01 20:06:021484 if (!resolve_and_bind_)
1485 return;
1486
1487 ScopedGLErrorSuppressor suppressor(decoder_);
1488 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT,
1489 decoder_->offscreen_target_frame_buffer_->id());
[email protected]de26b3c2011-08-03 21:54:271490 GLuint targetid;
1491 if (internal) {
1492 if (!decoder_->offscreen_resolved_frame_buffer_.get()) {
1493 decoder_->offscreen_resolved_frame_buffer_.reset(
1494 new FrameBuffer(decoder_));
1495 decoder_->offscreen_resolved_frame_buffer_->Create();
1496 decoder_->offscreen_resolved_color_texture_.reset(new Texture(decoder_));
1497 decoder_->offscreen_resolved_color_texture_->Create();
1498
1499 DCHECK(decoder_->offscreen_saved_color_format_);
1500 decoder_->offscreen_resolved_color_texture_->AllocateStorage(
1501 decoder_->offscreen_size_, decoder_->offscreen_saved_color_format_);
1502
1503 decoder_->offscreen_resolved_frame_buffer_->AttachRenderTexture(
1504 decoder_->offscreen_resolved_color_texture_.get());
1505 if (decoder_->offscreen_resolved_frame_buffer_->CheckStatus() !=
1506 GL_FRAMEBUFFER_COMPLETE) {
1507 LOG(ERROR) << "ScopedResolvedFrameBufferBinder failed "
1508 << "because offscreen resolved FBO was incomplete.";
1509 return;
1510 }
1511 }
1512 targetid = decoder_->offscreen_resolved_frame_buffer_->id();
1513 } else {
1514 targetid = decoder_->offscreen_saved_frame_buffer_->id();
1515 }
1516 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, targetid);
[email protected]34ff8b0c2010-10-01 20:06:021517 const int width = decoder_->offscreen_size_.width();
1518 const int height = decoder_->offscreen_size_.height();
[email protected]8c3e68782010-10-27 16:41:181519 glDisable(GL_SCISSOR_TEST);
[email protected]34ff8b0c2010-10-01 20:06:021520 if (IsAngle()) {
1521 glBlitFramebufferANGLE(0, 0, width, height, 0, 0, width, height,
1522 GL_COLOR_BUFFER_BIT, GL_NEAREST);
1523 } else {
1524 glBlitFramebufferEXT(0, 0, width, height, 0, 0, width, height,
1525 GL_COLOR_BUFFER_BIT, GL_NEAREST);
1526 }
[email protected]de26b3c2011-08-03 21:54:271527 glBindFramebufferEXT(GL_FRAMEBUFFER, targetid);
[email protected]34ff8b0c2010-10-01 20:06:021528}
1529
1530ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
1531 if (!resolve_and_bind_)
1532 return;
1533
1534 ScopedGLErrorSuppressor suppressor(decoder_);
1535 decoder_->RestoreCurrentFramebufferBindings();
[email protected]8c3e68782010-10-27 16:41:181536 if (decoder_->enable_scissor_test_) {
1537 glEnable(GL_SCISSOR_TEST);
1538 }
[email protected]34ff8b0c2010-10-01 20:06:021539}
1540
[email protected]6217d392010-03-25 22:08:351541Texture::Texture(GLES2DecoderImpl* decoder)
1542 : decoder_(decoder),
[email protected]3a4d0c52011-06-29 23:11:581543 id_(0) {
[email protected]6217d392010-03-25 22:08:351544}
1545
1546Texture::~Texture() {
1547 // This does not destroy the render texture because that would require that
1548 // the associated GL context was current. Just check that it was explicitly
1549 // destroyed.
1550 DCHECK_EQ(id_, 0u);
1551}
1552
1553void Texture::Create() {
1554 ScopedGLErrorSuppressor suppressor(decoder_);
1555 Destroy();
1556 glGenTextures(1, &id_);
[email protected]3a4d0c52011-06-29 23:11:581557 ScopedTexture2DBinder binder(decoder_, id_);
1558 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1559 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1560 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1561 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
[email protected]62788802011-10-03 17:57:161562
1563 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
1564 // never called on an offscreen context, no data will ever be uploaded to the
1565 // saved offscreen color texture (it is deferred until to when SwapBuffers
1566 // is called). My idea is that some nvidia drivers might have a bug where
1567 // deleting a texture that has never been populated might cause a
1568 // crash.
1569 glTexImage2D(
1570 GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
[email protected]6217d392010-03-25 22:08:351571}
1572
[email protected]34ff8b0c2010-10-01 20:06:021573bool Texture::AllocateStorage(const gfx::Size& size, GLenum format) {
[email protected]6217d392010-03-25 22:08:351574 DCHECK_NE(id_, 0u);
1575 ScopedGLErrorSuppressor suppressor(decoder_);
1576 ScopedTexture2DBinder binder(decoder_, id_);
[email protected]6217d392010-03-25 22:08:351577
1578 glTexImage2D(GL_TEXTURE_2D,
1579 0, // mip level
[email protected]34ff8b0c2010-10-01 20:06:021580 format,
[email protected]6217d392010-03-25 22:08:351581 size.width(),
1582 size.height(),
1583 0, // border
[email protected]34ff8b0c2010-10-01 20:06:021584 format,
[email protected]6217d392010-03-25 22:08:351585 GL_UNSIGNED_BYTE,
1586 NULL);
1587
[email protected]d37231fa2010-04-09 21:16:021588 size_ = size;
1589
[email protected]6217d392010-03-25 22:08:351590 return glGetError() == GL_NO_ERROR;
1591}
1592
[email protected]3a4d0c52011-06-29 23:11:581593void Texture::Copy(const gfx::Size& size, GLenum format) {
[email protected]6217d392010-03-25 22:08:351594 DCHECK_NE(id_, 0u);
1595 ScopedGLErrorSuppressor suppressor(decoder_);
1596 ScopedTexture2DBinder binder(decoder_, id_);
1597 glCopyTexImage2D(GL_TEXTURE_2D,
1598 0, // level
[email protected]3a4d0c52011-06-29 23:11:581599 format,
[email protected]6217d392010-03-25 22:08:351600 0, 0,
1601 size.width(),
1602 size.height(),
1603 0); // border
1604}
1605
1606void Texture::Destroy() {
1607 if (id_ != 0) {
1608 ScopedGLErrorSuppressor suppressor(decoder_);
1609 glDeleteTextures(1, &id_);
1610 id_ = 0;
1611 }
1612}
1613
[email protected]97872062010-11-03 19:07:051614void Texture::Invalidate() {
1615 id_ = 0;
1616}
1617
[email protected]6217d392010-03-25 22:08:351618RenderBuffer::RenderBuffer(GLES2DecoderImpl* decoder)
1619 : decoder_(decoder),
1620 id_(0) {
1621}
1622
1623RenderBuffer::~RenderBuffer() {
1624 // This does not destroy the render buffer because that would require that
1625 // the associated GL context was current. Just check that it was explicitly
1626 // destroyed.
1627 DCHECK_EQ(id_, 0u);
1628}
1629
1630void RenderBuffer::Create() {
1631 ScopedGLErrorSuppressor suppressor(decoder_);
1632 Destroy();
1633 glGenRenderbuffersEXT(1, &id_);
1634}
1635
[email protected]34ff8b0c2010-10-01 20:06:021636bool RenderBuffer::AllocateStorage(const gfx::Size& size, GLenum format,
1637 GLsizei samples) {
[email protected]6217d392010-03-25 22:08:351638 ScopedGLErrorSuppressor suppressor(decoder_);
1639 ScopedRenderBufferBinder binder(decoder_, id_);
[email protected]34ff8b0c2010-10-01 20:06:021640 if (samples <= 1) {
1641 glRenderbufferStorageEXT(GL_RENDERBUFFER,
1642 format,
1643 size.width(),
1644 size.height());
1645 } else {
1646 if (IsAngle()) {
1647 glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER,
1648 samples,
1649 format,
1650 size.width(),
1651 size.height());
1652 } else {
1653 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER,
1654 samples,
1655 format,
1656 size.width(),
1657 size.height());
1658 }
1659 }
[email protected]6217d392010-03-25 22:08:351660 return glGetError() == GL_NO_ERROR;
1661}
1662
1663void RenderBuffer::Destroy() {
1664 if (id_ != 0) {
1665 ScopedGLErrorSuppressor suppressor(decoder_);
1666 glDeleteRenderbuffersEXT(1, &id_);
1667 id_ = 0;
1668 }
1669}
1670
[email protected]97872062010-11-03 19:07:051671void RenderBuffer::Invalidate() {
1672 id_ = 0;
1673}
1674
[email protected]6217d392010-03-25 22:08:351675FrameBuffer::FrameBuffer(GLES2DecoderImpl* decoder)
1676 : decoder_(decoder),
1677 id_(0) {
1678}
1679
1680FrameBuffer::~FrameBuffer() {
1681 // This does not destroy the frame buffer because that would require that
1682 // the associated GL context was current. Just check that it was explicitly
1683 // destroyed.
1684 DCHECK_EQ(id_, 0u);
1685}
1686
1687void FrameBuffer::Create() {
1688 ScopedGLErrorSuppressor suppressor(decoder_);
1689 Destroy();
1690 glGenFramebuffersEXT(1, &id_);
1691}
1692
1693void FrameBuffer::AttachRenderTexture(Texture* texture) {
1694 DCHECK_NE(id_, 0u);
1695 ScopedGLErrorSuppressor suppressor(decoder_);
1696 ScopedFrameBufferBinder binder(decoder_, id_);
1697 GLuint attach_id = texture ? texture->id() : 0;
1698 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
1699 GL_COLOR_ATTACHMENT0,
1700 GL_TEXTURE_2D,
1701 attach_id,
1702 0);
1703}
1704
[email protected]b9363b22010-06-09 22:06:151705void FrameBuffer::AttachRenderBuffer(GLenum target,
1706 RenderBuffer* render_buffer) {
[email protected]6217d392010-03-25 22:08:351707 DCHECK_NE(id_, 0u);
1708 ScopedGLErrorSuppressor suppressor(decoder_);
1709 ScopedFrameBufferBinder binder(decoder_, id_);
1710 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
1711 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
[email protected]b9363b22010-06-09 22:06:151712 target,
[email protected]6217d392010-03-25 22:08:351713 GL_RENDERBUFFER,
1714 attach_id);
1715}
1716
[email protected]6217d392010-03-25 22:08:351717void FrameBuffer::Destroy() {
1718 if (id_ != 0) {
1719 ScopedGLErrorSuppressor suppressor(decoder_);
1720 glDeleteFramebuffersEXT(1, &id_);
1721 id_ = 0;
1722 }
1723}
1724
[email protected]97872062010-11-03 19:07:051725void FrameBuffer::Invalidate() {
1726 id_ = 0;
1727}
1728
[email protected]6217d392010-03-25 22:08:351729GLenum FrameBuffer::CheckStatus() {
1730 DCHECK_NE(id_, 0u);
1731 ScopedGLErrorSuppressor suppressor(decoder_);
1732 ScopedFrameBufferBinder binder(decoder_, id_);
1733 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
1734}
1735
[email protected]aa7666122011-09-02 19:45:521736GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
1737 return new GLES2DecoderImpl(group);
[email protected]96449d2c2009-11-25 00:01:321738}
1739
[email protected]aa7666122011-09-02 19:45:521740GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
[email protected]a3ded6d2010-10-19 06:44:391741 : GLES2Decoder(),
[email protected]3b1ecc262011-08-03 22:49:571742 group_(group),
[email protected]96449d2c2009-11-25 00:01:321743 error_bits_(0),
[email protected]96449d2c2009-11-25 00:01:321744 pack_alignment_(4),
1745 unpack_alignment_(4),
[email protected]b1122982010-05-17 23:04:241746 attrib_0_buffer_id_(0),
[email protected]fc753442011-02-04 19:49:491747 attrib_0_buffer_matches_value_(true),
[email protected]b1122982010-05-17 23:04:241748 attrib_0_size_(0),
[email protected]8fbedc02010-11-18 18:43:401749 fixed_attrib_buffer_id_(0),
1750 fixed_attrib_buffer_size_(0),
[email protected]3916c97e2010-02-25 03:20:501751 active_texture_unit_(0),
[email protected]3a2e7c7b2010-08-06 01:12:281752 clear_red_(0),
1753 clear_green_(0),
1754 clear_blue_(0),
1755 clear_alpha_(0),
1756 mask_red_(true),
1757 mask_green_(true),
1758 mask_blue_(true),
1759 mask_alpha_(true),
1760 clear_stencil_(0),
1761 mask_stencil_front_(-1),
1762 mask_stencil_back_(-1),
1763 clear_depth_(1.0f),
1764 mask_depth_(true),
1765 enable_scissor_test_(false),
[email protected]297ca1c2011-06-20 23:08:461766 enable_depth_test_(false),
1767 enable_stencil_test_(false),
1768 state_dirty_(true),
[email protected]34ff8b0c2010-10-01 20:06:021769 offscreen_target_color_format_(0),
1770 offscreen_target_depth_format_(0),
1771 offscreen_target_stencil_format_(0),
1772 offscreen_target_samples_(0),
[email protected]97872062010-11-03 19:07:051773 offscreen_saved_color_format_(0),
[email protected]b0af4f52011-09-28 22:04:421774 stream_texture_manager_(NULL),
[email protected]32fe9aa2011-01-21 23:47:131775 back_buffer_color_format_(0),
[email protected]297ca1c2011-06-20 23:08:461776 back_buffer_has_depth_(false),
1777 back_buffer_has_stencil_(false),
[email protected]473c01ccb2011-06-07 01:33:301778 teximage2d_faster_than_texsubimage2d_(true),
1779 bufferdata_faster_than_buffersubdata_(true),
[email protected]a3a93e7b2010-08-28 00:48:561780 current_decoder_error_(error::kNoError),
[email protected]9438b012010-06-15 22:55:051781 use_shader_translator_(true),
[email protected]915a59a12010-09-30 21:29:111782 validators_(group_->feature_info()->validators()),
[email protected]b493ee622011-04-13 23:52:001783 feature_info_(group_->feature_info()),
[email protected]65225772011-05-12 21:10:241784 tex_image_2d_failed_(false),
[email protected]38d139d2011-07-14 00:38:431785 frame_number_(0),
1786 has_arb_robustness_(false),
[email protected]75c023c2011-08-22 23:54:511787 reset_status_(GL_NO_ERROR),
[email protected]a2a0fe762011-09-20 00:59:121788 needs_mac_nvidia_driver_workaround_(false),
[email protected]f0d74742011-10-03 16:31:041789 needs_glsl_built_in_function_emulation_(false),
1790 force_webgl_glsl_validation_(false),
1791 derivatives_explicitly_enabled_(false) {
[email protected]3b1ecc262011-08-03 22:49:571792 DCHECK(group);
1793
[email protected]b1122982010-05-17 23:04:241794 attrib_0_value_.v[0] = 0.0f;
1795 attrib_0_value_.v[1] = 0.0f;
1796 attrib_0_value_.v[2] = 0.0f;
1797 attrib_0_value_.v[3] = 1.0f;
[email protected]b9363b22010-06-09 22:06:151798
[email protected]c2f8c8402010-12-06 18:07:241799 // The shader translator is used for WebGL even when running on EGL
1800 // because additional restrictions are needed (like only enabling
1801 // GL_OES_standard_derivatives on demand). It is used for the unit
1802 // tests because
1803 // GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes the
1804 // empty string to CompileShader and this is not a valid shader.
1805 // TODO(apatrick): fix this test.
1806 if ((gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
[email protected]f0d74742011-10-03 16:31:041807 !feature_info_->feature_flags().chromium_webglsl &&
1808 !force_webgl_glsl_validation_) ||
[email protected]b9363b22010-06-09 22:06:151809 gfx::GetGLImplementation() == gfx::kGLImplementationMockGL) {
1810 use_shader_translator_ = false;
1811 }
[email protected]473c01ccb2011-06-07 01:33:301812
1813 // TODO(gman): Consider setting these based on GPU and/or driver.
1814 if (IsAngle()) {
1815 teximage2d_faster_than_texsubimage2d_ = false;
1816 bufferdata_faster_than_buffersubdata_ = false;
1817 }
[email protected]96449d2c2009-11-25 00:01:321818}
1819
[email protected]c410da802011-03-14 19:17:411820bool GLES2DecoderImpl::Initialize(
[email protected]fbe20372011-06-01 01:46:381821 const scoped_refptr<gfx::GLSurface>& surface,
1822 const scoped_refptr<gfx::GLContext>& context,
[email protected]c410da802011-03-14 19:17:411823 const gfx::Size& size,
[email protected]e82fb792011-09-22 00:33:291824 const DisallowedFeatures& disallowed_features,
[email protected]c410da802011-03-14 19:17:411825 const char* allowed_extensions,
[email protected]3c644d82011-06-20 19:58:241826 const std::vector<int32>& attribs) {
[email protected]4bedba72010-04-20 22:08:541827 DCHECK(context);
[email protected]66791e382010-07-14 20:48:301828 DCHECK(!context_.get());
1829
[email protected]fbe20372011-06-01 01:46:381830 // Take ownership of the GLSurface. TODO(apatrick): once the parent / child
1831 // context is retired, the decoder should not take an initial surface as
1832 // an argument to this function.
1833 // Maybe create a short lived offscreen GLSurface for the purpose of
1834 // initializing the decoder's GLContext.
1835 surface_ = surface;
[email protected]f62a5ab2011-05-23 20:34:151836
[email protected]66791e382010-07-14 20:48:301837 // Take ownership of the GLContext.
[email protected]fbe20372011-06-01 01:46:381838 context_ = context;
[email protected]d37231fa2010-04-09 21:16:021839
[email protected]246a70452010-03-05 21:53:501840 if (!MakeCurrent()) {
[email protected]d0498742010-09-20 20:27:011841 LOG(ERROR) << "GLES2DecoderImpl::Initialize failed because "
1842 << "MakeCurrent failed.";
[email protected]1871a092011-10-10 21:46:421843 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
[email protected]246a70452010-03-05 21:53:501844 Destroy();
1845 return false;
[email protected]eb54a562010-01-20 21:55:181846 }
1847
[email protected]e82fb792011-09-22 00:33:291848 if (!group_->Initialize(disallowed_features, allowed_extensions)) {
[email protected]09ddb91f2011-04-14 23:16:221849 LOG(ERROR) << "GpuScheduler::InitializeCommon failed because group "
[email protected]a3ded6d2010-10-19 06:44:391850 << "failed to initialize.";
[email protected]1871a092011-10-10 21:46:421851 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
[email protected]a3ded6d2010-10-19 06:44:391852 Destroy();
[email protected]ae1741092010-11-17 19:16:031853 return false;
[email protected]a3ded6d2010-10-19 06:44:391854 }
1855
[email protected]246a70452010-03-05 21:53:501856 CHECK_GL_ERROR();
[email protected]e82fb792011-09-22 00:33:291857 disallowed_features_ = disallowed_features;
[email protected]246a70452010-03-05 21:53:501858
[email protected]f39f4b3f2010-05-12 17:04:081859 vertex_attrib_manager_.Initialize(group_->max_vertex_attribs());
[email protected]876f6fee2010-08-02 23:10:321860
[email protected]302ce6d2011-07-07 23:28:111861 util_.set_num_compressed_texture_formats(
1862 validators_->compressed_texture_format.GetValues().size());
1863
[email protected]1071e572011-02-09 20:00:121864 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
1865 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
1866 // OpenGL ES 2.0 does not have this issue.
1867 glEnableVertexAttribArray(0);
1868 }
[email protected]b1122982010-05-17 23:04:241869 glGenBuffersARB(1, &attrib_0_buffer_id_);
1870 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
1871 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
1872 glBindBuffer(GL_ARRAY_BUFFER, 0);
[email protected]8fbedc02010-11-18 18:43:401873 glGenBuffersARB(1, &fixed_attrib_buffer_id_);
[email protected]f39f4b3f2010-05-12 17:04:081874
[email protected]246a70452010-03-05 21:53:501875 texture_units_.reset(
1876 new TextureUnit[group_->max_texture_units()]);
[email protected]1958e0e2010-04-22 05:17:151877 for (uint32 tt = 0; tt < group_->max_texture_units(); ++tt) {
[email protected]00f893d2010-08-24 18:55:491878 glActiveTexture(GL_TEXTURE0 + tt);
[email protected]61eeb33f2011-07-26 15:30:311879 // We want the last bind to be 2D.
1880 TextureManager::TextureInfo* info;
1881 if (feature_info_->feature_flags().oes_egl_image_external) {
1882 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_EXTERNAL_OES);
1883 texture_units_[tt].bound_texture_external_oes = info;
1884 glBindTexture(GL_TEXTURE_EXTERNAL_OES, info->service_id());
1885 }
1886 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
[email protected]00f893d2010-08-24 18:55:491887 texture_units_[tt].bound_texture_cube_map = info;
1888 glBindTexture(GL_TEXTURE_CUBE_MAP, info->service_id());
1889 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
1890 texture_units_[tt].bound_texture_2d = info;
1891 glBindTexture(GL_TEXTURE_2D, info->service_id());
[email protected]1958e0e2010-04-22 05:17:151892 }
[email protected]00f893d2010-08-24 18:55:491893 glActiveTexture(GL_TEXTURE0);
[email protected]246a70452010-03-05 21:53:501894 CHECK_GL_ERROR();
1895
[email protected]297ca1c2011-06-20 23:08:461896 ContextCreationAttribParser attrib_parser;
1897 if (!attrib_parser.Parse(attribs))
1898 return false;
[email protected]41c56362011-06-14 16:47:431899
[email protected]297ca1c2011-06-20 23:08:461900 // These are NOT if the back buffer has these proprorties. They are
1901 // if we want the command buffer to enforce them regardless of what
1902 // the real backbuffer is assuming the real back buffer gives us more than
1903 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
1904 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
1905 // can't do anything about that.
1906
1907 GLint v = 0;
1908 glGetIntegerv(GL_ALPHA_BITS, &v);
1909 // This checks if the user requested RGBA and we have RGBA then RGBA. If the
1910 // user requested RGB then RGB. If the user did not specify a preference than
1911 // use whatever we were given. Same for DEPTH and STENCIL.
1912 back_buffer_color_format_ =
1913 (attrib_parser.alpha_size_ != 0 && v > 0) ? GL_RGBA : GL_RGB;
1914 glGetIntegerv(GL_DEPTH_BITS, &v);
1915 back_buffer_has_depth_ = attrib_parser.depth_size_ != 0 && v > 0;
1916 glGetIntegerv(GL_STENCIL_BITS, &v);
1917 back_buffer_has_stencil_ = attrib_parser.stencil_size_ != 0 && v > 0;
1918
1919 if (surface_->IsOffscreen()) {
[email protected]34ff8b0c2010-10-01 20:06:021920 if (attrib_parser.samples_ > 0 && attrib_parser.sample_buffers_ > 0 &&
[email protected]53862ed2010-10-25 19:22:541921 (context_->HasExtension("GL_EXT_framebuffer_multisample") ||
[email protected]34ff8b0c2010-10-01 20:06:021922 context_->HasExtension("GL_ANGLE_framebuffer_multisample"))) {
1923 // Per ext_framebuffer_multisample spec, need max bound on sample count.
[email protected]0b1e9d72010-11-11 16:29:431924 // max_sample_count must be initialized to a sane value. If
1925 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
1926 GLint max_sample_count = 1;
[email protected]34ff8b0c2010-10-01 20:06:021927 glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count);
1928 offscreen_target_samples_ = std::min(attrib_parser.samples_,
1929 max_sample_count);
1930 } else {
1931 offscreen_target_samples_ = 1;
1932 }
1933
1934 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
1935 const bool rgb8_supported =
1936 context_->HasExtension("GL_OES_rgb8_rgba8");
1937 // The only available default render buffer formats in GLES2 have very
1938 // little precision. Don't enable multisampling unless 8-bit render
1939 // buffer formats are available--instead fall back to 8-bit textures.
1940 if (rgb8_supported && offscreen_target_samples_ > 1) {
1941 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
1942 GL_RGBA8 : GL_RGB8;
1943 } else {
1944 offscreen_target_samples_ = 1;
1945 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
1946 GL_RGBA : GL_RGB;
1947 }
1948
1949 // ANGLE only supports packed depth/stencil formats, so use it if it is
1950 // available.
1951 const bool depth24_stencil8_supported =
1952 context_->HasExtension("GL_OES_packed_depth_stencil");
[email protected]d366c482010-10-20 00:11:271953 VLOG(1) << "GL_OES_packed_depth_stencil "
1954 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
[email protected]71ee3642010-10-14 18:08:001955 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
1956 depth24_stencil8_supported) {
[email protected]34ff8b0c2010-10-01 20:06:021957 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
1958 offscreen_target_stencil_format_ = 0;
1959 } else {
1960 // It may be the case that this depth/stencil combination is not
1961 // supported, but this will be checked later by CheckFramebufferStatus.
1962 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
1963 GL_DEPTH_COMPONENT16 : 0;
1964 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
1965 GL_STENCIL_INDEX8 : 0;
1966 }
1967 } else {
1968 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
1969 GL_RGBA : GL_RGB;
1970
1971 // If depth is requested at all, use the packed depth stencil format if
1972 // it's available, as some desktop GL drivers don't support any non-packed
1973 // formats for depth attachments.
1974 const bool depth24_stencil8_supported =
1975 context_->HasExtension("GL_EXT_packed_depth_stencil");
[email protected]d366c482010-10-20 00:11:271976 VLOG(1) << "GL_EXT_packed_depth_stencil "
1977 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
[email protected]34ff8b0c2010-10-01 20:06:021978
[email protected]71ee3642010-10-14 18:08:001979 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
1980 depth24_stencil8_supported) {
[email protected]34ff8b0c2010-10-01 20:06:021981 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
1982 offscreen_target_stencil_format_ = 0;
1983 } else {
1984 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
1985 GL_DEPTH_COMPONENT : 0;
1986 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
1987 GL_STENCIL_INDEX : 0;
1988 }
1989 }
1990
[email protected]97872062010-11-03 19:07:051991 offscreen_saved_color_format_ = attrib_parser.alpha_size_ > 0 ?
1992 GL_RGBA : GL_RGB;
1993
[email protected]6217d392010-03-25 22:08:351994 // Create the target frame buffer. This is the one that the client renders
1995 // directly to.
1996 offscreen_target_frame_buffer_.reset(new FrameBuffer(this));
1997 offscreen_target_frame_buffer_->Create();
[email protected]34ff8b0c2010-10-01 20:06:021998 // Due to GLES2 format limitations, either the color texture (for
1999 // non-multisampling) or the color render buffer (for multisampling) will be
2000 // attached to the offscreen frame buffer. The render buffer has more
2001 // limited formats available to it, but the texture can't do multisampling.
2002 if (IsOffscreenBufferMultisampled()) {
2003 offscreen_target_color_render_buffer_.reset(new RenderBuffer(this));
2004 offscreen_target_color_render_buffer_->Create();
2005 } else {
2006 offscreen_target_color_texture_.reset(new Texture(this));
2007 offscreen_target_color_texture_->Create();
2008 }
2009 offscreen_target_depth_render_buffer_.reset(new RenderBuffer(this));
[email protected]b9363b22010-06-09 22:06:152010 offscreen_target_depth_render_buffer_->Create();
[email protected]34ff8b0c2010-10-01 20:06:022011 offscreen_target_stencil_render_buffer_.reset(new RenderBuffer(this));
[email protected]b9363b22010-06-09 22:06:152012 offscreen_target_stencil_render_buffer_->Create();
[email protected]6217d392010-03-25 22:08:352013
2014 // Create the saved offscreen texture. The target frame buffer is copied
2015 // here when SwapBuffers is called.
[email protected]34ff8b0c2010-10-01 20:06:022016 offscreen_saved_frame_buffer_.reset(new FrameBuffer(this));
2017 offscreen_saved_frame_buffer_->Create();
2018 //
[email protected]6217d392010-03-25 22:08:352019 offscreen_saved_color_texture_.reset(new Texture(this));
2020 offscreen_saved_color_texture_->Create();
2021
[email protected]6217d392010-03-25 22:08:352022 // Allocate the render buffers at their initial size and check the status
2023 // of the frame buffers is okay.
[email protected]799b4b22011-08-22 17:09:592024 if (!ResizeOffscreenFrameBuffer(size)) {
[email protected]d0498742010-09-20 20:27:012025 LOG(ERROR) << "Could not allocate offscreen buffer storage.";
[email protected]6217d392010-03-25 22:08:352026 Destroy();
2027 return false;
2028 }
2029
2030 // Bind to the new default frame buffer (the offscreen target frame buffer).
2031 // This should now be associated with ID zero.
2032 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2033 }
2034
[email protected]76a0ee102010-04-07 21:03:042035 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2036 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2037 // isn't well documented; it was discovered in the Khronos OpenGL ES
[email protected]c1d82b62010-09-20 22:43:372038 // mailing list archives. It also implicitly enables the desktop GL
2039 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2040 // variable in fragment shaders.
[email protected]b9363b22010-06-09 22:06:152041 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2042 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
[email protected]c1d82b62010-09-20 22:43:372043 glEnable(GL_POINT_SPRITE);
[email protected]b9363b22010-06-09 22:06:152044 }
[email protected]de17df392010-04-23 21:09:412045
[email protected]38d139d2011-07-14 00:38:432046 has_arb_robustness_ = context->HasExtension("GL_ARB_robustness");
2047
[email protected]e82fb792011-09-22 00:33:292048 if (!disallowed_features_.driver_bug_workarounds) {
[email protected]75c023c2011-08-22 23:54:512049#if defined(OS_MACOSX)
[email protected]a2a0fe762011-09-20 00:59:122050 const char* vendor_str = reinterpret_cast<const char*>(
2051 glGetString(GL_VENDOR));
2052 needs_mac_nvidia_driver_workaround_ =
2053 vendor_str && strstr(vendor_str, "NVIDIA");
2054 needs_glsl_built_in_function_emulation_ =
2055 vendor_str && (strstr(vendor_str, "ATI") || strstr(vendor_str, "AMD"));
2056#elif defined(OS_WIN)
2057 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
2058 needs_glsl_built_in_function_emulation_ = true;
[email protected]75c023c2011-08-22 23:54:512059#endif
[email protected]a2a0fe762011-09-20 00:59:122060 }
[email protected]75c023c2011-08-22 23:54:512061
[email protected]c2f8c8402010-12-06 18:07:242062 if (!InitializeShaderTranslator()) {
2063 return false;
[email protected]de17df392010-04-23 21:09:412064 }
[email protected]76a0ee102010-04-07 21:03:042065
[email protected]246a70452010-03-05 21:53:502066 return true;
[email protected]96449d2c2009-11-25 00:01:322067}
2068
[email protected]302ce6d2011-07-07 23:28:112069void GLES2DecoderImpl::UpdateCapabilities() {
2070 util_.set_num_compressed_texture_formats(
2071 validators_->compressed_texture_format.GetValues().size());
2072 util_.set_num_shader_binary_formats(
2073 validators_->shader_binary_format.GetValues().size());
2074}
2075
[email protected]c2f8c8402010-12-06 18:07:242076bool GLES2DecoderImpl::InitializeShaderTranslator() {
2077 // Re-check the state of use_shader_translator_ each time this is called.
2078 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
[email protected]f0d74742011-10-03 16:31:042079 (feature_info_->feature_flags().chromium_webglsl ||
2080 force_webgl_glsl_validation_) &&
[email protected]c2f8c8402010-12-06 18:07:242081 !use_shader_translator_) {
2082 use_shader_translator_ = true;
2083 }
2084 if (!use_shader_translator_) {
2085 return true;
2086 }
2087 ShBuiltInResources resources;
2088 ShInitBuiltInResources(&resources);
2089 resources.MaxVertexAttribs = group_->max_vertex_attribs();
2090 resources.MaxVertexUniformVectors =
2091 group_->max_vertex_uniform_vectors();
2092 resources.MaxVaryingVectors = group_->max_varying_vectors();
2093 resources.MaxVertexTextureImageUnits =
2094 group_->max_vertex_texture_image_units();
2095 resources.MaxCombinedTextureImageUnits = group_->max_texture_units();
2096 resources.MaxTextureImageUnits = group_->max_texture_image_units();
2097 resources.MaxFragmentUniformVectors =
2098 group_->max_fragment_uniform_vectors();
2099 resources.MaxDrawBuffers = 1;
[email protected]f0d74742011-10-03 16:31:042100
2101 if (force_webgl_glsl_validation_) {
2102 resources.OES_standard_derivatives = derivatives_explicitly_enabled_;
2103 } else {
2104 resources.OES_standard_derivatives =
2105 feature_info_->feature_flags().oes_standard_derivatives ? 1 : 0;
2106 }
2107
[email protected]c2f8c8402010-12-06 18:07:242108 vertex_translator_.reset(new ShaderTranslator);
[email protected]f0d74742011-10-03 16:31:042109 ShShaderSpec shader_spec = force_webgl_glsl_validation_ ||
2110 feature_info_->feature_flags().chromium_webglsl ?
2111 SH_WEBGL_SPEC : SH_GLES2_SPEC;
[email protected]a2a0fe762011-09-20 00:59:122112 ShaderTranslatorInterface::GlslImplementationType implementation_type =
2113 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 ?
2114 ShaderTranslatorInterface::kGlslES : ShaderTranslatorInterface::kGlsl;
2115 ShaderTranslatorInterface::GlslBuiltInFunctionBehavior function_behavior =
2116 needs_glsl_built_in_function_emulation_ ?
2117 ShaderTranslatorInterface::kGlslBuiltInFunctionEmulated :
2118 ShaderTranslatorInterface::kGlslBuiltInFunctionOriginal;
[email protected]c2f8c8402010-12-06 18:07:242119 if (!vertex_translator_->Init(
[email protected]a2a0fe762011-09-20 00:59:122120 SH_VERTEX_SHADER, shader_spec, &resources,
2121 implementation_type, function_behavior)) {
[email protected]c2f8c8402010-12-06 18:07:242122 LOG(ERROR) << "Could not initialize vertex shader translator.";
2123 Destroy();
2124 return false;
2125 }
2126 fragment_translator_.reset(new ShaderTranslator);
2127 if (!fragment_translator_->Init(
[email protected]a2a0fe762011-09-20 00:59:122128 SH_FRAGMENT_SHADER, shader_spec, &resources,
2129 implementation_type, function_behavior)) {
[email protected]c2f8c8402010-12-06 18:07:242130 LOG(ERROR) << "Could not initialize fragment shader translator.";
2131 Destroy();
2132 return false;
2133 }
2134 return true;
2135}
2136
[email protected]ae51d192010-04-27 00:48:032137bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
[email protected]a93bb842010-02-16 23:03:472138 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:032139 if (GetBufferInfo(client_ids[ii])) {
2140 return false;
2141 }
2142 }
2143 scoped_array<GLuint> service_ids(new GLuint[n]);
2144 glGenBuffersARB(n, service_ids.get());
2145 for (GLsizei ii = 0; ii < n; ++ii) {
2146 CreateBufferInfo(client_ids[ii], service_ids[ii]);
2147 }
2148 return true;
2149}
2150
2151bool GLES2DecoderImpl::GenFramebuffersHelper(
2152 GLsizei n, const GLuint* client_ids) {
2153 for (GLsizei ii = 0; ii < n; ++ii) {
2154 if (GetFramebufferInfo(client_ids[ii])) {
2155 return false;
2156 }
2157 }
2158 scoped_array<GLuint> service_ids(new GLuint[n]);
2159 glGenFramebuffersEXT(n, service_ids.get());
2160 for (GLsizei ii = 0; ii < n; ++ii) {
2161 CreateFramebufferInfo(client_ids[ii], service_ids[ii]);
2162 }
2163 return true;
2164}
2165
2166bool GLES2DecoderImpl::GenRenderbuffersHelper(
2167 GLsizei n, const GLuint* client_ids) {
2168 for (GLsizei ii = 0; ii < n; ++ii) {
2169 if (GetRenderbufferInfo(client_ids[ii])) {
2170 return false;
2171 }
2172 }
2173 scoped_array<GLuint> service_ids(new GLuint[n]);
2174 glGenRenderbuffersEXT(n, service_ids.get());
2175 for (GLsizei ii = 0; ii < n; ++ii) {
2176 CreateRenderbufferInfo(client_ids[ii], service_ids[ii]);
2177 }
2178 return true;
2179}
2180
2181bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
2182 for (GLsizei ii = 0; ii < n; ++ii) {
2183 if (GetTextureInfo(client_ids[ii])) {
2184 return false;
2185 }
2186 }
2187 scoped_array<GLuint> service_ids(new GLuint[n]);
2188 glGenTextures(n, service_ids.get());
2189 for (GLsizei ii = 0; ii < n; ++ii) {
2190 CreateTextureInfo(client_ids[ii], service_ids[ii]);
2191 }
2192 return true;
2193}
2194
2195void GLES2DecoderImpl::DeleteBuffersHelper(
2196 GLsizei n, const GLuint* client_ids) {
2197 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]a0b78dc2011-11-11 10:43:102198 BufferManager::BufferInfo* buffer = GetBufferInfo(client_ids[ii]);
2199 if (buffer && !buffer->IsDeleted()) {
2200 vertex_attrib_manager_.Unbind(buffer);
2201 if (bound_array_buffer_ == buffer) {
2202 bound_array_buffer_ = NULL;
2203 }
2204 if (bound_element_array_buffer_ == buffer) {
2205 bound_element_array_buffer_ = NULL;
2206 }
2207 GLuint service_id = buffer->service_id();
[email protected]ae51d192010-04-27 00:48:032208 glDeleteBuffersARB(1, &service_id);
2209 RemoveBufferInfo(client_ids[ii]);
2210 }
[email protected]a93bb842010-02-16 23:03:472211 }
[email protected]07f54fcc2009-12-22 02:46:302212}
2213
[email protected]ae51d192010-04-27 00:48:032214void GLES2DecoderImpl::DeleteFramebuffersHelper(
2215 GLsizei n, const GLuint* client_ids) {
[email protected]b177ae22011-11-01 03:29:112216 bool supports_seperate_framebuffer_binds =
2217 feature_info_->feature_flags().chromium_framebuffer_multisample;
2218
[email protected]a25fa872010-03-25 02:57:582219 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]a0b78dc2011-11-11 10:43:102220 FramebufferManager::FramebufferInfo* framebuffer =
[email protected]ae51d192010-04-27 00:48:032221 GetFramebufferInfo(client_ids[ii]);
[email protected]a0b78dc2011-11-11 10:43:102222 if (framebuffer && !framebuffer->IsDeleted()) {
2223 if (framebuffer == bound_draw_framebuffer_) {
[email protected]297ca1c2011-06-20 23:08:462224 bound_draw_framebuffer_ = NULL;
2225 state_dirty_ = true;
[email protected]b177ae22011-11-01 03:29:112226 GLenum target = supports_seperate_framebuffer_binds ?
2227 GL_DRAW_FRAMEBUFFER : GL_FRAMEBUFFER;
2228 glBindFramebufferEXT(target, GetBackbufferServiceId());
2229 }
[email protected]a0b78dc2011-11-11 10:43:102230 if (framebuffer == bound_read_framebuffer_) {
[email protected]b177ae22011-11-01 03:29:112231 bound_read_framebuffer_ = NULL;
2232 GLenum target = supports_seperate_framebuffer_binds ?
2233 GL_READ_FRAMEBUFFER : GL_FRAMEBUFFER;
2234 glBindFramebufferEXT(target, GetBackbufferServiceId());
[email protected]297ca1c2011-06-20 23:08:462235 }
[email protected]a0b78dc2011-11-11 10:43:102236 GLuint service_id = framebuffer->service_id();
[email protected]ae51d192010-04-27 00:48:032237 glDeleteFramebuffersEXT(1, &service_id);
2238 RemoveFramebufferInfo(client_ids[ii]);
2239 }
[email protected]a25fa872010-03-25 02:57:582240 }
[email protected]07f54fcc2009-12-22 02:46:302241}
2242
[email protected]ae51d192010-04-27 00:48:032243void GLES2DecoderImpl::DeleteRenderbuffersHelper(
2244 GLsizei n, const GLuint* client_ids) {
[email protected]a0b78dc2011-11-11 10:43:102245 bool supports_seperate_framebuffer_binds =
2246 feature_info_->feature_flags().chromium_framebuffer_multisample;
[email protected]a25fa872010-03-25 02:57:582247 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]a0b78dc2011-11-11 10:43:102248 RenderbufferManager::RenderbufferInfo* renderbuffer =
[email protected]ae51d192010-04-27 00:48:032249 GetRenderbufferInfo(client_ids[ii]);
[email protected]a0b78dc2011-11-11 10:43:102250 if (renderbuffer && !renderbuffer->IsDeleted()) {
2251 if (bound_renderbuffer_ == renderbuffer) {
2252 bound_renderbuffer_ = NULL;
2253 }
2254 // Unbind from current framebuffers.
2255 if (supports_seperate_framebuffer_binds) {
2256 if (bound_read_framebuffer_) {
2257 bound_read_framebuffer_->UnbindRenderbuffer(
2258 GL_READ_FRAMEBUFFER, renderbuffer);
2259 }
2260 if (bound_draw_framebuffer_) {
2261 bound_draw_framebuffer_->UnbindRenderbuffer(
2262 GL_DRAW_FRAMEBUFFER, renderbuffer);
2263 }
2264 } else {
2265 if (bound_draw_framebuffer_) {
2266 bound_draw_framebuffer_->UnbindRenderbuffer(
2267 GL_FRAMEBUFFER, renderbuffer);
2268 }
2269 }
[email protected]297ca1c2011-06-20 23:08:462270 state_dirty_ = true;
[email protected]a0b78dc2011-11-11 10:43:102271 GLuint service_id = renderbuffer->service_id();
[email protected]ae51d192010-04-27 00:48:032272 glDeleteRenderbuffersEXT(1, &service_id);
2273 RemoveRenderbufferInfo(client_ids[ii]);
2274 }
[email protected]a25fa872010-03-25 02:57:582275 }
[email protected]07f54fcc2009-12-22 02:46:302276}
2277
[email protected]ae51d192010-04-27 00:48:032278void GLES2DecoderImpl::DeleteTexturesHelper(
2279 GLsizei n, const GLuint* client_ids) {
[email protected]a0b78dc2011-11-11 10:43:102280 bool supports_seperate_framebuffer_binds =
2281 feature_info_->feature_flags().chromium_framebuffer_multisample;
[email protected]a93bb842010-02-16 23:03:472282 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]a0b78dc2011-11-11 10:43:102283 TextureManager::TextureInfo* texture = GetTextureInfo(client_ids[ii]);
2284 if (texture && !texture->IsDeleted()) {
2285 if (texture->IsAttachedToFramebuffer()) {
[email protected]297ca1c2011-06-20 23:08:462286 state_dirty_ = true;
2287 }
[email protected]a0b78dc2011-11-11 10:43:102288 // Unbind texture from texture units.
2289 for (size_t jj = 0; jj < group_->max_texture_units(); ++jj) {
2290 texture_units_[ii].Unbind(texture);
2291 }
2292 // Unbind from current framebuffers.
2293 if (supports_seperate_framebuffer_binds) {
2294 if (bound_read_framebuffer_) {
2295 bound_read_framebuffer_->UnbindTexture(GL_READ_FRAMEBUFFER, texture);
2296 }
2297 if (bound_draw_framebuffer_) {
2298 bound_draw_framebuffer_->UnbindTexture(GL_DRAW_FRAMEBUFFER, texture);
2299 }
2300 } else {
2301 if (bound_draw_framebuffer_) {
2302 bound_draw_framebuffer_->UnbindTexture(GL_FRAMEBUFFER, texture);
2303 }
2304 }
2305 GLuint service_id = texture->service_id();
2306 if (texture->IsStreamTexture() && stream_texture_manager_) {
[email protected]b0af4f52011-09-28 22:04:422307 stream_texture_manager_->DestroyStreamTexture(service_id);
2308 }
[email protected]5f4f2a732011-07-30 00:47:552309 glDeleteTextures(1, &service_id);
[email protected]ae51d192010-04-27 00:48:032310 RemoveTextureInfo(client_ids[ii]);
2311 }
[email protected]a93bb842010-02-16 23:03:472312 }
[email protected]07f54fcc2009-12-22 02:46:302313}
2314
[email protected]43f28f832010-02-03 02:28:482315// } // anonymous namespace
[email protected]96449d2c2009-11-25 00:01:322316
[email protected]eb54a562010-01-20 21:55:182317bool GLES2DecoderImpl::MakeCurrent() {
[email protected]38d139d2011-07-14 00:38:432318 bool result = context_.get() ? context_->MakeCurrent(surface_.get()) : false;
2319 if (result && WasContextLost()) {
2320 LOG(ERROR) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
2321 result = false;
2322 }
2323
2324 return result;
[email protected]eb54a562010-01-20 21:55:182325}
2326
[email protected]a96a6022011-11-04 00:58:122327void GLES2DecoderImpl::ReleaseCurrent() {
2328 if (context_.get())
2329 context_->ReleaseCurrent(surface_.get());
2330}
2331
[email protected]8e3e0662010-08-23 18:46:302332void GLES2DecoderImpl::RestoreCurrentRenderbufferBindings() {
[email protected]0d6bfdc2011-11-02 01:32:202333 RenderbufferManager::RenderbufferInfo* renderbuffer =
2334 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
[email protected]8e3e0662010-08-23 18:46:302335 glBindRenderbufferEXT(
[email protected]0d6bfdc2011-11-02 01:32:202336 GL_RENDERBUFFER, renderbuffer ? renderbuffer->service_id() : 0);
[email protected]8e3e0662010-08-23 18:46:302337}
2338
2339static void RebindCurrentFramebuffer(
2340 GLenum target,
2341 FramebufferManager::FramebufferInfo* info,
2342 FrameBuffer* offscreen_frame_buffer) {
2343 GLuint framebuffer_id = info ? info->service_id() : 0;
[email protected]297ca1c2011-06-20 23:08:462344
[email protected]8e3e0662010-08-23 18:46:302345 if (framebuffer_id == 0 && offscreen_frame_buffer) {
2346 framebuffer_id = offscreen_frame_buffer->id();
2347 }
[email protected]297ca1c2011-06-20 23:08:462348
[email protected]8e3e0662010-08-23 18:46:302349 glBindFramebufferEXT(target, framebuffer_id);
2350}
2351
2352void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
[email protected]297ca1c2011-06-20 23:08:462353 state_dirty_ = true;
2354
[email protected]a3ded6d2010-10-19 06:44:392355 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:302356 RebindCurrentFramebuffer(
2357 GL_FRAMEBUFFER,
2358 bound_draw_framebuffer_.get(),
2359 offscreen_target_frame_buffer_.get());
2360 } else {
2361 RebindCurrentFramebuffer(
2362 GL_READ_FRAMEBUFFER_EXT,
2363 bound_read_framebuffer_.get(),
2364 offscreen_target_frame_buffer_.get());
2365 RebindCurrentFramebuffer(
2366 GL_DRAW_FRAMEBUFFER_EXT,
2367 bound_draw_framebuffer_.get(),
2368 offscreen_target_frame_buffer_.get());
2369 }
2370}
2371
2372void GLES2DecoderImpl::RestoreCurrentTexture2DBindings() {
2373 GLES2DecoderImpl::TextureUnit& info = texture_units_[0];
2374 GLuint last_id;
2375 if (info.bound_texture_2d) {
2376 last_id = info.bound_texture_2d->service_id();
2377 } else {
2378 last_id = 0;
2379 }
2380
2381 glBindTexture(GL_TEXTURE_2D, last_id);
2382 glActiveTexture(GL_TEXTURE0 + active_texture_unit_);
2383}
2384
[email protected]0d6bfdc2011-11-02 01:32:202385bool GLES2DecoderImpl::CheckFramebufferValid(
2386 FramebufferManager::FramebufferInfo* framebuffer,
2387 GLenum target, const char* func_name) {
[email protected]a0b78dc2011-11-11 10:43:102388 if (!framebuffer) {
[email protected]0d6bfdc2011-11-02 01:32:202389 return true;
2390 }
2391
2392 GLenum completeness = framebuffer->IsPossiblyComplete();
2393 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
2394 SetGLError(
2395 GL_INVALID_FRAMEBUFFER_OPERATION,
2396 (std::string(func_name) + " framebuffer incomplete").c_str());
[email protected]3a03a8f2011-03-19 00:51:272397 return false;
2398 }
[email protected]0d6bfdc2011-11-02 01:32:202399
2400 // Are all the attachments cleared?
2401 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
2402 texture_manager()->HaveUnclearedMips()) {
2403 if (!framebuffer->IsCleared()) {
2404 // Can we clear them?
2405 if (glCheckFramebufferStatusEXT(target) != GL_FRAMEBUFFER_COMPLETE) {
2406 SetGLError(
2407 GL_INVALID_FRAMEBUFFER_OPERATION,
2408 (std::string(func_name) +
2409 " framebuffer incomplete (clear)").c_str());
2410 return false;
2411 }
2412 ClearUnclearedAttachments(target, framebuffer);
2413 }
2414 }
2415
2416 // NOTE: At this point we don't know if the framebuffer is complete but
2417 // we DO know that everything that needs to be cleared has been cleared.
[email protected]3a03a8f2011-03-19 00:51:272418 return true;
2419}
2420
[email protected]0d6bfdc2011-11-02 01:32:202421bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name) {
2422 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
2423 return CheckFramebufferValid(
2424 bound_draw_framebuffer_, GL_FRAMEBUFFER_EXT, func_name);
2425 }
2426 return CheckFramebufferValid(
2427 bound_draw_framebuffer_, GL_DRAW_FRAMEBUFFER_EXT, func_name) &&
2428 CheckFramebufferValid(
2429 bound_read_framebuffer_, GL_READ_FRAMEBUFFER_EXT, func_name);
2430}
2431
[email protected]8e3e0662010-08-23 18:46:302432gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
[email protected]0d6bfdc2011-11-02 01:32:202433 FramebufferManager::FramebufferInfo* framebuffer =
2434 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER);
2435 if (framebuffer != NULL) {
[email protected]9edc6b22010-12-23 02:00:262436 const FramebufferManager::FramebufferInfo::Attachment* attachment =
[email protected]0d6bfdc2011-11-02 01:32:202437 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
[email protected]9edc6b22010-12-23 02:00:262438 if (attachment) {
2439 return gfx::Size(attachment->width(), attachment->height());
[email protected]246a70452010-03-05 21:53:502440 }
[email protected]9edc6b22010-12-23 02:00:262441 return gfx::Size(0, 0);
[email protected]34ff8b0c2010-10-01 20:06:022442 } else if (offscreen_target_frame_buffer_.get()) {
2443 return offscreen_size_;
[email protected]6217d392010-03-25 22:08:352444 } else {
[email protected]f62a5ab2011-05-23 20:34:152445 return surface_->GetSize();
[email protected]d37231fa2010-04-09 21:16:022446 }
[email protected]246a70452010-03-05 21:53:502447}
2448
[email protected]9edc6b22010-12-23 02:00:262449GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
[email protected]0d6bfdc2011-11-02 01:32:202450 FramebufferManager::FramebufferInfo* framebuffer =
2451 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER);
2452 if (framebuffer != NULL) {
2453 return framebuffer->GetColorAttachmentFormat();
[email protected]297ca1c2011-06-20 23:08:462454 } else if (offscreen_target_frame_buffer_.get()) {
2455 return offscreen_target_color_format_;
2456 } else {
2457 return back_buffer_color_format_;
2458 }
2459}
2460
2461GLenum GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
[email protected]0d6bfdc2011-11-02 01:32:202462 FramebufferManager::FramebufferInfo* framebuffer =
2463 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER);
2464 if (framebuffer != NULL) {
2465 return framebuffer->GetColorAttachmentFormat();
[email protected]9edc6b22010-12-23 02:00:262466 } else if (offscreen_target_frame_buffer_.get()) {
2467 return offscreen_target_color_format_;
2468 } else {
[email protected]32fe9aa2011-01-21 23:47:132469 return back_buffer_color_format_;
[email protected]9edc6b22010-12-23 02:00:262470 }
2471}
2472
[email protected]9a5afa432011-07-22 18:16:392473void GLES2DecoderImpl::UpdateParentTextureInfo() {
[email protected]34ff8b0c2010-10-01 20:06:022474 if (parent_) {
[email protected]2f2d7042010-04-14 21:45:582475 // Update the info about the offscreen saved color texture in the parent.
2476 // The reference to the parent is a weak pointer and will become null if the
2477 // parent is later destroyed.
[email protected]6217d392010-03-25 22:08:352478 GLuint service_id = offscreen_saved_color_texture_->id();
[email protected]8d25d042010-06-16 19:48:142479 GLuint client_id;
[email protected]262d7aa2010-12-03 22:07:292480 TextureManager* parent_texture_manager = parent_->texture_manager();
2481 CHECK(parent_texture_manager->GetClientId(service_id, &client_id));
[email protected]8d25d042010-06-16 19:48:142482 TextureManager::TextureInfo* info = parent_->GetTextureInfo(client_id);
[email protected]6217d392010-03-25 22:08:352483 DCHECK(info);
2484
[email protected]262d7aa2010-12-03 22:07:292485 parent_texture_manager->SetLevelInfo(
[email protected]915a59a12010-09-30 21:29:112486 feature_info_,
[email protected]ef526492010-06-02 23:12:252487 info,
2488 GL_TEXTURE_2D,
2489 0, // level
2490 GL_RGBA,
[email protected]799b4b22011-08-22 17:09:592491 offscreen_size_.width(),
2492 offscreen_size_.height(),
[email protected]ef526492010-06-02 23:12:252493 1, // depth
2494 0, // border
2495 GL_RGBA,
[email protected]0d6bfdc2011-11-02 01:32:202496 GL_UNSIGNED_BYTE,
2497 true);
[email protected]262d7aa2010-12-03 22:07:292498 parent_texture_manager->SetParameter(
[email protected]8c515f82010-11-09 03:40:042499 feature_info_,
2500 info,
2501 GL_TEXTURE_MAG_FILTER,
2502 GL_NEAREST);
[email protected]262d7aa2010-12-03 22:07:292503 parent_texture_manager->SetParameter(
[email protected]8c515f82010-11-09 03:40:042504 feature_info_,
2505 info,
2506 GL_TEXTURE_MIN_FILTER,
2507 GL_NEAREST);
[email protected]262d7aa2010-12-03 22:07:292508 parent_texture_manager->SetParameter(
[email protected]8c515f82010-11-09 03:40:042509 feature_info_,
2510 info,
2511 GL_TEXTURE_WRAP_S,
2512 GL_CLAMP_TO_EDGE);
[email protected]262d7aa2010-12-03 22:07:292513 parent_texture_manager->SetParameter(
[email protected]8c515f82010-11-09 03:40:042514 feature_info_,
2515 info,
2516 GL_TEXTURE_WRAP_T,
2517 GL_CLAMP_TO_EDGE);
[email protected]0c8c9d22010-06-25 17:36:392518 }
[email protected]6217d392010-03-25 22:08:352519}
2520
[email protected]799b4b22011-08-22 17:09:592521void GLES2DecoderImpl::SetResizeCallback(
[email protected]9d37f062011-11-22 01:24:522522 const base::Callback<void(gfx::Size)>& callback) {
2523 resize_callback_ = callback;
[email protected]7ff86b92010-11-25 17:50:002524}
2525
[email protected]9d37f062011-11-22 01:24:522526void GLES2DecoderImpl::SetSwapBuffersCallback(const base::Closure& callback) {
2527 swap_buffers_callback_ = callback;
[email protected]43f28f832010-02-03 02:28:482528}
[email protected]43f28f832010-02-03 02:28:482529
[email protected]b0af4f52011-09-28 22:04:422530void GLES2DecoderImpl::SetStreamTextureManager(StreamTextureManager* manager) {
2531 stream_texture_manager_ = manager;
2532}
2533
[email protected]1318e922010-09-17 22:03:162534bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
2535 uint32* service_texture_id) {
2536 TextureManager::TextureInfo* texture =
2537 texture_manager()->GetTextureInfo(client_texture_id);
2538 if (texture) {
2539 *service_texture_id = texture->service_id();
2540 return true;
2541 }
2542 return false;
2543}
2544
[email protected]96449d2c2009-11-25 00:01:322545void GLES2DecoderImpl::Destroy() {
[email protected]eadc96792010-10-27 19:39:392546 bool have_context = context_.get() && MakeCurrent();
[email protected]97872062010-11-03 19:07:052547
[email protected]3c644d82011-06-20 19:58:242548 SetParent(NULL, 0);
2549
[email protected]eadc96792010-10-27 19:39:392550 if (have_context) {
[email protected]ca488e12010-12-13 20:06:142551 if (current_program_) {
2552 program_manager()->UnuseProgram(shader_manager(), current_program_);
2553 current_program_ = NULL;
2554 }
2555
[email protected]b1122982010-05-17 23:04:242556 if (attrib_0_buffer_id_) {
2557 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
2558 }
[email protected]8fbedc02010-11-18 18:43:402559 if (fixed_attrib_buffer_id_) {
2560 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_);
2561 }
[email protected]b1122982010-05-17 23:04:242562
[email protected]97872062010-11-03 19:07:052563 if (offscreen_target_frame_buffer_.get())
[email protected]4bedba72010-04-20 22:08:542564 offscreen_target_frame_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052565 if (offscreen_target_color_texture_.get())
[email protected]4bedba72010-04-20 22:08:542566 offscreen_target_color_texture_->Destroy();
[email protected]97872062010-11-03 19:07:052567 if (offscreen_target_color_render_buffer_.get())
[email protected]34ff8b0c2010-10-01 20:06:022568 offscreen_target_color_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052569 if (offscreen_target_depth_render_buffer_.get())
[email protected]b9363b22010-06-09 22:06:152570 offscreen_target_depth_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052571 if (offscreen_target_stencil_render_buffer_.get())
[email protected]b9363b22010-06-09 22:06:152572 offscreen_target_stencil_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052573 if (offscreen_saved_frame_buffer_.get())
[email protected]34ff8b0c2010-10-01 20:06:022574 offscreen_saved_frame_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052575 if (offscreen_saved_color_texture_.get())
[email protected]4bedba72010-04-20 22:08:542576 offscreen_saved_color_texture_->Destroy();
[email protected]de26b3c2011-08-03 21:54:272577 if (offscreen_resolved_frame_buffer_.get())
2578 offscreen_resolved_frame_buffer_->Destroy();
2579 if (offscreen_resolved_color_texture_.get())
2580 offscreen_resolved_color_texture_->Destroy();
[email protected]97872062010-11-03 19:07:052581 } else {
2582 if (offscreen_target_frame_buffer_.get())
2583 offscreen_target_frame_buffer_->Invalidate();
2584 if (offscreen_target_color_texture_.get())
2585 offscreen_target_color_texture_->Invalidate();
2586 if (offscreen_target_color_render_buffer_.get())
2587 offscreen_target_color_render_buffer_->Invalidate();
2588 if (offscreen_target_depth_render_buffer_.get())
2589 offscreen_target_depth_render_buffer_->Invalidate();
2590 if (offscreen_target_stencil_render_buffer_.get())
2591 offscreen_target_stencil_render_buffer_->Invalidate();
2592 if (offscreen_saved_frame_buffer_.get())
2593 offscreen_saved_frame_buffer_->Invalidate();
2594 if (offscreen_saved_color_texture_.get())
2595 offscreen_saved_color_texture_->Invalidate();
[email protected]de26b3c2011-08-03 21:54:272596 if (offscreen_resolved_frame_buffer_.get())
2597 offscreen_resolved_frame_buffer_->Invalidate();
2598 if (offscreen_resolved_color_texture_.get())
2599 offscreen_resolved_color_texture_->Invalidate();
[email protected]d37231fa2010-04-09 21:16:022600 }
[email protected]97872062010-11-03 19:07:052601
[email protected]1871a092011-10-10 21:46:422602 if (group_) {
2603 group_->Destroy(have_context);
2604 group_ = NULL;
2605 }
[email protected]3ae019382011-10-05 19:42:412606
[email protected]fe871662011-06-16 20:43:052607 if (context_.get()) {
2608 context_->ReleaseCurrent(NULL);
[email protected]79311e82011-09-20 00:40:502609 context_ = NULL;
[email protected]fe871662011-06-16 20:43:052610 }
[email protected]0fc35742011-04-13 17:57:542611
[email protected]97872062010-11-03 19:07:052612 offscreen_target_frame_buffer_.reset();
2613 offscreen_target_color_texture_.reset();
2614 offscreen_target_color_render_buffer_.reset();
2615 offscreen_target_depth_render_buffer_.reset();
2616 offscreen_target_stencil_render_buffer_.reset();
2617 offscreen_saved_frame_buffer_.reset();
2618 offscreen_saved_color_texture_.reset();
[email protected]de26b3c2011-08-03 21:54:272619 offscreen_resolved_frame_buffer_.reset();
2620 offscreen_resolved_color_texture_.reset();
[email protected]96449d2c2009-11-25 00:01:322621}
2622
[email protected]3c644d82011-06-20 19:58:242623bool GLES2DecoderImpl::SetParent(GLES2Decoder* new_parent,
2624 uint32 new_parent_texture_id) {
[email protected]9a5afa432011-07-22 18:16:392625 if (!offscreen_saved_color_texture_.get())
2626 return false;
2627
[email protected]3c644d82011-06-20 19:58:242628 // Remove the saved frame buffer mapping from the parent decoder. The
2629 // parent pointer is a weak pointer so it will be null if the parent has
2630 // already been destroyed.
2631 if (parent_) {
2632 // First check the texture has been mapped into the parent. This might not
2633 // be the case if initialization failed midway through.
2634 GLuint service_id = offscreen_saved_color_texture_->id();
2635 GLuint client_id = 0;
2636 if (parent_->texture_manager()->GetClientId(service_id, &client_id)) {
2637 parent_->texture_manager()->RemoveTextureInfo(feature_info_, client_id);
2638 }
2639 }
2640
2641 GLES2DecoderImpl* new_parent_impl = static_cast<GLES2DecoderImpl*>(
2642 new_parent);
2643 if (new_parent_impl) {
2644 // Map the ID of the saved offscreen texture into the parent so that
2645 // it can reference it.
2646 GLuint service_id = offscreen_saved_color_texture_->id();
[email protected]98687862011-07-11 23:31:302647
2648 // Replace texture info when ID is already in use by parent.
2649 if (new_parent_impl->texture_manager()->GetTextureInfo(
2650 new_parent_texture_id))
2651 new_parent_impl->texture_manager()->RemoveTextureInfo(
2652 feature_info_, new_parent_texture_id);
2653
[email protected]3c644d82011-06-20 19:58:242654 TextureManager::TextureInfo* info =
[email protected]5f4f2a732011-07-30 00:47:552655 new_parent_impl->CreateTextureInfo(new_parent_texture_id, service_id);
2656 info->SetNotOwned();
[email protected]b0af4f52011-09-28 22:04:422657 new_parent_impl->texture_manager()->SetInfoTarget(feature_info_,
2658 info, GL_TEXTURE_2D);
[email protected]3c644d82011-06-20 19:58:242659
2660 parent_ = new_parent_impl->AsWeakPtr();
[email protected]9a5afa432011-07-22 18:16:392661
2662 UpdateParentTextureInfo();
[email protected]3c644d82011-06-20 19:58:242663 } else {
2664 parent_.reset();
2665 }
2666
2667 return true;
2668}
2669
[email protected]799b4b22011-08-22 17:09:592670bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
2671 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
2672 if (!is_offscreen) {
2673 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
2674 << " with an onscreen framebuffer.";
2675 return false;
2676 }
2677
2678 if (offscreen_size_ == size)
2679 return true;
2680
2681 offscreen_size_ = size;
2682 int w = offscreen_size_.width();
2683 int h = offscreen_size_.height();
2684 if (w < 0 || h < 0 || h >= (INT_MAX / 4) / (w ? w : 1)) {
2685 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2686 << "to allocate storage due to excessive dimensions.";
2687 return false;
2688 }
2689
2690 // Reallocate the offscreen target buffers.
2691 DCHECK(offscreen_target_color_format_);
2692 if (IsOffscreenBufferMultisampled()) {
2693 if (!offscreen_target_color_render_buffer_->AllocateStorage(
2694 offscreen_size_, offscreen_target_color_format_,
2695 offscreen_target_samples_)) {
2696 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2697 << "to allocate storage for offscreen target color buffer.";
2698 return false;
2699 }
2700 } else {
2701 if (!offscreen_target_color_texture_->AllocateStorage(
2702 offscreen_size_, offscreen_target_color_format_)) {
2703 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2704 << "to allocate storage for offscreen target color texture.";
2705 return false;
2706 }
2707 }
2708 if (offscreen_target_depth_format_ &&
2709 !offscreen_target_depth_render_buffer_->AllocateStorage(
2710 offscreen_size_, offscreen_target_depth_format_,
2711 offscreen_target_samples_)) {
2712 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2713 << "to allocate storage for offscreen target depth buffer.";
2714 return false;
2715 }
2716 if (offscreen_target_stencil_format_ &&
2717 !offscreen_target_stencil_render_buffer_->AllocateStorage(
2718 offscreen_size_, offscreen_target_stencil_format_,
2719 offscreen_target_samples_)) {
2720 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2721 << "to allocate storage for offscreen target stencil buffer.";
2722 return false;
2723 }
2724
2725 // Attach the offscreen target buffers to the target frame buffer.
2726 if (IsOffscreenBufferMultisampled()) {
2727 offscreen_target_frame_buffer_->AttachRenderBuffer(
2728 GL_COLOR_ATTACHMENT0,
2729 offscreen_target_color_render_buffer_.get());
2730 } else {
2731 offscreen_target_frame_buffer_->AttachRenderTexture(
2732 offscreen_target_color_texture_.get());
2733 }
2734 if (offscreen_target_depth_format_) {
2735 offscreen_target_frame_buffer_->AttachRenderBuffer(
2736 GL_DEPTH_ATTACHMENT,
2737 offscreen_target_depth_render_buffer_.get());
2738 }
2739 const bool packed_depth_stencil =
2740 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
2741 if (packed_depth_stencil) {
2742 offscreen_target_frame_buffer_->AttachRenderBuffer(
2743 GL_STENCIL_ATTACHMENT,
2744 offscreen_target_depth_render_buffer_.get());
2745 } else if (offscreen_target_stencil_format_) {
2746 offscreen_target_frame_buffer_->AttachRenderBuffer(
2747 GL_STENCIL_ATTACHMENT,
2748 offscreen_target_stencil_render_buffer_.get());
2749 }
2750
2751 if (offscreen_target_frame_buffer_->CheckStatus() !=
2752 GL_FRAMEBUFFER_COMPLETE) {
2753 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2754 << "because offscreen FBO was incomplete.";
2755 return false;
2756 }
2757
2758 // Clear the target frame buffer.
2759 {
2760 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
2761 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
2762 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1);
2763 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
2764 glClearStencil(0);
2765 glStencilMaskSeparate(GL_FRONT, -1);
2766 glStencilMaskSeparate(GL_BACK, -1);
2767 glClearDepth(0);
2768 glDepthMask(GL_TRUE);
2769 glDisable(GL_SCISSOR_TEST);
2770 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2771 RestoreClearState();
2772 }
[email protected]d85ef76d2011-09-08 22:21:432773
2774 // Destroy the offscreen resolved framebuffers.
2775 if (offscreen_resolved_frame_buffer_.get())
2776 offscreen_resolved_frame_buffer_->Destroy();
2777 if (offscreen_resolved_color_texture_.get())
2778 offscreen_resolved_color_texture_->Destroy();
2779 offscreen_resolved_color_texture_.reset();
2780 offscreen_resolved_frame_buffer_.reset();
2781
[email protected]799b4b22011-08-22 17:09:592782 return true;
[email protected]6217d392010-03-25 22:08:352783}
2784
[email protected]799b4b22011-08-22 17:09:592785error::Error GLES2DecoderImpl::HandleResizeCHROMIUM(
2786 uint32 immediate_data_size, const gles2::ResizeCHROMIUM& c) {
2787 GLuint width = static_cast<GLuint>(c.width);
2788 GLuint height = static_cast<GLuint>(c.height);
2789 TRACE_EVENT2("gpu", "glResizeChromium", "width", width, "height", height);
[email protected]a0d989162011-11-22 13:15:072790#if defined(OS_POSIX) && !defined(OS_MACOSX) && \
2791 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
[email protected]7ff86b92010-11-25 17:50:002792 // Make sure that we are done drawing to the back buffer before resizing.
2793 glFinish();
2794#endif
[email protected]799b4b22011-08-22 17:09:592795 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
2796 if (is_offscreen) {
2797 if (!ResizeOffscreenFrameBuffer(gfx::Size(width, height)))
2798 return error::kLostContext;
[email protected]7ff86b92010-11-25 17:50:002799 }
[email protected]799b4b22011-08-22 17:09:592800
[email protected]9d37f062011-11-22 01:24:522801 if (!resize_callback_.is_null()) {
2802 resize_callback_.Run(gfx::Size(width, height));
[email protected]c777de52011-09-09 23:08:562803 DCHECK(context_->IsCurrent(surface_.get()));
2804 if (!context_->IsCurrent(surface_.get()))
[email protected]658f7562011-09-09 05:24:052805 return error::kLostContext;
[email protected]658f7562011-09-09 05:24:052806 }
[email protected]799b4b22011-08-22 17:09:592807
2808 return error::kNoError;
[email protected]43ecf372010-11-16 19:19:392809}
2810
[email protected]96449d2c2009-11-25 00:01:322811const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
2812 if (command_id > kStartPoint && command_id < kNumCommands) {
2813 return gles2::GetCommandName(static_cast<CommandId>(command_id));
2814 }
2815 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
2816}
2817
2818// Decode command with its arguments, and call the corresponding GL function.
2819// Note: args is a pointer to the command buffer. As such, it could be changed
2820// by a (malicious) client at any time, so if validation has to happen, it
2821// should operate on a copy of them.
[email protected]f7a64ee2010-02-01 22:24:142822error::Error GLES2DecoderImpl::DoCommand(
[email protected]96449d2c2009-11-25 00:01:322823 unsigned int command,
2824 unsigned int arg_count,
2825 const void* cmd_data) {
[email protected]f7a64ee2010-02-01 22:24:142826 error::Error result = error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192827 if (debug()) {
2828 // TODO(gman): Change output to something useful for NaCl.
[email protected]4297cbe2011-11-03 18:04:002829 LOG(INFO) << "[" << this << "]" << "cmd: " << GetCommandName(command);
[email protected]b9849abf2009-11-25 19:13:192830 }
[email protected]96449d2c2009-11-25 00:01:322831 unsigned int command_index = command - kStartPoint - 1;
2832 if (command_index < arraysize(g_command_info)) {
2833 const CommandInfo& info = g_command_info[command_index];
2834 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
2835 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
2836 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
[email protected]b9849abf2009-11-25 19:13:192837 uint32 immediate_data_size =
2838 (arg_count - info_arg_count) * sizeof(CommandBufferEntry); // NOLINT
[email protected]96449d2c2009-11-25 00:01:322839 switch (command) {
2840 #define GLES2_CMD_OP(name) \
2841 case name::kCmdId: \
[email protected]b9849abf2009-11-25 19:13:192842 result = Handle ## name( \
2843 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:322844 *static_cast<const name*>(cmd_data)); \
[email protected]b9849abf2009-11-25 19:13:192845 break; \
[email protected]96449d2c2009-11-25 00:01:322846
2847 GLES2_COMMAND_LIST(GLES2_CMD_OP)
[email protected]96449d2c2009-11-25 00:01:322848 #undef GLES2_CMD_OP
[email protected]bf0985e2009-12-17 03:04:382849 }
2850 if (debug()) {
[email protected]07f54fcc2009-12-22 02:46:302851 GLenum error;
2852 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]bf0985e2009-12-17 03:04:382853 // TODO(gman): Change output to something useful for NaCl.
[email protected]8eee29c2010-04-29 03:38:292854 SetGLError(error, NULL);
[email protected]8e1b98a2011-06-14 23:39:532855 DLOG(INFO) << "[" << this << "]"
2856 << "GL ERROR: " << error << " : " << GetCommandName(command);
[email protected]b9849abf2009-11-25 19:13:192857 }
[email protected]96449d2c2009-11-25 00:01:322858 }
2859 } else {
[email protected]f7a64ee2010-02-01 22:24:142860 result = error::kInvalidArguments;
[email protected]96449d2c2009-11-25 00:01:322861 }
[email protected]b9849abf2009-11-25 19:13:192862 } else {
2863 result = DoCommonCommand(command, arg_count, cmd_data);
[email protected]96449d2c2009-11-25 00:01:322864 }
[email protected]a3a93e7b2010-08-28 00:48:562865 if (result == error::kNoError && current_decoder_error_ != error::kNoError) {
2866 result = current_decoder_error_;
2867 current_decoder_error_ = error::kNoError;
2868 }
[email protected]b9849abf2009-11-25 19:13:192869 return result;
[email protected]96449d2c2009-11-25 00:01:322870}
2871
[email protected]ae51d192010-04-27 00:48:032872void GLES2DecoderImpl::RemoveBufferInfo(GLuint client_id) {
2873 buffer_manager()->RemoveBufferInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:502874}
2875
[email protected]ae51d192010-04-27 00:48:032876bool GLES2DecoderImpl::CreateProgramHelper(GLuint client_id) {
2877 if (GetProgramInfo(client_id)) {
2878 return false;
2879 }
[email protected]96449d2c2009-11-25 00:01:322880 GLuint service_id = glCreateProgram();
[email protected]ae51d192010-04-27 00:48:032881 if (service_id != 0) {
2882 CreateProgramInfo(client_id, service_id);
[email protected]96449d2c2009-11-25 00:01:322883 }
[email protected]ae51d192010-04-27 00:48:032884 return true;
[email protected]96449d2c2009-11-25 00:01:322885}
2886
[email protected]ae51d192010-04-27 00:48:032887bool GLES2DecoderImpl::CreateShaderHelper(GLenum type, GLuint client_id) {
2888 if (GetShaderInfo(client_id)) {
2889 return false;
[email protected]96449d2c2009-11-25 00:01:322890 }
[email protected]ae51d192010-04-27 00:48:032891 GLuint service_id = glCreateShader(type);
2892 if (service_id != 0) {
[email protected]7cea56d92010-04-28 17:21:382893 CreateShaderInfo(client_id, service_id, type);
[email protected]ae51d192010-04-27 00:48:032894 }
2895 return true;
[email protected]96449d2c2009-11-25 00:01:322896}
2897
[email protected]3916c97e2010-02-25 03:20:502898void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
[email protected]36cef8ce2010-03-16 07:34:452899 GLuint texture_index = texture_unit - GL_TEXTURE0;
[email protected]660858b2011-07-13 23:16:142900 if (texture_index >= group_->max_texture_units()) {
[email protected]8eee29c2010-04-29 03:38:292901 SetGLError(GL_INVALID_ENUM, "glActiveTexture: texture_unit out of range.");
[email protected]3916c97e2010-02-25 03:20:502902 return;
2903 }
[email protected]36cef8ce2010-03-16 07:34:452904 active_texture_unit_ = texture_index;
2905 glActiveTexture(texture_unit);
[email protected]3916c97e2010-02-25 03:20:502906}
2907
[email protected]051b1372010-04-12 02:42:082908void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:502909 BufferManager::BufferInfo* info = NULL;
[email protected]051b1372010-04-12 02:42:082910 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:032911 if (client_id != 0) {
2912 info = GetBufferInfo(client_id);
2913 if (!info) {
[email protected]bf5a8d132011-08-16 08:39:352914 if (!group_->bind_generates_resource()) {
2915 SetGLError(GL_INVALID_VALUE,
2916 "glBindBuffer: id not generated by glGenBuffers");
2917 return;
2918 }
2919
[email protected]ae51d192010-04-27 00:48:032920 // It's a new id so make a buffer info for it.
2921 glGenBuffersARB(1, &service_id);
2922 CreateBufferInfo(client_id, service_id);
2923 info = GetBufferInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:572924 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:102925 group_->GetIdAllocator(id_namespaces::kBuffers);
2926 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:032927 }
[email protected]051b1372010-04-12 02:42:082928 }
[email protected]ae51d192010-04-27 00:48:032929 if (info) {
[email protected]4e8a5b122010-05-08 22:00:102930 if (!buffer_manager()->SetTarget(info, target)) {
[email protected]8eee29c2010-04-29 03:38:292931 SetGLError(GL_INVALID_OPERATION,
2932 "glBindBuffer: buffer bound to more than 1 target");
[email protected]a93bb842010-02-16 23:03:472933 return;
2934 }
[email protected]ae51d192010-04-27 00:48:032935 service_id = info->service_id();
[email protected]a93bb842010-02-16 23:03:472936 }
[email protected]96449d2c2009-11-25 00:01:322937 switch (target) {
2938 case GL_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:502939 bound_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:322940 break;
2941 case GL_ELEMENT_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:502942 bound_element_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:322943 break;
2944 default:
[email protected]a93bb842010-02-16 23:03:472945 NOTREACHED(); // Validation should prevent us getting here.
[email protected]96449d2c2009-11-25 00:01:322946 break;
2947 }
[email protected]051b1372010-04-12 02:42:082948 glBindBuffer(target, service_id);
[email protected]96449d2c2009-11-25 00:01:322949}
2950
[email protected]297ca1c2011-06-20 23:08:462951bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha() {
2952 return (GLES2Util::GetChannelsForFormat(
2953 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
2954}
2955
2956bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
[email protected]0d6bfdc2011-11-02 01:32:202957 FramebufferManager::FramebufferInfo* framebuffer =
2958 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER);
2959 if (framebuffer) {
2960 return framebuffer->HasDepthAttachment();
[email protected]297ca1c2011-06-20 23:08:462961 }
2962 if (offscreen_target_frame_buffer_.get()) {
2963 return offscreen_target_depth_format_ != 0;
2964 }
2965 return back_buffer_has_depth_;
2966}
2967
2968bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
[email protected]0d6bfdc2011-11-02 01:32:202969 FramebufferManager::FramebufferInfo* framebuffer =
2970 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER);
2971 if (framebuffer) {
2972 return framebuffer->HasStencilAttachment();
[email protected]297ca1c2011-06-20 23:08:462973 }
2974 if (offscreen_target_frame_buffer_.get()) {
2975 return offscreen_target_stencil_format_ != 0 ||
2976 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
2977 }
2978 return back_buffer_has_stencil_;
2979}
2980
2981void GLES2DecoderImpl::ApplyDirtyState() {
2982 if (state_dirty_) {
2983 glColorMask(
2984 mask_red_, mask_green_, mask_blue_,
2985 mask_alpha_ && BoundFramebufferHasColorAttachmentWithAlpha());
2986 bool have_depth = BoundFramebufferHasDepthAttachment();
2987 glDepthMask(mask_depth_ && have_depth);
2988 EnableDisable(GL_DEPTH_TEST, enable_depth_test_ && have_depth);
2989 bool have_stencil = BoundFramebufferHasStencilAttachment();
2990 glStencilMaskSeparate(GL_FRONT, have_stencil ? mask_stencil_front_ : 0);
2991 glStencilMaskSeparate(GL_BACK, have_stencil ? mask_stencil_back_ : 0);
2992 EnableDisable(GL_STENCIL_TEST, enable_stencil_test_ && have_stencil);
2993 state_dirty_ = false;
2994 }
2995}
2996
[email protected]b177ae22011-11-01 03:29:112997GLuint GLES2DecoderImpl::GetBackbufferServiceId() {
2998 return (offscreen_target_frame_buffer_.get()) ?
2999 offscreen_target_frame_buffer_->id() :
3000 surface_->GetBackingFrameBufferObject();
3001}
3002
[email protected]051b1372010-04-12 02:42:083003void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
3004 FramebufferManager::FramebufferInfo* info = NULL;
3005 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033006 if (client_id != 0) {
3007 info = GetFramebufferInfo(client_id);
[email protected]051b1372010-04-12 02:42:083008 if (!info) {
[email protected]bf5a8d132011-08-16 08:39:353009 if (!group_->bind_generates_resource()) {
3010 SetGLError(GL_INVALID_VALUE,
3011 "glBindFramebuffer: id not generated by glGenFramebuffers");
3012 return;
3013 }
3014
[email protected]ae51d192010-04-27 00:48:033015 // It's a new id so make a framebuffer info for it.
3016 glGenFramebuffersEXT(1, &service_id);
3017 CreateFramebufferInfo(client_id, service_id);
3018 info = GetFramebufferInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:573019 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103020 group_->GetIdAllocator(id_namespaces::kFramebuffers);
3021 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033022 } else {
3023 service_id = info->service_id();
[email protected]051b1372010-04-12 02:42:083024 }
[email protected]06c8b082011-01-05 18:00:363025 info->MarkAsValid();
[email protected]051b1372010-04-12 02:42:083026 }
[email protected]8e3e0662010-08-23 18:46:303027
3028 if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) {
3029 bound_draw_framebuffer_ = info;
3030 }
3031 if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) {
3032 bound_read_framebuffer_ = info;
3033 }
[email protected]6217d392010-03-25 22:08:353034
[email protected]297ca1c2011-06-20 23:08:463035 state_dirty_ = true;
3036
[email protected]b177ae22011-11-01 03:29:113037 // If we are rendering to the backbuffer get the FBO id for any simulated
3038 // backbuffer.
3039 if (info == NULL) {
3040 service_id = GetBackbufferServiceId();
[email protected]297ca1c2011-06-20 23:08:463041 }
[email protected]6217d392010-03-25 22:08:353042
[email protected]051b1372010-04-12 02:42:083043 glBindFramebufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:563044}
3045
[email protected]051b1372010-04-12 02:42:083046void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
3047 RenderbufferManager::RenderbufferInfo* info = NULL;
3048 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033049 if (client_id != 0) {
3050 info = GetRenderbufferInfo(client_id);
[email protected]051b1372010-04-12 02:42:083051 if (!info) {
[email protected]bf5a8d132011-08-16 08:39:353052 if (!group_->bind_generates_resource()) {
3053 SetGLError(
3054 GL_INVALID_VALUE,
3055 "glBindRenderbuffer: id not generated by glGenRenderbuffers");
3056 return;
3057 }
3058
[email protected]ae51d192010-04-27 00:48:033059 // It's a new id so make a renderbuffer info for it.
3060 glGenRenderbuffersEXT(1, &service_id);
3061 CreateRenderbufferInfo(client_id, service_id);
[email protected]066849e32010-05-03 19:14:103062 info = GetRenderbufferInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:573063 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103064 group_->GetIdAllocator(id_namespaces::kRenderbuffers);
3065 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033066 } else {
3067 service_id = info->service_id();
[email protected]051b1372010-04-12 02:42:083068 }
[email protected]06c8b082011-01-05 18:00:363069 info->MarkAsValid();
[email protected]051b1372010-04-12 02:42:083070 }
3071 bound_renderbuffer_ = info;
3072 glBindRenderbufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:563073}
3074
[email protected]051b1372010-04-12 02:42:083075void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:033076 TextureManager::TextureInfo* info = NULL;
[email protected]051b1372010-04-12 02:42:083077 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033078 if (client_id != 0) {
3079 info = GetTextureInfo(client_id);
3080 if (!info) {
[email protected]bf5a8d132011-08-16 08:39:353081 if (!group_->bind_generates_resource()) {
3082 SetGLError(GL_INVALID_VALUE,
3083 "glBindTexture: id not generated by glGenTextures");
3084 return;
3085 }
3086
[email protected]ae51d192010-04-27 00:48:033087 // It's a new id so make a texture info for it.
3088 glGenTextures(1, &service_id);
3089 CreateTextureInfo(client_id, service_id);
3090 info = GetTextureInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:573091 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103092 group_->GetIdAllocator(id_namespaces::kTextures);
3093 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033094 }
3095 } else {
3096 info = texture_manager()->GetDefaultTextureInfo(target);
[email protected]051b1372010-04-12 02:42:083097 }
[email protected]ae51d192010-04-27 00:48:033098
[email protected]1958e0e2010-04-22 05:17:153099 // Check the texture exists
3100 // Check that we are not trying to bind it to a different target.
[email protected]ae51d192010-04-27 00:48:033101 if (info->target() != 0 && info->target() != target) {
[email protected]8eee29c2010-04-29 03:38:293102 SetGLError(GL_INVALID_OPERATION,
3103 "glBindTexture: texture bound to more than 1 target.");
[email protected]1958e0e2010-04-22 05:17:153104 return;
3105 }
[email protected]b0af4f52011-09-28 22:04:423106 if (info->IsStreamTexture() && target != GL_TEXTURE_EXTERNAL_OES) {
3107 SetGLError(GL_INVALID_OPERATION,
3108 "glBindTexture: illegal target for stream texture.");
3109 return;
3110 }
[email protected]1958e0e2010-04-22 05:17:153111 if (info->target() == 0) {
[email protected]b0af4f52011-09-28 22:04:423112 texture_manager()->SetInfoTarget(feature_info_, info, target);
[email protected]a93bb842010-02-16 23:03:473113 }
[email protected]ae51d192010-04-27 00:48:033114 glBindTexture(target, info->service_id());
[email protected]3916c97e2010-02-25 03:20:503115 TextureUnit& unit = texture_units_[active_texture_unit_];
3116 unit.bind_target = target;
[email protected]a93bb842010-02-16 23:03:473117 switch (target) {
3118 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:503119 unit.bound_texture_2d = info;
[email protected]a93bb842010-02-16 23:03:473120 break;
3121 case GL_TEXTURE_CUBE_MAP:
[email protected]3916c97e2010-02-25 03:20:503122 unit.bound_texture_cube_map = info;
[email protected]a93bb842010-02-16 23:03:473123 break;
[email protected]61eeb33f2011-07-26 15:30:313124 case GL_TEXTURE_EXTERNAL_OES:
3125 unit.bound_texture_external_oes = info;
[email protected]b0af4f52011-09-28 22:04:423126 if (info->IsStreamTexture()) {
3127 DCHECK(stream_texture_manager_);
3128 StreamTexture* stream_tex =
3129 stream_texture_manager_->LookupStreamTexture(info->service_id());
3130 if (stream_tex)
3131 stream_tex->Update();
3132 }
[email protected]61eeb33f2011-07-26 15:30:313133 break;
[email protected]a93bb842010-02-16 23:03:473134 default:
3135 NOTREACHED(); // Validation should prevent us getting here.
3136 break;
3137 }
3138}
3139
[email protected]07f54fcc2009-12-22 02:46:303140void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
[email protected]f39f4b3f2010-05-12 17:04:083141 if (vertex_attrib_manager_.Enable(index, false)) {
[email protected]1071e572011-02-09 20:00:123142 if (index != 0 ||
3143 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
[email protected]b1122982010-05-17 23:04:243144 glDisableVertexAttribArray(index);
3145 }
[email protected]07f54fcc2009-12-22 02:46:303146 } else {
[email protected]8eee29c2010-04-29 03:38:293147 SetGLError(GL_INVALID_VALUE,
3148 "glDisableVertexAttribArray: index out of range");
[email protected]07f54fcc2009-12-22 02:46:303149 }
3150}
3151
3152void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
[email protected]f39f4b3f2010-05-12 17:04:083153 if (vertex_attrib_manager_.Enable(index, true)) {
[email protected]07f54fcc2009-12-22 02:46:303154 glEnableVertexAttribArray(index);
3155 } else {
[email protected]8eee29c2010-04-29 03:38:293156 SetGLError(GL_INVALID_VALUE,
3157 "glEnableVertexAttribArray: index out of range");
[email protected]07f54fcc2009-12-22 02:46:303158 }
3159}
3160
[email protected]a93bb842010-02-16 23:03:473161void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
[email protected]3916c97e2010-02-25 03:20:503162 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]915a59a12010-09-30 21:29:113163 if (!info || !texture_manager()->MarkMipmapsGenerated(feature_info_, info)) {
[email protected]8eee29c2010-04-29 03:38:293164 SetGLError(GL_INVALID_OPERATION,
3165 "glGenerateMipmaps: Can not generate mips for npot textures");
[email protected]a93bb842010-02-16 23:03:473166 return;
3167 }
[email protected]59f3ca02011-03-26 22:24:193168 // Workaround for Mac driver bug. In the large scheme of things setting
3169 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
[email protected]a8bad262011-10-21 18:28:563170 // hit so there's probably no need to make this conditional. The bug appears
3171 // to be that if the filtering mode is set to something that doesn't require
3172 // mipmaps for rendering, or is never set to something other than the default,
3173 // then glGenerateMipmap misbehaves.
3174 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
[email protected]a93bb842010-02-16 23:03:473175 glGenerateMipmapEXT(target);
[email protected]59f3ca02011-03-26 22:24:193176 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, info->min_filter());
[email protected]a93bb842010-02-16 23:03:473177}
3178
[email protected]b273e432010-04-12 17:23:583179bool GLES2DecoderImpl::GetHelper(
3180 GLenum pname, GLint* params, GLsizei* num_written) {
[email protected]b273e432010-04-12 17:23:583181 DCHECK(num_written);
[email protected]b9363b22010-06-09 22:06:153182 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
3183 switch (pname) {
[email protected]b273e432010-04-12 17:23:583184 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
3185 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103186 if (params) {
[email protected]5094b0f2010-11-09 19:45:243187 *params = GL_RGBA; // We don't support other formats.
[email protected]4e8a5b122010-05-08 22:00:103188 }
[email protected]b273e432010-04-12 17:23:583189 return true;
3190 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
3191 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103192 if (params) {
[email protected]5094b0f2010-11-09 19:45:243193 *params = GL_UNSIGNED_BYTE; // We don't support other types.
[email protected]4e8a5b122010-05-08 22:00:103194 }
[email protected]b273e432010-04-12 17:23:583195 return true;
3196 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
3197 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103198 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:483199 *params = group_->max_fragment_uniform_vectors();
[email protected]4e8a5b122010-05-08 22:00:103200 }
[email protected]b273e432010-04-12 17:23:583201 return true;
3202 case GL_MAX_VARYING_VECTORS:
3203 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103204 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:483205 *params = group_->max_varying_vectors();
[email protected]4e8a5b122010-05-08 22:00:103206 }
[email protected]b273e432010-04-12 17:23:583207 return true;
3208 case GL_MAX_VERTEX_UNIFORM_VECTORS:
3209 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103210 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:483211 *params = group_->max_vertex_uniform_vectors();
[email protected]4e8a5b122010-05-08 22:00:103212 }
[email protected]b273e432010-04-12 17:23:583213 return true;
[email protected]5cb735d2011-10-13 01:37:233214 }
3215 }
3216 switch (pname) {
[email protected]5094b0f2010-11-09 19:45:243217 case GL_MAX_VIEWPORT_DIMS:
3218 if (offscreen_target_frame_buffer_.get()) {
3219 *num_written = 2;
3220 if (params) {
3221 params[0] = renderbuffer_manager()->max_renderbuffer_size();
3222 params[1] = renderbuffer_manager()->max_renderbuffer_size();
3223 }
3224 return true;
3225 }
[email protected]5cb735d2011-10-13 01:37:233226 return false;
[email protected]84afefa2011-10-19 21:45:533227 case GL_MAX_SAMPLES:
3228 *num_written = 1;
3229 if (params) {
3230 params[0] = renderbuffer_manager()->max_samples();
3231 }
3232 return true;
3233 case GL_MAX_RENDERBUFFER_SIZE:
3234 *num_written = 1;
3235 if (params) {
3236 params[0] = renderbuffer_manager()->max_renderbuffer_size();
3237 }
3238 return true;
[email protected]5cb735d2011-10-13 01:37:233239 case GL_MAX_TEXTURE_SIZE:
3240 *num_written = 1;
3241 if (params) {
3242 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D);
3243 }
3244 return true;
3245 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
3246 *num_written = 1;
3247 if (params) {
3248 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP);
3249 }
3250 return true;
[email protected]297ca1c2011-06-20 23:08:463251 case GL_COLOR_WRITEMASK:
3252 *num_written = 4;
3253 if (params) {
3254 params[0] = mask_red_;
3255 params[1] = mask_green_;
3256 params[2] = mask_blue_;
3257 params[3] = mask_alpha_;
3258 }
3259 return true;
3260 case GL_DEPTH_WRITEMASK:
3261 *num_written = 1;
3262 if (params) {
3263 params[0] = mask_depth_;
3264 }
3265 return true;
3266 case GL_STENCIL_BACK_WRITEMASK:
3267 *num_written = 1;
3268 if (params) {
3269 params[0] = mask_stencil_back_;
3270 }
3271 return true;
3272 case GL_STENCIL_WRITEMASK:
3273 *num_written = 1;
3274 if (params) {
3275 params[0] = mask_stencil_front_;
3276 }
3277 return true;
3278 case GL_DEPTH_TEST:
3279 *num_written = 1;
3280 if (params) {
3281 params[0] = enable_depth_test_;
3282 }
3283 return true;
3284 case GL_STENCIL_TEST:
3285 *num_written = 1;
3286 if (params) {
3287 params[0] = enable_stencil_test_;
3288 }
3289 return true;
3290 case GL_ALPHA_BITS:
3291 *num_written = 1;
3292 if (params) {
3293 GLint v = 0;
3294 glGetIntegerv(GL_ALPHA_BITS, &v);
3295 params[0] = BoundFramebufferHasColorAttachmentWithAlpha() ? v : 0;
3296 }
3297 return true;
3298 case GL_DEPTH_BITS:
3299 *num_written = 1;
3300 if (params) {
3301 GLint v = 0;
3302 glGetIntegerv(GL_DEPTH_BITS, &v);
3303 params[0] = BoundFramebufferHasDepthAttachment() ? v : 0;
3304 }
3305 return true;
3306 case GL_STENCIL_BITS:
3307 *num_written = 1;
3308 if (params) {
3309 GLint v = 0;
3310 glGetIntegerv(GL_STENCIL_BITS, &v);
3311 params[0] = BoundFramebufferHasStencilAttachment() ? v : 0;
3312 }
3313 return true;
[email protected]656dcaad2010-05-07 17:18:373314 case GL_COMPRESSED_TEXTURE_FORMATS:
[email protected]302ce6d2011-07-07 23:28:113315 *num_written = validators_->compressed_texture_format.GetValues().size();
3316 if (params) {
3317 for (GLint ii = 0; ii < *num_written; ++ii) {
3318 params[ii] = validators_->compressed_texture_format.GetValues()[ii];
3319 }
3320 }
[email protected]656dcaad2010-05-07 17:18:373321 return true;
[email protected]b273e432010-04-12 17:23:583322 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
3323 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103324 if (params) {
[email protected]302ce6d2011-07-07 23:28:113325 *params = validators_->compressed_texture_format.GetValues().size();
[email protected]4e8a5b122010-05-08 22:00:103326 }
[email protected]b273e432010-04-12 17:23:583327 return true;
3328 case GL_NUM_SHADER_BINARY_FORMATS:
3329 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103330 if (params) {
[email protected]302ce6d2011-07-07 23:28:113331 *params = validators_->shader_binary_format.GetValues().size();
[email protected]4e8a5b122010-05-08 22:00:103332 }
[email protected]b273e432010-04-12 17:23:583333 return true;
3334 case GL_SHADER_BINARY_FORMATS:
[email protected]302ce6d2011-07-07 23:28:113335 *num_written = validators_->shader_binary_format.GetValues().size();
3336 if (params) {
3337 for (GLint ii = 0; ii < *num_written; ++ii) {
3338 params[ii] = validators_->shader_binary_format.GetValues()[ii];
3339 }
3340 }
3341 return true;
[email protected]b273e432010-04-12 17:23:583342 case GL_SHADER_COMPILER:
3343 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103344 if (params) {
3345 *params = GL_TRUE;
3346 }
[email protected]b273e432010-04-12 17:23:583347 return true;
[email protected]6b8cf1a2010-05-06 16:13:583348 case GL_ARRAY_BUFFER_BINDING:
3349 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103350 if (params) {
3351 if (bound_array_buffer_) {
3352 GLuint client_id = 0;
3353 buffer_manager()->GetClientId(bound_array_buffer_->service_id(),
3354 &client_id);
3355 *params = client_id;
3356 } else {
3357 *params = 0;
3358 }
[email protected]6b8cf1a2010-05-06 16:13:583359 }
3360 return true;
3361 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
3362 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103363 if (params) {
3364 if (bound_element_array_buffer_) {
3365 GLuint client_id = 0;
3366 buffer_manager()->GetClientId(
3367 bound_element_array_buffer_->service_id(),
3368 &client_id);
3369 *params = client_id;
3370 } else {
3371 *params = 0;
3372 }
[email protected]6b8cf1a2010-05-06 16:13:583373 }
3374 return true;
3375 case GL_FRAMEBUFFER_BINDING:
[email protected]8e3e0662010-08-23 18:46:303376 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
[email protected]6b8cf1a2010-05-06 16:13:583377 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103378 if (params) {
[email protected]0d6bfdc2011-11-02 01:32:203379 FramebufferManager::FramebufferInfo* framebuffer =
3380 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER);
3381 if (framebuffer) {
[email protected]4e8a5b122010-05-08 22:00:103382 GLuint client_id = 0;
3383 framebuffer_manager()->GetClientId(
[email protected]0d6bfdc2011-11-02 01:32:203384 framebuffer->service_id(), &client_id);
[email protected]8e3e0662010-08-23 18:46:303385 *params = client_id;
3386 } else {
3387 *params = 0;
3388 }
3389 }
3390 return true;
3391 case GL_READ_FRAMEBUFFER_BINDING:
3392 *num_written = 1;
3393 if (params) {
[email protected]0d6bfdc2011-11-02 01:32:203394 FramebufferManager::FramebufferInfo* framebuffer =
3395 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER);
3396 if (framebuffer) {
[email protected]8e3e0662010-08-23 18:46:303397 GLuint client_id = 0;
3398 framebuffer_manager()->GetClientId(
[email protected]0d6bfdc2011-11-02 01:32:203399 framebuffer->service_id(), &client_id);
[email protected]4e8a5b122010-05-08 22:00:103400 *params = client_id;
3401 } else {
3402 *params = 0;
3403 }
[email protected]6b8cf1a2010-05-06 16:13:583404 }
3405 return true;
3406 case GL_RENDERBUFFER_BINDING:
3407 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103408 if (params) {
[email protected]0d6bfdc2011-11-02 01:32:203409 RenderbufferManager::RenderbufferInfo* renderbuffer =
3410 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
3411 if (renderbuffer) {
[email protected]4e8a5b122010-05-08 22:00:103412 GLuint client_id = 0;
3413 renderbuffer_manager()->GetClientId(
[email protected]0d6bfdc2011-11-02 01:32:203414 renderbuffer->service_id(), &client_id);
[email protected]4e8a5b122010-05-08 22:00:103415 *params = client_id;
3416 } else {
3417 *params = 0;
3418 }
[email protected]6b8cf1a2010-05-06 16:13:583419 }
3420 return true;
3421 case GL_CURRENT_PROGRAM:
3422 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103423 if (params) {
3424 if (current_program_) {
3425 GLuint client_id = 0;
3426 program_manager()->GetClientId(
3427 current_program_->service_id(), &client_id);
3428 *params = client_id;
3429 } else {
3430 *params = 0;
3431 }
[email protected]6b8cf1a2010-05-06 16:13:583432 }
3433 return true;
[email protected]4e8a5b122010-05-08 22:00:103434 case GL_TEXTURE_BINDING_2D:
3435 *num_written = 1;
3436 if (params) {
[email protected]6b8cf1a2010-05-06 16:13:583437 TextureUnit& unit = texture_units_[active_texture_unit_];
3438 if (unit.bound_texture_2d) {
3439 GLuint client_id = 0;
3440 texture_manager()->GetClientId(
3441 unit.bound_texture_2d->service_id(), &client_id);
3442 *params = client_id;
3443 } else {
3444 *params = 0;
3445 }
[email protected]6b8cf1a2010-05-06 16:13:583446 }
[email protected]4e8a5b122010-05-08 22:00:103447 return true;
3448 case GL_TEXTURE_BINDING_CUBE_MAP:
3449 *num_written = 1;
3450 if (params) {
[email protected]6b8cf1a2010-05-06 16:13:583451 TextureUnit& unit = texture_units_[active_texture_unit_];
3452 if (unit.bound_texture_cube_map) {
3453 GLuint client_id = 0;
3454 texture_manager()->GetClientId(
3455 unit.bound_texture_cube_map->service_id(), &client_id);
3456 *params = client_id;
3457 } else {
3458 *params = 0;
3459 }
[email protected]6b8cf1a2010-05-06 16:13:583460 }
[email protected]4e8a5b122010-05-08 22:00:103461 return true;
[email protected]61eeb33f2011-07-26 15:30:313462 case GL_TEXTURE_BINDING_EXTERNAL_OES:
3463 *num_written = 1;
3464 if (params) {
3465 TextureUnit& unit = texture_units_[active_texture_unit_];
3466 if (unit.bound_texture_external_oes) {
3467 GLuint client_id = 0;
3468 texture_manager()->GetClientId(
3469 unit.bound_texture_external_oes->service_id(), &client_id);
3470 *params = client_id;
3471 } else {
3472 *params = 0;
3473 }
3474 }
3475 return true;
[email protected]b273e432010-04-12 17:23:583476 default:
[email protected]4e8a5b122010-05-08 22:00:103477 *num_written = util_.GLGetNumValuesReturned(pname);
[email protected]c5d798342010-09-24 20:42:533478 return false;
[email protected]b273e432010-04-12 17:23:583479 }
3480}
3481
[email protected]4e8a5b122010-05-08 22:00:103482bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
3483 GLenum pname, GLsizei* num_values) {
3484 return GetHelper(pname, NULL, num_values);
3485}
3486
[email protected]b273e432010-04-12 17:23:583487void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
3488 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:103489 GLsizei num_written = 0;
3490 if (GetHelper(pname, NULL, &num_written)) {
3491 scoped_array<GLint> values(new GLint[num_written]);
3492 GetHelper(pname, values.get(), &num_written);
[email protected]b273e432010-04-12 17:23:583493 for (GLsizei ii = 0; ii < num_written; ++ii) {
3494 params[ii] = static_cast<GLboolean>(values[ii]);
3495 }
3496 } else {
3497 glGetBooleanv(pname, params);
3498 }
3499}
3500
3501void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
3502 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:103503 GLsizei num_written = 0;
3504 if (GetHelper(pname, NULL, &num_written)) {
3505 scoped_array<GLint> values(new GLint[num_written]);
3506 GetHelper(pname, values.get(), &num_written);
[email protected]b273e432010-04-12 17:23:583507 for (GLsizei ii = 0; ii < num_written; ++ii) {
3508 params[ii] = static_cast<GLfloat>(values[ii]);
3509 }
3510 } else {
3511 glGetFloatv(pname, params);
3512 }
3513}
3514
3515void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
3516 DCHECK(params);
3517 GLsizei num_written;
3518 if (!GetHelper(pname, params, &num_written)) {
3519 glGetIntegerv(pname, params);
3520 }
3521}
3522
[email protected]a0c3e972010-04-21 00:49:133523void GLES2DecoderImpl::DoGetProgramiv(
3524 GLuint program_id, GLenum pname, GLint* params) {
[email protected]6b8cf1a2010-05-06 16:13:583525 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3526 program_id, "glGetProgramiv");
[email protected]a0c3e972010-04-21 00:49:133527 if (!info) {
[email protected]a0c3e972010-04-21 00:49:133528 return;
3529 }
3530 info->GetProgramiv(pname, params);
3531}
3532
[email protected]258a3313f2011-10-18 20:13:573533void GLES2DecoderImpl::DoBindAttribLocation(
3534 GLuint program, GLuint index, const char* name) {
3535 if (!StringIsValidForGLES(name)) {
3536 SetGLError(GL_INVALID_VALUE, "glBindAttribLocation: Invalid character");
3537 return;
3538 }
[email protected]6b8cf1a2010-05-06 16:13:583539 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3540 program, "glBindAttribLocation");
[email protected]ae51d192010-04-27 00:48:033541 if (!info) {
[email protected]258a3313f2011-10-18 20:13:573542 return;
[email protected]558847a2010-03-24 07:02:543543 }
[email protected]258a3313f2011-10-18 20:13:573544 glBindAttribLocation(info->service_id(), index, name);
3545}
3546
3547error::Error GLES2DecoderImpl::HandleBindAttribLocation(
3548 uint32 immediate_data_size, const gles2::BindAttribLocation& c) {
3549 GLuint program = static_cast<GLuint>(c.program);
[email protected]558847a2010-03-24 07:02:543550 GLuint index = static_cast<GLuint>(c.index);
3551 uint32 name_size = c.data_size;
3552 const char* name = GetSharedMemoryAs<const char*>(
3553 c.name_shm_id, c.name_shm_offset, name_size);
3554 if (name == NULL) {
3555 return error::kOutOfBounds;
3556 }
3557 String name_str(name, name_size);
[email protected]258a3313f2011-10-18 20:13:573558 DoBindAttribLocation(program, index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543559 return error::kNoError;
3560}
3561
3562error::Error GLES2DecoderImpl::HandleBindAttribLocationImmediate(
3563 uint32 immediate_data_size, const gles2::BindAttribLocationImmediate& c) {
[email protected]6b8cf1a2010-05-06 16:13:583564 GLuint program = static_cast<GLuint>(c.program);
[email protected]558847a2010-03-24 07:02:543565 GLuint index = static_cast<GLuint>(c.index);
3566 uint32 name_size = c.data_size;
3567 const char* name = GetImmediateDataAs<const char*>(
3568 c, name_size, immediate_data_size);
3569 if (name == NULL) {
3570 return error::kOutOfBounds;
3571 }
3572 String name_str(name, name_size);
[email protected]258a3313f2011-10-18 20:13:573573 DoBindAttribLocation(program, index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543574 return error::kNoError;
3575}
3576
3577error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
3578 uint32 immediate_data_size, const gles2::BindAttribLocationBucket& c) {
[email protected]6b8cf1a2010-05-06 16:13:583579 GLuint program = static_cast<GLuint>(c.program);
[email protected]558847a2010-03-24 07:02:543580 GLuint index = static_cast<GLuint>(c.index);
3581 Bucket* bucket = GetBucket(c.name_bucket_id);
3582 if (!bucket || bucket->size() == 0) {
3583 return error::kInvalidArguments;
3584 }
3585 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:183586 if (!bucket->GetAsString(&name_str)) {
3587 return error::kInvalidArguments;
3588 }
[email protected]258a3313f2011-10-18 20:13:573589 DoBindAttribLocation(program, index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543590 return error::kNoError;
3591}
3592
[email protected]f7a64ee2010-02-01 22:24:143593error::Error GLES2DecoderImpl::HandleDeleteShader(
[email protected]ba3176a2009-12-16 18:19:463594 uint32 immediate_data_size, const gles2::DeleteShader& c) {
[email protected]ae51d192010-04-27 00:48:033595 GLuint client_id = c.shader;
3596 if (client_id) {
3597 ShaderManager::ShaderInfo* info = GetShaderInfo(client_id);
3598 if (info) {
[email protected]ca488e12010-12-13 20:06:143599 if (!info->IsDeleted()) {
3600 glDeleteShader(info->service_id());
3601 shader_manager()->MarkAsDeleted(info);
3602 }
[email protected]ae51d192010-04-27 00:48:033603 } else {
[email protected]8eee29c2010-04-29 03:38:293604 SetGLError(GL_INVALID_VALUE, "glDeleteShader: unknown shader");
[email protected]ae51d192010-04-27 00:48:033605 }
[email protected]96449d2c2009-11-25 00:01:323606 }
[email protected]f7a64ee2010-02-01 22:24:143607 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323608}
3609
[email protected]f7a64ee2010-02-01 22:24:143610error::Error GLES2DecoderImpl::HandleDeleteProgram(
[email protected]ba3176a2009-12-16 18:19:463611 uint32 immediate_data_size, const gles2::DeleteProgram& c) {
[email protected]ae51d192010-04-27 00:48:033612 GLuint client_id = c.program;
3613 if (client_id) {
3614 ProgramManager::ProgramInfo* info = GetProgramInfo(client_id);
3615 if (info) {
[email protected]ca488e12010-12-13 20:06:143616 if (!info->IsDeleted()) {
3617 glDeleteProgram(info->service_id());
3618 program_manager()->MarkAsDeleted(shader_manager(), info);
3619 }
[email protected]ae51d192010-04-27 00:48:033620 } else {
[email protected]8eee29c2010-04-29 03:38:293621 SetGLError(GL_INVALID_VALUE, "glDeleteProgram: unknown program");
[email protected]ae51d192010-04-27 00:48:033622 }
[email protected]96449d2c2009-11-25 00:01:323623 }
[email protected]f7a64ee2010-02-01 22:24:143624 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323625}
3626
[email protected]269200b12010-11-18 22:53:063627void GLES2DecoderImpl::DoDeleteSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:103628 GLuint namespace_id, GLsizei n, const GLuint* ids) {
[email protected]3b1ecc262011-08-03 22:49:573629 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
[email protected]066849e32010-05-03 19:14:103630 for (GLsizei ii = 0; ii < n; ++ii) {
3631 id_allocator->FreeID(ids[ii]);
3632 }
3633}
3634
[email protected]269200b12010-11-18 22:53:063635error::Error GLES2DecoderImpl::HandleDeleteSharedIdsCHROMIUM(
3636 uint32 immediate_data_size, const gles2::DeleteSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:103637 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
3638 GLsizei n = static_cast<GLsizei>(c.n);
3639 uint32 data_size;
3640 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
3641 return error::kOutOfBounds;
3642 }
3643 const GLuint* ids = GetSharedMemoryAs<const GLuint*>(
3644 c.ids_shm_id, c.ids_shm_offset, data_size);
3645 if (n < 0) {
[email protected]269200b12010-11-18 22:53:063646 SetGLError(GL_INVALID_VALUE, "DeleteSharedIdsCHROMIUM: n < 0");
[email protected]066849e32010-05-03 19:14:103647 return error::kNoError;
3648 }
3649 if (ids == NULL) {
3650 return error::kOutOfBounds;
3651 }
[email protected]269200b12010-11-18 22:53:063652 DoDeleteSharedIdsCHROMIUM(namespace_id, n, ids);
[email protected]066849e32010-05-03 19:14:103653 return error::kNoError;
3654}
3655
[email protected]269200b12010-11-18 22:53:063656void GLES2DecoderImpl::DoGenSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:103657 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids) {
[email protected]3b1ecc262011-08-03 22:49:573658 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
[email protected]066849e32010-05-03 19:14:103659 if (id_offset == 0) {
3660 for (GLsizei ii = 0; ii < n; ++ii) {
3661 ids[ii] = id_allocator->AllocateID();
3662 }
3663 } else {
3664 for (GLsizei ii = 0; ii < n; ++ii) {
3665 ids[ii] = id_allocator->AllocateIDAtOrAbove(id_offset);
3666 id_offset = ids[ii] + 1;
3667 }
3668 }
3669}
3670
[email protected]269200b12010-11-18 22:53:063671error::Error GLES2DecoderImpl::HandleGenSharedIdsCHROMIUM(
3672 uint32 immediate_data_size, const gles2::GenSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:103673 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
3674 GLuint id_offset = static_cast<GLuint>(c.id_offset);
3675 GLsizei n = static_cast<GLsizei>(c.n);
3676 uint32 data_size;
3677 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
3678 return error::kOutOfBounds;
3679 }
3680 GLuint* ids = GetSharedMemoryAs<GLuint*>(
3681 c.ids_shm_id, c.ids_shm_offset, data_size);
3682 if (n < 0) {
[email protected]269200b12010-11-18 22:53:063683 SetGLError(GL_INVALID_VALUE, "GenSharedIdsCHROMIUM: n < 0");
[email protected]066849e32010-05-03 19:14:103684 return error::kNoError;
3685 }
3686 if (ids == NULL) {
3687 return error::kOutOfBounds;
3688 }
[email protected]269200b12010-11-18 22:53:063689 DoGenSharedIdsCHROMIUM(namespace_id, id_offset, n, ids);
[email protected]066849e32010-05-03 19:14:103690 return error::kNoError;
3691}
3692
[email protected]269200b12010-11-18 22:53:063693void GLES2DecoderImpl::DoRegisterSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:103694 GLuint namespace_id, GLsizei n, const GLuint* ids) {
[email protected]3b1ecc262011-08-03 22:49:573695 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
[email protected]066849e32010-05-03 19:14:103696 for (GLsizei ii = 0; ii < n; ++ii) {
3697 if (!id_allocator->MarkAsUsed(ids[ii])) {
3698 for (GLsizei jj = 0; jj < ii; ++jj) {
3699 id_allocator->FreeID(ids[jj]);
3700 }
3701 SetGLError(
3702 GL_INVALID_VALUE,
[email protected]269200b12010-11-18 22:53:063703 "RegisterSharedIdsCHROMIUM: attempt to register "
3704 "id that already exists");
[email protected]066849e32010-05-03 19:14:103705 return;
3706 }
3707 }
3708}
3709
[email protected]269200b12010-11-18 22:53:063710error::Error GLES2DecoderImpl::HandleRegisterSharedIdsCHROMIUM(
3711 uint32 immediate_data_size, const gles2::RegisterSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:103712 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
3713 GLsizei n = static_cast<GLsizei>(c.n);
3714 uint32 data_size;
3715 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
3716 return error::kOutOfBounds;
3717 }
3718 GLuint* ids = GetSharedMemoryAs<GLuint*>(
3719 c.ids_shm_id, c.ids_shm_offset, data_size);
3720 if (n < 0) {
[email protected]269200b12010-11-18 22:53:063721 SetGLError(GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM: n < 0");
[email protected]066849e32010-05-03 19:14:103722 return error::kNoError;
3723 }
3724 if (ids == NULL) {
3725 return error::kOutOfBounds;
3726 }
[email protected]269200b12010-11-18 22:53:063727 DoRegisterSharedIdsCHROMIUM(namespace_id, n, ids);
[email protected]066849e32010-05-03 19:14:103728 return error::kNoError;
3729}
3730
[email protected]3a03a8f2011-03-19 00:51:273731void GLES2DecoderImpl::DoClear(GLbitfield mask) {
[email protected]0d6bfdc2011-11-02 01:32:203732 if (CheckBoundFramebuffersValid("glClear")) {
[email protected]297ca1c2011-06-20 23:08:463733 ApplyDirtyState();
[email protected]3a03a8f2011-03-19 00:51:273734 glClear(mask);
3735 }
3736}
3737
[email protected]36cef8ce2010-03-16 07:34:453738void GLES2DecoderImpl::DoFramebufferRenderbuffer(
3739 GLenum target, GLenum attachment, GLenum renderbuffertarget,
[email protected]ae51d192010-04-27 00:48:033740 GLuint client_renderbuffer_id) {
[email protected]8e3e0662010-08-23 18:46:303741 FramebufferManager::FramebufferInfo* framebuffer_info =
3742 GetFramebufferInfoForTarget(target);
3743 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:293744 SetGLError(GL_INVALID_OPERATION,
3745 "glFramebufferRenderbuffer: no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:453746 return;
3747 }
[email protected]ae51d192010-04-27 00:48:033748 GLuint service_id = 0;
[email protected]3a2e7c7b2010-08-06 01:12:283749 RenderbufferManager::RenderbufferInfo* info = NULL;
[email protected]ae51d192010-04-27 00:48:033750 if (client_renderbuffer_id) {
[email protected]3a2e7c7b2010-08-06 01:12:283751 info = GetRenderbufferInfo(client_renderbuffer_id);
[email protected]ae51d192010-04-27 00:48:033752 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293753 SetGLError(GL_INVALID_OPERATION,
3754 "glFramebufferRenderbuffer: unknown renderbuffer");
[email protected]ae51d192010-04-27 00:48:033755 return;
3756 }
3757 service_id = info->service_id();
3758 }
[email protected]9edc6b22010-12-23 02:00:263759 CopyRealGLErrorsToWrapper();
[email protected]ae51d192010-04-27 00:48:033760 glFramebufferRenderbufferEXT(
3761 target, attachment, renderbuffertarget, service_id);
[email protected]1002c2d2011-06-28 22:39:043762 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:263763 if (error == GL_NO_ERROR) {
[email protected]8e3e0662010-08-23 18:46:303764 framebuffer_info->AttachRenderbuffer(attachment, info);
[email protected]3a2e7c7b2010-08-06 01:12:283765 }
[email protected]297ca1c2011-06-20 23:08:463766 if (framebuffer_info == bound_draw_framebuffer_) {
3767 state_dirty_ = true;
3768 }
[email protected]3a2e7c7b2010-08-06 01:12:283769}
3770
[email protected]297ca1c2011-06-20 23:08:463771bool GLES2DecoderImpl::SetCapabilityState(GLenum cap, bool enabled) {
[email protected]3a2e7c7b2010-08-06 01:12:283772 switch (cap) {
3773 case GL_SCISSOR_TEST:
3774 enable_scissor_test_ = enabled;
[email protected]297ca1c2011-06-20 23:08:463775 return true;
3776 case GL_DEPTH_TEST: {
3777 if (enable_depth_test_ != enabled) {
3778 enable_depth_test_ = enabled;
3779 state_dirty_ = true;
3780 }
3781 return false;
3782 }
3783 case GL_STENCIL_TEST:
3784 if (enable_stencil_test_ != enabled) {
3785 enable_stencil_test_ = enabled;
3786 state_dirty_ = true;
3787 }
3788 return false;
[email protected]3a2e7c7b2010-08-06 01:12:283789 default:
[email protected]297ca1c2011-06-20 23:08:463790 return true;
[email protected]3a2e7c7b2010-08-06 01:12:283791 }
3792}
3793
3794void GLES2DecoderImpl::DoDisable(GLenum cap) {
[email protected]297ca1c2011-06-20 23:08:463795 if (SetCapabilityState(cap, false)) {
3796 glDisable(cap);
3797 }
[email protected]3a2e7c7b2010-08-06 01:12:283798}
3799
3800void GLES2DecoderImpl::DoEnable(GLenum cap) {
[email protected]297ca1c2011-06-20 23:08:463801 if (SetCapabilityState(cap, true)) {
3802 glEnable(cap);
3803 }
[email protected]3a2e7c7b2010-08-06 01:12:283804}
3805
3806void GLES2DecoderImpl::DoClearColor(
3807 GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {
3808 clear_red_ = red;
3809 clear_green_ = green;
3810 clear_blue_ = blue;
3811 clear_alpha_ = alpha;
3812 glClearColor(red, green, blue, alpha);
3813}
3814
3815void GLES2DecoderImpl::DoClearDepthf(GLclampf depth) {
3816 clear_depth_ = depth;
3817 glClearDepth(depth);
3818}
3819
3820void GLES2DecoderImpl::DoClearStencil(GLint s) {
3821 clear_stencil_ = s;
3822 glClearStencil(s);
3823}
3824
3825void GLES2DecoderImpl::DoColorMask(
3826 GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {
3827 mask_red_ = red;
3828 mask_green_ = green;
3829 mask_blue_ = blue;
3830 mask_alpha_ = alpha;
[email protected]297ca1c2011-06-20 23:08:463831 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:283832}
3833
3834void GLES2DecoderImpl::DoDepthMask(GLboolean depth) {
3835 mask_depth_ = depth;
[email protected]297ca1c2011-06-20 23:08:463836 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:283837}
3838
3839void GLES2DecoderImpl::DoStencilMask(GLuint mask) {
3840 mask_stencil_front_ = mask;
3841 mask_stencil_back_ = mask;
[email protected]297ca1c2011-06-20 23:08:463842 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:283843}
3844
3845void GLES2DecoderImpl::DoStencilMaskSeparate(GLenum face, GLuint mask) {
[email protected]297ca1c2011-06-20 23:08:463846 if (face == GL_FRONT || face == GL_FRONT_AND_BACK) {
[email protected]3a2e7c7b2010-08-06 01:12:283847 mask_stencil_front_ = mask;
[email protected]297ca1c2011-06-20 23:08:463848 }
3849 if (face == GL_BACK || face == GL_FRONT_AND_BACK) {
[email protected]3a2e7c7b2010-08-06 01:12:283850 mask_stencil_back_ = mask;
3851 }
[email protected]297ca1c2011-06-20 23:08:463852 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:283853}
3854
[email protected]0d6bfdc2011-11-02 01:32:203855// Assumes framebuffer is complete.
3856void GLES2DecoderImpl::ClearUnclearedAttachments(
[email protected]8e3e0662010-08-23 18:46:303857 GLenum target, FramebufferManager::FramebufferInfo* info) {
[email protected]8e3e0662010-08-23 18:46:303858 if (target == GL_READ_FRAMEBUFFER_EXT) {
[email protected]0d6bfdc2011-11-02 01:32:203859 // bind this to the DRAW point, clear then bind back to READ
3860 // TODO(gman): I don't think there is any guarantee that an FBO that
3861 // is complete on the READ attachment will be complete as a DRAW
3862 // attachment.
3863 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
3864 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, info->service_id());
[email protected]8e3e0662010-08-23 18:46:303865 }
[email protected]3a2e7c7b2010-08-06 01:12:283866 GLbitfield clear_bits = 0;
3867 if (info->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0)) {
[email protected]297ca1c2011-06-20 23:08:463868 glClearColor(
[email protected]0d6bfdc2011-11-02 01:32:203869 0.0f, 0.0f, 0.0f,
[email protected]297ca1c2011-06-20 23:08:463870 (GLES2Util::GetChannelsForFormat(
[email protected]0d6bfdc2011-11-02 01:32:203871 info->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0.0f : 1.0f);
[email protected]3a2e7c7b2010-08-06 01:12:283872 glColorMask(true, true, true, true);
3873 clear_bits |= GL_COLOR_BUFFER_BIT;
3874 }
3875
3876 if (info->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) ||
3877 info->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
3878 glClearStencil(0);
3879 glStencilMask(-1);
3880 clear_bits |= GL_STENCIL_BUFFER_BIT;
3881 }
3882
3883 if (info->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
3884 info->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
3885 glClearDepth(1.0f);
3886 glDepthMask(true);
3887 clear_bits |= GL_DEPTH_BUFFER_BIT;
3888 }
3889
3890 glDisable(GL_SCISSOR_TEST);
3891 glClear(clear_bits);
3892
[email protected]0d6bfdc2011-11-02 01:32:203893 info->MarkAttachmentsAsCleared(renderbuffer_manager(), texture_manager());
[email protected]3a2e7c7b2010-08-06 01:12:283894
[email protected]c007aa02010-09-02 22:22:403895 RestoreClearState();
3896
3897 if (target == GL_READ_FRAMEBUFFER_EXT) {
[email protected]0d6bfdc2011-11-02 01:32:203898 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, info->service_id());
3899 FramebufferManager::FramebufferInfo*framebuffer =
3900 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER);
3901 glBindFramebufferEXT(
3902 GL_DRAW_FRAMEBUFFER_EXT, framebuffer ? framebuffer->service_id() : 0);
[email protected]c007aa02010-09-02 22:22:403903 }
3904}
3905
3906void GLES2DecoderImpl::RestoreClearState() {
[email protected]297ca1c2011-06-20 23:08:463907 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:283908 glClearColor(clear_red_, clear_green_, clear_blue_, clear_alpha_);
[email protected]3a2e7c7b2010-08-06 01:12:283909 glClearStencil(clear_stencil_);
[email protected]3a2e7c7b2010-08-06 01:12:283910 glClearDepth(clear_depth_);
[email protected]3a2e7c7b2010-08-06 01:12:283911 if (enable_scissor_test_) {
3912 glEnable(GL_SCISSOR_TEST);
3913 }
[email protected]36cef8ce2010-03-16 07:34:453914}
3915
3916GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
[email protected]0d6bfdc2011-11-02 01:32:203917 FramebufferManager::FramebufferInfo* framebuffer =
[email protected]8e3e0662010-08-23 18:46:303918 GetFramebufferInfoForTarget(target);
[email protected]0d6bfdc2011-11-02 01:32:203919 if (!framebuffer) {
[email protected]36cef8ce2010-03-16 07:34:453920 return GL_FRAMEBUFFER_COMPLETE;
3921 }
[email protected]0d6bfdc2011-11-02 01:32:203922 GLenum completeness = framebuffer->IsPossiblyComplete();
3923 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
3924 return completeness;
3925 }
[email protected]36cef8ce2010-03-16 07:34:453926 return glCheckFramebufferStatusEXT(target);
3927}
3928
3929void GLES2DecoderImpl::DoFramebufferTexture2D(
[email protected]ae51d192010-04-27 00:48:033930 GLenum target, GLenum attachment, GLenum textarget,
3931 GLuint client_texture_id, GLint level) {
[email protected]8e3e0662010-08-23 18:46:303932 FramebufferManager::FramebufferInfo* framebuffer_info =
3933 GetFramebufferInfoForTarget(target);
3934 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:293935 SetGLError(GL_INVALID_OPERATION,
3936 "glFramebufferTexture2D: no framebuffer bound.");
[email protected]36cef8ce2010-03-16 07:34:453937 return;
3938 }
[email protected]ae51d192010-04-27 00:48:033939 GLuint service_id = 0;
[email protected]3a2e7c7b2010-08-06 01:12:283940 TextureManager::TextureInfo* info = NULL;
[email protected]ae51d192010-04-27 00:48:033941 if (client_texture_id) {
[email protected]3a2e7c7b2010-08-06 01:12:283942 info = GetTextureInfo(client_texture_id);
[email protected]ae51d192010-04-27 00:48:033943 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293944 SetGLError(GL_INVALID_OPERATION,
3945 "glFramebufferTexture2D: unknown texture");
[email protected]ae51d192010-04-27 00:48:033946 return;
3947 }
3948 service_id = info->service_id();
3949 }
[email protected]0d6bfdc2011-11-02 01:32:203950
3951 if (!texture_manager()->ValidForTarget(
3952 feature_info_, textarget, level, 0, 0, 1)) {
3953 SetGLError(GL_INVALID_VALUE,
3954 "glFramebufferTexture2D: level out of range");
3955 return;
3956 }
3957
[email protected]9edc6b22010-12-23 02:00:263958 CopyRealGLErrorsToWrapper();
[email protected]ae51d192010-04-27 00:48:033959 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
[email protected]1002c2d2011-06-28 22:39:043960 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:263961 if (error == GL_NO_ERROR) {
3962 framebuffer_info->AttachTexture(attachment, info, textarget, level);
[email protected]3a2e7c7b2010-08-06 01:12:283963 }
[email protected]297ca1c2011-06-20 23:08:463964 if (framebuffer_info == bound_draw_framebuffer_) {
3965 state_dirty_ = true;
3966 }
[email protected]36cef8ce2010-03-16 07:34:453967}
3968
3969void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
3970 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
[email protected]8e3e0662010-08-23 18:46:303971 FramebufferManager::FramebufferInfo* framebuffer_info =
3972 GetFramebufferInfoForTarget(target);
3973 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:293974 SetGLError(GL_INVALID_OPERATION,
3975 "glFramebufferAttachmentParameteriv: no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:453976 return;
3977 }
3978 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
[email protected]74c1ec42010-08-12 01:55:573979 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
3980 GLint type = 0;
3981 GLuint client_id = 0;
3982 glGetFramebufferAttachmentParameterivEXT(
3983 target, attachment, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &type);
3984 switch (type) {
3985 case GL_RENDERBUFFER: {
3986 renderbuffer_manager()->GetClientId(*params, &client_id);
3987 break;
3988 }
3989 case GL_TEXTURE: {
3990 texture_manager()->GetClientId(*params, &client_id);
3991 break;
3992 }
3993 default:
3994 break;
3995 }
3996 *params = client_id;
3997 }
[email protected]36cef8ce2010-03-16 07:34:453998}
3999
4000void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
4001 GLenum target, GLenum pname, GLint* params) {
[email protected]0d6bfdc2011-11-02 01:32:204002 RenderbufferManager::RenderbufferInfo* renderbuffer =
4003 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4004 if (!renderbuffer) {
[email protected]8eee29c2010-04-29 03:38:294005 SetGLError(GL_INVALID_OPERATION,
4006 "glGetRenderbufferParameteriv: no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:454007 return;
4008 }
[email protected]3a03a8f2011-03-19 00:51:274009 switch (pname) {
4010 case GL_RENDERBUFFER_INTERNAL_FORMAT:
[email protected]0d6bfdc2011-11-02 01:32:204011 *params = renderbuffer->internal_format();
[email protected]3a03a8f2011-03-19 00:51:274012 break;
4013 case GL_RENDERBUFFER_WIDTH:
[email protected]0d6bfdc2011-11-02 01:32:204014 *params = renderbuffer->width();
[email protected]3a03a8f2011-03-19 00:51:274015 break;
4016 case GL_RENDERBUFFER_HEIGHT:
[email protected]0d6bfdc2011-11-02 01:32:204017 *params = renderbuffer->height();
[email protected]3a03a8f2011-03-19 00:51:274018 break;
4019 default:
4020 glGetRenderbufferParameterivEXT(target, pname, params);
4021 break;
[email protected]b71f52c2010-06-18 22:20:204022 }
[email protected]36cef8ce2010-03-16 07:34:454023}
4024
[email protected]8e3e0662010-08-23 18:46:304025void GLES2DecoderImpl::DoBlitFramebufferEXT(
4026 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
4027 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
4028 GLbitfield mask, GLenum filter) {
[email protected]a3ded6d2010-10-19 06:44:394029 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:304030 SetGLError(GL_INVALID_OPERATION,
4031 "glBlitFramebufferEXT: function not available");
4032 }
[email protected]5094b0f2010-11-09 19:45:244033 if (IsAngle()) {
4034 glBlitFramebufferANGLE(
4035 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
4036 } else {
4037 glBlitFramebufferEXT(
4038 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
4039 }
[email protected]8e3e0662010-08-23 18:46:304040}
4041
4042void GLES2DecoderImpl::DoRenderbufferStorageMultisample(
4043 GLenum target, GLsizei samples, GLenum internalformat,
4044 GLsizei width, GLsizei height) {
[email protected]a3ded6d2010-10-19 06:44:394045 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:304046 SetGLError(GL_INVALID_OPERATION,
4047 "glRenderbufferStorageMultisampleEXT: function not available");
4048 return;
4049 }
[email protected]8e3e0662010-08-23 18:46:304050
[email protected]0d6bfdc2011-11-02 01:32:204051 RenderbufferManager::RenderbufferInfo* renderbuffer =
4052 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4053 if (!renderbuffer) {
4054 SetGLError(GL_INVALID_OPERATION,
4055 "glGetRenderbufferStorageMultisample: no renderbuffer bound");
4056 return;
4057 }
4058
[email protected]84afefa2011-10-19 21:45:534059 if (samples > renderbuffer_manager()->max_samples()) {
4060 SetGLError(GL_INVALID_VALUE,
4061 "glGetRenderbufferStorageMultisample: samples too large");
4062 return;
4063 }
4064
4065 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
4066 height > renderbuffer_manager()->max_renderbuffer_size()) {
4067 SetGLError(GL_INVALID_VALUE,
4068 "glGetRenderbufferStorageMultisample: size too large");
4069 return;
4070 }
4071
[email protected]9edc6b22010-12-23 02:00:264072 GLenum impl_format = internalformat;
[email protected]8e3e0662010-08-23 18:46:304073 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
[email protected]9edc6b22010-12-23 02:00:264074 switch (impl_format) {
[email protected]8e3e0662010-08-23 18:46:304075 case GL_DEPTH_COMPONENT16:
[email protected]9edc6b22010-12-23 02:00:264076 impl_format = GL_DEPTH_COMPONENT;
[email protected]8e3e0662010-08-23 18:46:304077 break;
4078 case GL_RGBA4:
4079 case GL_RGB5_A1:
[email protected]9edc6b22010-12-23 02:00:264080 impl_format = GL_RGBA;
[email protected]8e3e0662010-08-23 18:46:304081 break;
4082 case GL_RGB565:
[email protected]9edc6b22010-12-23 02:00:264083 impl_format = GL_RGB;
[email protected]8e3e0662010-08-23 18:46:304084 break;
4085 }
4086 }
4087
[email protected]9edc6b22010-12-23 02:00:264088 CopyRealGLErrorsToWrapper();
[email protected]866b91c52011-03-23 14:38:084089 if (IsAngle()) {
4090 glRenderbufferStorageMultisampleANGLE(
4091 target, samples, impl_format, width, height);
4092 } else {
4093 glRenderbufferStorageMultisampleEXT(
4094 target, samples, impl_format, width, height);
4095 }
[email protected]1002c2d2011-06-28 22:39:044096 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:264097 if (error == GL_NO_ERROR) {
[email protected]0d6bfdc2011-11-02 01:32:204098 renderbuffer_manager()->SetInfo(
4099 renderbuffer, samples, internalformat, width, height);
[email protected]9edc6b22010-12-23 02:00:264100 }
[email protected]8e3e0662010-08-23 18:46:304101}
4102
[email protected]36cef8ce2010-03-16 07:34:454103void GLES2DecoderImpl::DoRenderbufferStorage(
4104 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
[email protected]0d6bfdc2011-11-02 01:32:204105 RenderbufferManager::RenderbufferInfo* renderbuffer =
4106 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4107 if (!renderbuffer) {
[email protected]8eee29c2010-04-29 03:38:294108 SetGLError(GL_INVALID_OPERATION,
4109 "glGetRenderbufferStorage: no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:454110 return;
4111 }
[email protected]876f6fee2010-08-02 23:10:324112
[email protected]84afefa2011-10-19 21:45:534113 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
4114 height > renderbuffer_manager()->max_renderbuffer_size()) {
4115 SetGLError(GL_INVALID_VALUE,
4116 "glGetRenderbufferStorage: size too large");
4117 return;
4118 }
4119
[email protected]9edc6b22010-12-23 02:00:264120 GLenum impl_format = internalformat;
[email protected]876f6fee2010-08-02 23:10:324121 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
[email protected]9edc6b22010-12-23 02:00:264122 switch (impl_format) {
[email protected]876f6fee2010-08-02 23:10:324123 case GL_DEPTH_COMPONENT16:
[email protected]9edc6b22010-12-23 02:00:264124 impl_format = GL_DEPTH_COMPONENT;
[email protected]876f6fee2010-08-02 23:10:324125 break;
4126 case GL_RGBA4:
4127 case GL_RGB5_A1:
[email protected]9edc6b22010-12-23 02:00:264128 impl_format = GL_RGBA;
[email protected]876f6fee2010-08-02 23:10:324129 break;
4130 case GL_RGB565:
[email protected]9edc6b22010-12-23 02:00:264131 impl_format = GL_RGB;
[email protected]876f6fee2010-08-02 23:10:324132 break;
4133 }
[email protected]b71f52c2010-06-18 22:20:204134 }
[email protected]876f6fee2010-08-02 23:10:324135
[email protected]9edc6b22010-12-23 02:00:264136 CopyRealGLErrorsToWrapper();
4137 glRenderbufferStorageEXT(target, impl_format, width, height);
[email protected]1002c2d2011-06-28 22:39:044138 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:264139 if (error == GL_NO_ERROR) {
[email protected]0d6bfdc2011-11-02 01:32:204140 renderbuffer_manager()->SetInfo(
4141 renderbuffer, 0, internalformat, width, height);
[email protected]9edc6b22010-12-23 02:00:264142 }
[email protected]36cef8ce2010-03-16 07:34:454143}
4144
[email protected]07f54fcc2009-12-22 02:46:304145void GLES2DecoderImpl::DoLinkProgram(GLuint program) {
[email protected]0c8fabf2011-06-14 19:35:224146 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
[email protected]6b8cf1a2010-05-06 16:13:584147 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
4148 program, "glLinkProgram");
[email protected]a93bb842010-02-16 23:03:474149 if (!info) {
[email protected]a93bb842010-02-16 23:03:474150 return;
4151 }
[email protected]05afda12011-01-20 00:17:344152
[email protected]d685a682011-04-29 16:19:574153 info->Link();
[email protected]07f54fcc2009-12-22 02:46:304154};
4155
[email protected]3916c97e2010-02-25 03:20:504156void GLES2DecoderImpl::DoTexParameterf(
4157 GLenum target, GLenum pname, GLfloat param) {
4158 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]07f54fcc2009-12-22 02:46:304159 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294160 SetGLError(GL_INVALID_VALUE, "glTexParameterf: unknown texture");
[email protected]cbb22e42011-05-12 23:36:244161 return;
[email protected]07f54fcc2009-12-22 02:46:304162 }
[email protected]cbb22e42011-05-12 23:36:244163
4164 if (!texture_manager()->SetParameter(
4165 feature_info_, info, pname, static_cast<GLint>(param))) {
4166 SetGLError(GL_INVALID_ENUM, "glTexParameterf: param GL_INVALID_ENUM");
4167 return;
4168 }
4169 glTexParameterf(target, pname, param);
[email protected]07f54fcc2009-12-22 02:46:304170}
4171
[email protected]3916c97e2010-02-25 03:20:504172void GLES2DecoderImpl::DoTexParameteri(
4173 GLenum target, GLenum pname, GLint param) {
4174 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
4175 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294176 SetGLError(GL_INVALID_VALUE, "glTexParameteri: unknown texture");
[email protected]cbb22e42011-05-12 23:36:244177 return;
[email protected]3916c97e2010-02-25 03:20:504178 }
[email protected]cbb22e42011-05-12 23:36:244179
4180 if (!texture_manager()->SetParameter(feature_info_, info, pname, param)) {
4181 SetGLError(GL_INVALID_ENUM, "glTexParameteri: param GL_INVALID_ENUM");
4182 return;
4183 }
4184 glTexParameteri(target, pname, param);
[email protected]3916c97e2010-02-25 03:20:504185}
4186
4187void GLES2DecoderImpl::DoTexParameterfv(
4188 GLenum target, GLenum pname, const GLfloat* params) {
4189 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
4190 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294191 SetGLError(GL_INVALID_VALUE, "glTexParameterfv: unknown texture");
[email protected]cbb22e42011-05-12 23:36:244192 return;
[email protected]3916c97e2010-02-25 03:20:504193 }
[email protected]cbb22e42011-05-12 23:36:244194
4195 if (!texture_manager()->SetParameter(
4196 feature_info_, info, pname, static_cast<GLint>(params[0]))) {
4197 SetGLError(GL_INVALID_ENUM, "glTexParameterfv: param GL_INVALID_ENUM");
4198 return;
4199 }
4200 glTexParameterfv(target, pname, params);
[email protected]3916c97e2010-02-25 03:20:504201}
4202
4203void GLES2DecoderImpl::DoTexParameteriv(
4204 GLenum target, GLenum pname, const GLint* params) {
4205 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
4206 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294207 SetGLError(GL_INVALID_VALUE, "glTexParameteriv: unknown texture");
[email protected]cbb22e42011-05-12 23:36:244208 return;
[email protected]3916c97e2010-02-25 03:20:504209 }
[email protected]cbb22e42011-05-12 23:36:244210
4211 if (!texture_manager()->SetParameter(feature_info_, info, pname, *params)) {
4212 SetGLError(GL_INVALID_ENUM, "glTexParameteriv: param GL_INVALID_ENUM");
4213 return;
4214 }
4215 glTexParameteriv(target, pname, params);
[email protected]3916c97e2010-02-25 03:20:504216}
4217
[email protected]939e7362010-05-13 20:49:104218bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
[email protected]ca488e12010-12-13 20:06:144219 if (!current_program_) {
[email protected]939e7362010-05-13 20:49:104220 // The program does not exist.
4221 SetGLError(GL_INVALID_OPERATION,
4222 (std::string(function_name) + ": no program in use").c_str());
4223 return false;
4224 }
[email protected]ca488e12010-12-13 20:06:144225 if (!current_program_->InUse()) {
[email protected]939e7362010-05-13 20:49:104226 SetGLError(GL_INVALID_OPERATION,
4227 (std::string(function_name) + ": program not linked").c_str());
4228 return false;
4229 }
4230 return true;
4231}
4232
4233bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
4234 GLint location, const char* function_name) {
4235 if (!CheckCurrentProgram(function_name)) {
4236 return false;
4237 }
4238 return location != -1;
4239}
4240
[email protected]43c2f1f2011-03-25 18:35:364241bool GLES2DecoderImpl::PrepForSetUniformByLocation(
4242 GLint location, const char* function_name, GLenum* type, GLsizei* count) {
4243 DCHECK(type);
4244 DCHECK(count);
[email protected]939e7362010-05-13 20:49:104245 if (!CheckCurrentProgramForUniform(location, function_name)) {
4246 return false;
4247 }
[email protected]43c2f1f2011-03-25 18:35:364248 GLint array_index = -1;
4249 const ProgramManager::ProgramInfo::UniformInfo* info =
4250 current_program_->GetUniformInfoByLocation(location, &array_index);
4251 if (!info) {
[email protected]939e7362010-05-13 20:49:104252 SetGLError(GL_INVALID_OPERATION,
[email protected]43c2f1f2011-03-25 18:35:364253 (std::string(function_name) + ": unknown location").c_str());
[email protected]939e7362010-05-13 20:49:104254 return false;
4255 }
[email protected]43c2f1f2011-03-25 18:35:364256 if (*count > 1 && !info->is_array) {
4257 SetGLError(
4258 GL_INVALID_OPERATION,
4259 (std::string(function_name) + ": count > 1 for non-array").c_str());
4260 return false;
4261 }
4262 *count = std::min(info->size - array_index, *count);
4263 if (*count <= 0) {
4264 return false;
4265 }
4266 *type = info->type;
[email protected]939e7362010-05-13 20:49:104267 return true;
4268}
4269
[email protected]939e7362010-05-13 20:49:104270void GLES2DecoderImpl::DoUniform1i(GLint location, GLint v0) {
4271 if (!CheckCurrentProgramForUniform(location, "glUniform1i")) {
[email protected]3916c97e2010-02-25 03:20:504272 return;
4273 }
4274 current_program_->SetSamplers(location, 1, &v0);
4275 glUniform1i(location, v0);
4276}
4277
4278void GLES2DecoderImpl::DoUniform1iv(
4279 GLint location, GLsizei count, const GLint *value) {
[email protected]939e7362010-05-13 20:49:104280 if (!CheckCurrentProgramForUniform(location, "glUniform1iv")) {
[email protected]3916c97e2010-02-25 03:20:504281 return;
4282 }
[email protected]43c2f1f2011-03-25 18:35:364283 GLenum type = 0;
4284 if (!PrepForSetUniformByLocation(location, "glUniform1iv", &type, &count)) {
4285 return;
4286 }
[email protected]61eeb33f2011-07-26 15:30:314287 if (type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
4288 type == GL_SAMPLER_EXTERNAL_OES) {
[email protected]43c2f1f2011-03-25 18:35:364289 current_program_->SetSamplers(location, count, value);
4290 }
[email protected]3916c97e2010-02-25 03:20:504291 glUniform1iv(location, count, value);
4292}
4293
[email protected]939e7362010-05-13 20:49:104294void GLES2DecoderImpl::DoUniform1fv(
4295 GLint location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364296 GLenum type = 0;
4297 if (!PrepForSetUniformByLocation(location, "glUniform1fv", &type, &count)) {
[email protected]939e7362010-05-13 20:49:104298 return;
4299 }
4300 if (type == GL_BOOL) {
4301 scoped_array<GLint> temp(new GLint[count]);
4302 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]136a63e2010-11-12 22:01:534303 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:104304 }
4305 DoUniform1iv(location, count, temp.get());
4306 } else {
4307 glUniform1fv(location, count, value);
4308 }
4309}
4310
4311void GLES2DecoderImpl::DoUniform2fv(
4312 GLint location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364313 GLenum type = 0;
4314 if (!PrepForSetUniformByLocation(location, "glUniform2fv", &type, &count)) {
[email protected]939e7362010-05-13 20:49:104315 return;
4316 }
4317 if (type == GL_BOOL_VEC2) {
4318 GLsizei num_values = count * 2;
4319 scoped_array<GLint> temp(new GLint[num_values]);
4320 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:534321 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:104322 }
4323 glUniform2iv(location, count, temp.get());
4324 } else {
4325 glUniform2fv(location, count, value);
4326 }
4327}
4328
4329void GLES2DecoderImpl::DoUniform3fv(
4330 GLint location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364331 GLenum type = 0;
4332 if (!PrepForSetUniformByLocation(location, "glUniform3fv", &type, &count)) {
[email protected]939e7362010-05-13 20:49:104333 return;
4334 }
4335 if (type == GL_BOOL_VEC3) {
4336 GLsizei num_values = count * 3;
4337 scoped_array<GLint> temp(new GLint[num_values]);
4338 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:534339 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:104340 }
4341 glUniform3iv(location, count, temp.get());
4342 } else {
4343 glUniform3fv(location, count, value);
4344 }
4345}
4346
4347void GLES2DecoderImpl::DoUniform4fv(
4348 GLint location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364349 GLenum type = 0;
4350 if (!PrepForSetUniformByLocation(location, "glUniform4fv", &type, &count)) {
[email protected]939e7362010-05-13 20:49:104351 return;
4352 }
4353 if (type == GL_BOOL_VEC4) {
4354 GLsizei num_values = count * 4;
4355 scoped_array<GLint> temp(new GLint[num_values]);
4356 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:534357 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:104358 }
4359 glUniform4iv(location, count, temp.get());
4360 } else {
4361 glUniform4fv(location, count, value);
4362 }
4363}
4364
[email protected]43c2f1f2011-03-25 18:35:364365void GLES2DecoderImpl::DoUniform2iv(
4366 GLint location, GLsizei count, const GLint* value) {
4367 GLenum type = 0;
4368 if (!PrepForSetUniformByLocation(location, "glUniform2iv", &type, &count)) {
4369 return;
4370 }
4371 glUniform2iv(location, count, value);
4372}
4373
4374void GLES2DecoderImpl::DoUniform3iv(
4375 GLint location, GLsizei count, const GLint* value) {
4376 GLenum type = 0;
4377 if (!PrepForSetUniformByLocation(location, "glUniform3iv", &type, &count)) {
4378 return;
4379 }
4380 glUniform3iv(location, count, value);
4381}
4382
4383void GLES2DecoderImpl::DoUniform4iv(
4384 GLint location, GLsizei count, const GLint* value) {
4385 GLenum type = 0;
4386 if (!PrepForSetUniformByLocation(location, "glUniform4iv", &type, &count)) {
4387 return;
4388 }
4389 glUniform4iv(location, count, value);
4390}
4391
4392void GLES2DecoderImpl::DoUniformMatrix2fv(
4393 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
4394 GLenum type = 0;
4395 if (!PrepForSetUniformByLocation(
4396 location, "glUniformMatrix2fv", &type, &count)) {
4397 return;
4398 }
4399 glUniformMatrix2fv (location, count, transpose, value);
4400}
4401
4402void GLES2DecoderImpl::DoUniformMatrix3fv(
4403 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
4404 GLenum type = 0;
4405 if (!PrepForSetUniformByLocation(
4406 location, "glUniformMatrix3fv", &type, &count)) {
4407 return;
4408 }
4409 glUniformMatrix3fv (location, count, transpose, value);
4410}
4411
4412void GLES2DecoderImpl::DoUniformMatrix4fv(
4413 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
4414 GLenum type = 0;
4415 if (!PrepForSetUniformByLocation(
4416 location, "glUniformMatrix4fv", &type, &count)) {
4417 return;
4418 }
4419 glUniformMatrix4fv (location, count, transpose, value);
4420}
4421
[email protected]3916c97e2010-02-25 03:20:504422void GLES2DecoderImpl::DoUseProgram(GLuint program) {
[email protected]ae51d192010-04-27 00:48:034423 GLuint service_id = 0;
[email protected]3916c97e2010-02-25 03:20:504424 ProgramManager::ProgramInfo* info = NULL;
4425 if (program) {
[email protected]6b8cf1a2010-05-06 16:13:584426 info = GetProgramInfoNotShader(program, "glUseProgram");
[email protected]3916c97e2010-02-25 03:20:504427 if (!info) {
[email protected]ae51d192010-04-27 00:48:034428 return;
4429 }
4430 if (!info->IsValid()) {
[email protected]3916c97e2010-02-25 03:20:504431 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]8eee29c2010-04-29 03:38:294432 SetGLError(GL_INVALID_OPERATION, "glUseProgram: program not linked");
[email protected]3916c97e2010-02-25 03:20:504433 return;
4434 }
[email protected]ae51d192010-04-27 00:48:034435 service_id = info->service_id();
[email protected]3916c97e2010-02-25 03:20:504436 }
[email protected]ca488e12010-12-13 20:06:144437 if (current_program_) {
4438 program_manager()->UnuseProgram(shader_manager(), current_program_);
4439 }
[email protected]3916c97e2010-02-25 03:20:504440 current_program_ = info;
[email protected]ca488e12010-12-13 20:06:144441 if (current_program_) {
4442 program_manager()->UseProgram(current_program_);
4443 }
[email protected]ae51d192010-04-27 00:48:034444 glUseProgram(service_id);
[email protected]3916c97e2010-02-25 03:20:504445}
4446
[email protected]96449d2c2009-11-25 00:01:324447GLenum GLES2DecoderImpl::GetGLError() {
4448 // Check the GL error first, then our wrapped error.
4449 GLenum error = glGetError();
4450 if (error == GL_NO_ERROR && error_bits_ != 0) {
[email protected]03f882a2010-01-08 20:46:374451 for (uint32 mask = 1; mask != 0; mask = mask << 1) {
[email protected]96449d2c2009-11-25 00:01:324452 if ((error_bits_ & mask) != 0) {
[email protected]ddd968b82010-03-02 00:44:294453 error = GLES2Util::GLErrorBitToGLError(mask);
[email protected]96449d2c2009-11-25 00:01:324454 break;
4455 }
4456 }
4457 }
4458
4459 if (error != GL_NO_ERROR) {
4460 // There was an error, clear the corresponding wrapped error.
[email protected]ddd968b82010-03-02 00:44:294461 error_bits_ &= ~GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:324462 }
4463 return error;
4464}
4465
[email protected]1002c2d2011-06-28 22:39:044466GLenum GLES2DecoderImpl::PeekGLError() {
4467 GLenum error = glGetError();
4468 if (error != GL_NO_ERROR) {
4469 SetGLError(error, "");
4470 }
4471 return error;
4472}
4473
[email protected]8eee29c2010-04-29 03:38:294474void GLES2DecoderImpl::SetGLError(GLenum error, const char* msg) {
4475 if (msg) {
4476 last_error_ = msg;
[email protected]d0498742010-09-20 20:27:014477 LOG(ERROR) << last_error_;
[email protected]8eee29c2010-04-29 03:38:294478 }
[email protected]ddd968b82010-03-02 00:44:294479 error_bits_ |= GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:324480}
4481
[email protected]07f54fcc2009-12-22 02:46:304482void GLES2DecoderImpl::CopyRealGLErrorsToWrapper() {
4483 GLenum error;
4484 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]8eee29c2010-04-29 03:38:294485 SetGLError(error, NULL);
[email protected]07f54fcc2009-12-22 02:46:304486 }
4487}
4488
[email protected]6217d392010-03-25 22:08:354489void GLES2DecoderImpl::ClearRealGLErrors() {
4490 GLenum error;
4491 while ((error = glGetError()) != GL_NO_ERROR) {
4492 NOTREACHED() << "GL error " << error << " was unhandled.";
4493 }
4494}
4495
[email protected]ef526492010-06-02 23:12:254496bool GLES2DecoderImpl::SetBlackTextureForNonRenderableTextures() {
[email protected]3916c97e2010-02-25 03:20:504497 DCHECK(current_program_);
[email protected]ef526492010-06-02 23:12:254498 // Only check if there are some unrenderable textures.
4499 if (!texture_manager()->HaveUnrenderableTextures()) {
4500 return false;
4501 }
4502 bool textures_set = false;
[email protected]3916c97e2010-02-25 03:20:504503 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
4504 current_program_->sampler_indices();
4505 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
4506 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
4507 current_program_->GetUniformInfo(sampler_indices[ii]);
4508 DCHECK(uniform_info);
4509 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
4510 GLuint texture_unit_index = uniform_info->texture_units[jj];
4511 if (texture_unit_index < group_->max_texture_units()) {
4512 TextureUnit& texture_unit = texture_units_[texture_unit_index];
4513 TextureManager::TextureInfo* texture_info =
[email protected]61eeb33f2011-07-26 15:30:314514 texture_unit.GetInfoForSamplerType(uniform_info->type);
[email protected]915a59a12010-09-30 21:29:114515 if (!texture_info || !texture_info->CanRender(feature_info_)) {
[email protected]ef526492010-06-02 23:12:254516 textures_set = true;
[email protected]3916c97e2010-02-25 03:20:504517 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
4518 glBindTexture(
[email protected]61eeb33f2011-07-26 15:30:314519 GetBindTargetForSamplerType(uniform_info->type),
[email protected]00f893d2010-08-24 18:55:494520 texture_manager()->black_texture_id(uniform_info->type));
[email protected]3916c97e2010-02-25 03:20:504521 }
4522 }
4523 // else: should this be an error?
4524 }
4525 }
[email protected]ef526492010-06-02 23:12:254526 return textures_set;
[email protected]3916c97e2010-02-25 03:20:504527}
4528
4529void GLES2DecoderImpl::RestoreStateForNonRenderableTextures() {
4530 DCHECK(current_program_);
[email protected]3916c97e2010-02-25 03:20:504531 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
4532 current_program_->sampler_indices();
4533 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
4534 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
4535 current_program_->GetUniformInfo(sampler_indices[ii]);
4536 DCHECK(uniform_info);
4537 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
4538 GLuint texture_unit_index = uniform_info->texture_units[jj];
4539 if (texture_unit_index < group_->max_texture_units()) {
4540 TextureUnit& texture_unit = texture_units_[texture_unit_index];
4541 TextureManager::TextureInfo* texture_info =
4542 uniform_info->type == GL_SAMPLER_2D ?
4543 texture_unit.bound_texture_2d :
4544 texture_unit.bound_texture_cube_map;
[email protected]915a59a12010-09-30 21:29:114545 if (!texture_info || !texture_info->CanRender(feature_info_)) {
[email protected]3916c97e2010-02-25 03:20:504546 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
4547 // Get the texture info that was previously bound here.
4548 texture_info = texture_unit.bind_target == GL_TEXTURE_2D ?
4549 texture_unit.bound_texture_2d :
4550 texture_unit.bound_texture_cube_map;
4551 glBindTexture(texture_unit.bind_target,
[email protected]ae51d192010-04-27 00:48:034552 texture_info ? texture_info->service_id() : 0);
[email protected]3916c97e2010-02-25 03:20:504553 }
4554 }
4555 }
4556 }
4557 // Set the active texture back to whatever the user had it as.
4558 glActiveTexture(GL_TEXTURE0 + active_texture_unit_);
[email protected]07f54fcc2009-12-22 02:46:304559}
4560
[email protected]0d6bfdc2011-11-02 01:32:204561bool GLES2DecoderImpl::ClearUnclearedTextures() {
4562 // Only check if there are some uncleared textures.
4563 if (!texture_manager()->HaveUnsafeTextures()) {
4564 return true;
4565 }
4566
4567 // 1: Check all textures we are about to render with.
4568 if (current_program_) {
4569 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
4570 current_program_->sampler_indices();
4571 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
4572 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
4573 current_program_->GetUniformInfo(sampler_indices[ii]);
4574 DCHECK(uniform_info);
4575 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
4576 GLuint texture_unit_index = uniform_info->texture_units[jj];
4577 if (texture_unit_index < group_->max_texture_units()) {
4578 TextureUnit& texture_unit = texture_units_[texture_unit_index];
4579 TextureManager::TextureInfo* texture_info =
4580 texture_unit.GetInfoForSamplerType(uniform_info->type);
4581 if (texture_info && !texture_info->SafeToRenderFrom()) {
4582 if (!texture_manager()->ClearRenderableLevels(this, texture_info)) {
4583 return false;
4584 }
4585 }
4586 }
4587 }
4588 }
4589 }
4590 return true;
4591}
4592
[email protected]07f54fcc2009-12-22 02:46:304593bool GLES2DecoderImpl::IsDrawValid(GLuint max_vertex_accessed) {
[email protected]689fa1c52010-06-09 18:35:034594 // NOTE: We specifically do not check current_program->IsValid() because
4595 // it could never be invalid since glUseProgram would have failed. While
4596 // glLinkProgram could later mark the program as invalid the previous
4597 // valid program will still function if it is still the current program.
[email protected]ca488e12010-12-13 20:06:144598 if (!current_program_) {
[email protected]3916c97e2010-02-25 03:20:504599 // The program does not exist.
4600 // But GL says no ERROR.
4601 return false;
4602 }
[email protected]f39f4b3f2010-05-12 17:04:084603 // Validate all attribs currently enabled. If they are used by the current
4604 // program then check that they have enough elements to handle the draw call.
4605 // If they are not used by the current program check that they have a buffer
4606 // assigned.
4607 const VertexAttribManager::VertexAttribInfoList& infos =
4608 vertex_attrib_manager_.GetEnabledVertexAttribInfos();
4609 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
[email protected]8fbedc02010-11-18 18:43:404610 infos.begin(); it != infos.end(); ++it) {
[email protected]f39f4b3f2010-05-12 17:04:084611 const VertexAttribManager::VertexAttribInfo* info = *it;
4612 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
4613 current_program_->GetAttribInfoByLocation(info->index());
4614 if (attrib_info) {
4615 // This attrib is used in the current program.
4616 if (!info->CanAccess(max_vertex_accessed)) {
4617 SetGLError(GL_INVALID_OPERATION,
4618 "glDrawXXX: attempt to access out of range vertices");
4619 return false;
4620 }
4621 } else {
4622 // This attrib is not used in the current program.
[email protected]a0b78dc2011-11-11 10:43:104623 if (!info->buffer()) {
[email protected]f39f4b3f2010-05-12 17:04:084624 SetGLError(
4625 GL_INVALID_OPERATION,
4626 "glDrawXXX: attempt to render with no buffer attached to enabled "
4627 "attrib");
4628 return false;
4629 }
[email protected]1d32bc82010-01-13 22:06:464630 }
[email protected]07f54fcc2009-12-22 02:46:304631 }
[email protected]3916c97e2010-02-25 03:20:504632 return true;
[email protected]b1122982010-05-17 23:04:244633}
4634
[email protected]c13e1da62011-09-09 21:48:304635bool GLES2DecoderImpl::SimulateAttrib0(
4636 GLuint max_vertex_accessed, bool* simulated) {
4637 DCHECK(simulated);
4638 *simulated = false;
4639
[email protected]876f6fee2010-08-02 23:10:324640 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
[email protected]c13e1da62011-09-09 21:48:304641 return true;
[email protected]876f6fee2010-08-02 23:10:324642
[email protected]b1122982010-05-17 23:04:244643 const VertexAttribManager::VertexAttribInfo* info =
4644 vertex_attrib_manager_.GetVertexAttribInfo(0);
4645 // If it's enabled or it's not used then we don't need to do anything.
[email protected]fc753442011-02-04 19:49:494646 bool attrib_0_used = current_program_->GetAttribInfoByLocation(0) != NULL;
4647 if (info->enabled() && attrib_0_used) {
[email protected]c13e1da62011-09-09 21:48:304648 return true;
[email protected]b1122982010-05-17 23:04:244649 }
4650
[email protected]b1122982010-05-17 23:04:244651 // Make a buffer with a single repeated vec4 value enough to
4652 // simulate the constant value that is supposed to be here.
4653 // This is required to emulate GLES2 on GL.
[email protected]c13e1da62011-09-09 21:48:304654 typedef VertexAttribManager::VertexAttribInfo::Vec4 Vec4;
4655
4656 GLuint num_vertices = max_vertex_accessed + 1;
4657 GLuint size_needed = 0;
4658
4659 if (num_vertices == 0 ||
4660 !SafeMultiply(num_vertices, static_cast<GLuint>(sizeof(Vec4)),
4661 &size_needed) ||
4662 size_needed > 0x7FFFFFFFU) {
4663 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: Simulating attrib 0");
4664 return false;
4665 }
4666
4667 CopyRealGLErrorsToWrapper();
4668 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
4669
4670 if (static_cast<GLsizei>(size_needed) > attrib_0_size_) {
[email protected]fc753442011-02-04 19:49:494671 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
[email protected]c13e1da62011-09-09 21:48:304672 GLenum error = glGetError();
4673 if (error != GL_NO_ERROR) {
4674 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: Simulating attrib 0");
4675 return false;
4676 }
[email protected]fc753442011-02-04 19:49:494677 attrib_0_buffer_matches_value_ = false;
4678 }
4679 if (attrib_0_used &&
4680 (!attrib_0_buffer_matches_value_ ||
4681 (info->value().v[0] != attrib_0_value_.v[0] ||
4682 info->value().v[1] != attrib_0_value_.v[1] ||
4683 info->value().v[2] != attrib_0_value_.v[2] ||
4684 info->value().v[3] != attrib_0_value_.v[3]))) {
4685 std::vector<Vec4> temp(num_vertices, info->value());
4686 glBufferSubData(GL_ARRAY_BUFFER, 0, size_needed, &temp[0].v[0]);
4687 attrib_0_buffer_matches_value_ = true;
[email protected]b1122982010-05-17 23:04:244688 attrib_0_value_ = info->value();
4689 attrib_0_size_ = size_needed;
4690 }
4691
4692 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
4693
[email protected]c13e1da62011-09-09 21:48:304694 *simulated = true;
[email protected]b1122982010-05-17 23:04:244695 return true;
[email protected]b1122982010-05-17 23:04:244696}
4697
4698void GLES2DecoderImpl::RestoreStateForSimulatedAttrib0() {
4699 const VertexAttribManager::VertexAttribInfo* info =
4700 vertex_attrib_manager_.GetVertexAttribInfo(0);
4701 const void* ptr = reinterpret_cast<const void*>(info->offset());
4702 BufferManager::BufferInfo* buffer_info = info->buffer();
4703 glBindBuffer(GL_ARRAY_BUFFER, buffer_info ? buffer_info->service_id() : 0);
4704 glVertexAttribPointer(
4705 0, info->size(), info->type(), info->normalized(), info->gl_stride(),
4706 ptr);
4707 glBindBuffer(GL_ARRAY_BUFFER,
4708 bound_array_buffer_ ? bound_array_buffer_->service_id() : 0);
4709}
[email protected]07f54fcc2009-12-22 02:46:304710
[email protected]8fbedc02010-11-18 18:43:404711bool GLES2DecoderImpl::SimulateFixedAttribs(
4712 GLuint max_vertex_accessed, bool* simulated) {
4713 DCHECK(simulated);
4714 *simulated = false;
4715 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
4716 return true;
4717
4718 if (!vertex_attrib_manager_.HaveFixedAttribs()) {
4719 return true;
4720 }
4721
4722 // NOTE: we could be smart and try to check if a buffer is used
4723 // twice in 2 different attribs, find the overlapping parts and therefore
4724 // duplicate the minimum amount of data but this whole code path is not meant
4725 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
4726 // tests so we just add to the buffer attrib used.
4727
4728 // Compute the number of elements needed.
[email protected]c13e1da62011-09-09 21:48:304729 GLuint num_vertices = max_vertex_accessed + 1;
4730 if (num_vertices == 0) {
4731 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: Simulating attrib 0");
4732 return false;
4733 }
4734
4735 GLuint elements_needed = 0;
[email protected]8fbedc02010-11-18 18:43:404736 const VertexAttribManager::VertexAttribInfoList& infos =
4737 vertex_attrib_manager_.GetEnabledVertexAttribInfos();
4738 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
4739 infos.begin(); it != infos.end(); ++it) {
4740 const VertexAttribManager::VertexAttribInfo* info = *it;
4741 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
4742 current_program_->GetAttribInfoByLocation(info->index());
4743 if (attrib_info &&
4744 info->CanAccess(max_vertex_accessed) &&
4745 info->type() == GL_FIXED) {
[email protected]c13e1da62011-09-09 21:48:304746 GLuint elements_used = 0;
4747 if (!SafeMultiply(num_vertices,
4748 static_cast<GLuint>(info->size()), &elements_used) ||
[email protected]8fbedc02010-11-18 18:43:404749 !SafeAdd(elements_needed, elements_used, &elements_needed)) {
4750 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: simulating GL_FIXED attribs");
4751 return false;
4752 }
4753 }
4754 }
4755
[email protected]c13e1da62011-09-09 21:48:304756 const GLuint kSizeOfFloat = sizeof(float); // NOLINT
4757 GLuint size_needed = 0;
4758 if (!SafeMultiply(elements_needed, kSizeOfFloat, &size_needed) ||
4759 size_needed > 0x7FFFFFFFU) {
[email protected]8fbedc02010-11-18 18:43:404760 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: simulating GL_FIXED attribs");
4761 return false;
4762 }
4763
[email protected]c13e1da62011-09-09 21:48:304764 CopyRealGLErrorsToWrapper();
[email protected]8fbedc02010-11-18 18:43:404765
4766 glBindBuffer(GL_ARRAY_BUFFER, fixed_attrib_buffer_id_);
[email protected]c13e1da62011-09-09 21:48:304767 if (static_cast<GLsizei>(size_needed) > fixed_attrib_buffer_size_) {
[email protected]8fbedc02010-11-18 18:43:404768 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
[email protected]c13e1da62011-09-09 21:48:304769 GLenum error = glGetError();
4770 if (error != GL_NO_ERROR) {
4771 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: simulating GL_FIXED attribs");
4772 return false;
4773 }
[email protected]8fbedc02010-11-18 18:43:404774 }
4775
4776 // Copy the elements and convert to float
4777 GLintptr offset = 0;
4778 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
4779 infos.begin(); it != infos.end(); ++it) {
4780 const VertexAttribManager::VertexAttribInfo* info = *it;
4781 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
4782 current_program_->GetAttribInfoByLocation(info->index());
4783 if (attrib_info &&
4784 info->CanAccess(max_vertex_accessed) &&
4785 info->type() == GL_FIXED) {
4786 int num_elements = info->size() * kSizeOfFloat;
4787 int size = num_elements * num_vertices;
4788 scoped_array<float> data(new float[size]);
4789 const int32* src = reinterpret_cast<const int32 *>(
4790 info->buffer()->GetRange(info->offset(), size));
4791 const int32* end = src + num_elements;
4792 float* dst = data.get();
4793 while (src != end) {
4794 *dst++ = static_cast<float>(*src++) / 65536.0f;
4795 }
4796 glBufferSubData(GL_ARRAY_BUFFER, offset, size, data.get());
4797 glVertexAttribPointer(
4798 info->index(), info->size(), GL_FLOAT, false, 0,
4799 reinterpret_cast<GLvoid*>(offset));
4800 offset += size;
4801 }
4802 }
4803 *simulated = true;
4804 return true;
4805}
4806
4807void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
4808 // There's no need to call glVertexAttribPointer because we shadow all the
4809 // settings and passing GL_FIXED to it will not work.
4810 glBindBuffer(GL_ARRAY_BUFFER,
4811 bound_array_buffer_ ? bound_array_buffer_->service_id() : 0);
4812}
4813
[email protected]38d139d2011-07-14 00:38:434814error::Error GLES2DecoderImpl::HandleDrawArrays(
4815 uint32 immediate_data_size, const gles2::DrawArrays& c) {
4816 GLenum mode = static_cast<GLenum>(c.mode);
4817 GLint first = static_cast<GLint>(c.first);
4818 GLsizei count = static_cast<GLsizei>(c.count);
4819 if (!validators_->draw_mode.IsValid(mode)) {
4820 SetGLError(GL_INVALID_ENUM, "glDrawArrays: mode GL_INVALID_ENUM");
4821 return error::kNoError;
4822 }
4823 if (count < 0) {
4824 SetGLError(GL_INVALID_VALUE, "glDrawArrays: count < 0");
4825 return error::kNoError;
4826 }
[email protected]0d6bfdc2011-11-02 01:32:204827 if (!CheckBoundFramebuffersValid("glDrawArrays")) {
[email protected]38d139d2011-07-14 00:38:434828 return error::kNoError;
4829 }
4830 // We have to check this here because the prototype for glDrawArrays
4831 // is GLint not GLsizei.
4832 if (first < 0) {
4833 SetGLError(GL_INVALID_VALUE, "glDrawArrays: first < 0");
4834 return error::kNoError;
4835 }
4836
4837 if (count == 0) {
4838 return error::kNoError;
4839 }
4840
4841 GLuint max_vertex_accessed = first + count - 1;
4842 if (IsDrawValid(max_vertex_accessed)) {
[email protected]0d6bfdc2011-11-02 01:32:204843 if (!ClearUnclearedTextures()) {
4844 SetGLError(GL_INVALID_VALUE, "glDrawArrays: out of memory");
4845 return error::kNoError;
4846 }
[email protected]c13e1da62011-09-09 21:48:304847 bool simulated_attrib_0 = false;
4848 if (!SimulateAttrib0(max_vertex_accessed, &simulated_attrib_0)) {
4849 return error::kNoError;
4850 }
[email protected]38d139d2011-07-14 00:38:434851 bool simulated_fixed_attribs = false;
4852 if (SimulateFixedAttribs(max_vertex_accessed, &simulated_fixed_attribs)) {
4853 bool textures_set = SetBlackTextureForNonRenderableTextures();
4854 ApplyDirtyState();
4855 glDrawArrays(mode, first, count);
4856 if (textures_set) {
4857 RestoreStateForNonRenderableTextures();
4858 }
4859 if (simulated_fixed_attribs) {
4860 RestoreStateForSimulatedFixedAttribs();
4861 }
4862 }
4863 if (simulated_attrib_0) {
4864 RestoreStateForSimulatedAttrib0();
4865 }
4866 if (WasContextLost()) {
4867 LOG(ERROR) << " GLES2DecoderImpl: Context lost during DrawArrays.";
4868 return error::kLostContext;
4869 }
4870 }
4871 return error::kNoError;
4872}
4873
[email protected]f7a64ee2010-02-01 22:24:144874error::Error GLES2DecoderImpl::HandleDrawElements(
[email protected]b9849abf2009-11-25 19:13:194875 uint32 immediate_data_size, const gles2::DrawElements& c) {
[email protected]a0b78dc2011-11-11 10:43:104876 if (!bound_element_array_buffer_) {
[email protected]8eee29c2010-04-29 03:38:294877 SetGLError(GL_INVALID_OPERATION,
4878 "glDrawElements: No element array buffer bound");
4879 return error::kNoError;
4880 }
4881
4882 GLenum mode = c.mode;
4883 GLsizei count = c.count;
4884 GLenum type = c.type;
4885 int32 offset = c.index_offset;
4886 if (count < 0) {
4887 SetGLError(GL_INVALID_VALUE, "glDrawElements: count < 0");
4888 return error::kNoError;
4889 }
4890 if (offset < 0) {
4891 SetGLError(GL_INVALID_VALUE, "glDrawElements: offset < 0");
4892 return error::kNoError;
4893 }
[email protected]9438b012010-06-15 22:55:054894 if (!validators_->draw_mode.IsValid(mode)) {
[email protected]8eee29c2010-04-29 03:38:294895 SetGLError(GL_INVALID_ENUM, "glDrawElements: mode GL_INVALID_ENUM");
4896 return error::kNoError;
4897 }
[email protected]9438b012010-06-15 22:55:054898 if (!validators_->index_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:294899 SetGLError(GL_INVALID_ENUM, "glDrawElements: type GL_INVALID_ENUM");
4900 return error::kNoError;
4901 }
4902
[email protected]0d6bfdc2011-11-02 01:32:204903 if (!CheckBoundFramebuffersValid("glDrawElements")) {
[email protected]3a03a8f2011-03-19 00:51:274904 return error::kNoError;
4905 }
4906
[email protected]6c788fb72010-08-26 02:16:314907 if (count == 0) {
4908 return error::kNoError;
4909 }
4910
[email protected]8eee29c2010-04-29 03:38:294911 GLuint max_vertex_accessed;
4912 if (!bound_element_array_buffer_->GetMaxValueForRange(
4913 offset, count, type, &max_vertex_accessed)) {
4914 SetGLError(GL_INVALID_OPERATION,
4915 "glDrawElements: range out of bounds for buffer");
4916 return error::kNoError;
4917 }
4918
4919 if (IsDrawValid(max_vertex_accessed)) {
[email protected]0d6bfdc2011-11-02 01:32:204920 if (!ClearUnclearedTextures()) {
4921 SetGLError(GL_INVALID_VALUE, "glDrawElements: out of memory");
4922 return error::kNoError;
4923 }
[email protected]c13e1da62011-09-09 21:48:304924 bool simulated_attrib_0 = false;
4925 if (!SimulateAttrib0(max_vertex_accessed, &simulated_attrib_0)) {
4926 return error::kNoError;
4927 }
[email protected]8fbedc02010-11-18 18:43:404928 bool simulated_fixed_attribs = false;
4929 if (SimulateFixedAttribs(max_vertex_accessed, &simulated_fixed_attribs)) {
4930 bool textures_set = SetBlackTextureForNonRenderableTextures();
[email protected]297ca1c2011-06-20 23:08:464931 ApplyDirtyState();
[email protected]8fbedc02010-11-18 18:43:404932 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
4933 glDrawElements(mode, count, type, indices);
4934 if (textures_set) {
4935 RestoreStateForNonRenderableTextures();
4936 }
4937 if (simulated_fixed_attribs) {
4938 RestoreStateForSimulatedFixedAttribs();
4939 }
[email protected]ba3176a2009-12-16 18:19:464940 }
[email protected]b1122982010-05-17 23:04:244941 if (simulated_attrib_0) {
4942 RestoreStateForSimulatedAttrib0();
4943 }
[email protected]38d139d2011-07-14 00:38:434944 if (WasContextLost()) {
4945 LOG(ERROR) << " GLES2DecoderImpl: Context lost during DrawElements.";
4946 return error::kLostContext;
4947 }
[email protected]96449d2c2009-11-25 00:01:324948 }
[email protected]f7a64ee2010-02-01 22:24:144949 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324950}
4951
[email protected]269200b12010-11-18 22:53:064952GLuint GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
[email protected]29a9eb52010-04-13 09:04:234953 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
4954 GLuint max_vertex_accessed = 0;
4955 BufferManager::BufferInfo* info = GetBufferInfo(buffer_id);
[email protected]8eee29c2010-04-29 03:38:294956 if (!info) {
[email protected]ae51d192010-04-27 00:48:034957 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]8eee29c2010-04-29 03:38:294958 SetGLError(GL_INVALID_VALUE,
[email protected]269200b12010-11-18 22:53:064959 "GetMaxValueInBufferCHROMIUM: unknown buffer");
[email protected]29a9eb52010-04-13 09:04:234960 } else {
4961 if (!info->GetMaxValueForRange(offset, count, type, &max_vertex_accessed)) {
[email protected]ae51d192010-04-27 00:48:034962 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]269200b12010-11-18 22:53:064963 SetGLError(
4964 GL_INVALID_OPERATION,
4965 "GetMaxValueInBufferCHROMIUM: range out of bounds for buffer");
[email protected]29a9eb52010-04-13 09:04:234966 }
4967 }
4968 return max_vertex_accessed;
4969}
4970
[email protected]96449d2c2009-11-25 00:01:324971// Calls glShaderSource for the various versions of the ShaderSource command.
4972// Assumes that data / data_size points to a piece of memory that is in range
4973// of whatever context it came from (shared memory, immediate memory, bucket
4974// memory.)
[email protected]45bf5152010-02-12 00:11:314975error::Error GLES2DecoderImpl::ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:034976 GLuint client_id, const char* data, uint32 data_size) {
[email protected]258a3313f2011-10-18 20:13:574977 std::string str(data, data + data_size);
[email protected]6b8cf1a2010-05-06 16:13:584978 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
4979 client_id, "glShaderSource");
[email protected]45bf5152010-02-12 00:11:314980 if (!info) {
[email protected]45bf5152010-02-12 00:11:314981 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324982 }
[email protected]45bf5152010-02-12 00:11:314983 // Note: We don't actually call glShaderSource here. We wait until
4984 // the call to glCompileShader.
[email protected]258a3313f2011-10-18 20:13:574985 info->UpdateSource(str.c_str());
[email protected]f7a64ee2010-02-01 22:24:144986 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324987}
4988
[email protected]f7a64ee2010-02-01 22:24:144989error::Error GLES2DecoderImpl::HandleShaderSource(
[email protected]b9849abf2009-11-25 19:13:194990 uint32 immediate_data_size, const gles2::ShaderSource& c) {
[email protected]96449d2c2009-11-25 00:01:324991 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:314992 const char* data = GetSharedMemoryAs<const char*>(
[email protected]96449d2c2009-11-25 00:01:324993 c.data_shm_id, c.data_shm_offset, data_size);
[email protected]ba3176a2009-12-16 18:19:464994 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:144995 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:324996 }
[email protected]ae51d192010-04-27 00:48:034997 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]96449d2c2009-11-25 00:01:324998}
4999
[email protected]f7a64ee2010-02-01 22:24:145000error::Error GLES2DecoderImpl::HandleShaderSourceImmediate(
[email protected]b9849abf2009-11-25 19:13:195001 uint32 immediate_data_size, const gles2::ShaderSourceImmediate& c) {
[email protected]96449d2c2009-11-25 00:01:325002 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:315003 const char* data = GetImmediateDataAs<const char*>(
[email protected]07f54fcc2009-12-22 02:46:305004 c, data_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:465005 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:145006 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:325007 }
[email protected]ae51d192010-04-27 00:48:035008 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]45bf5152010-02-12 00:11:315009}
5010
[email protected]558847a2010-03-24 07:02:545011error::Error GLES2DecoderImpl::HandleShaderSourceBucket(
5012 uint32 immediate_data_size, const gles2::ShaderSourceBucket& c) {
[email protected]558847a2010-03-24 07:02:545013 Bucket* bucket = GetBucket(c.data_bucket_id);
5014 if (!bucket || bucket->size() == 0) {
5015 return error::kInvalidArguments;
5016 }
5017 return ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:035018 c.shader, bucket->GetDataAs<const char*>(0, bucket->size() - 1),
[email protected]558847a2010-03-24 07:02:545019 bucket->size() - 1);
5020}
5021
[email protected]ae51d192010-04-27 00:48:035022void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
[email protected]0c8fabf2011-06-14 19:35:225023 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
[email protected]6b8cf1a2010-05-06 16:13:585024 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5025 client_id, "glCompileShader");
[email protected]45bf5152010-02-12 00:11:315026 if (!info) {
[email protected]45bf5152010-02-12 00:11:315027 return;
5028 }
[email protected]de17df392010-04-23 21:09:415029 // Translate GL ES 2.0 shader to Desktop GL shader and pass that to
5030 // glShaderSource and then glCompileShader.
[email protected]df6cf1ad2011-01-29 01:20:525031 const char* shader_src = info->source() ? info->source()->c_str() : "";
[email protected]f57bb282010-11-12 00:51:345032 ShaderTranslator* translator = NULL;
[email protected]b1d2dcb2010-05-17 19:24:185033 if (use_shader_translator_) {
[email protected]f57bb282010-11-12 00:51:345034 translator = info->shader_type() == GL_VERTEX_SHADER ?
[email protected]a550584e2010-09-17 18:01:455035 vertex_translator_.get() : fragment_translator_.get();
[email protected]5236b752010-07-27 18:02:235036
[email protected]a550584e2010-09-17 18:01:455037 if (!translator->Translate(shader_src)) {
[email protected]f57bb282010-11-12 00:51:345038 info->SetStatus(false, translator->info_log(), NULL);
[email protected]b1d2dcb2010-05-17 19:24:185039 return;
5040 }
[email protected]a550584e2010-09-17 18:01:455041 shader_src = translator->translated_shader();
[email protected]93297702011-11-05 05:09:465042 if (!feature_info_->feature_flags().angle_translated_shader_source)
[email protected]d6a53e42011-10-05 00:09:365043 info->UpdateTranslatedSource(shader_src);
[email protected]de17df392010-04-23 21:09:415044 }
[email protected]de17df392010-04-23 21:09:415045
[email protected]ae51d192010-04-27 00:48:035046 glShaderSource(info->service_id(), 1, &shader_src, NULL);
5047 glCompileShader(info->service_id());
[email protected]93297702011-11-05 05:09:465048 if (feature_info_->feature_flags().angle_translated_shader_source) {
[email protected]d6a53e42011-10-05 00:09:365049 GLint max_len = 0;
5050 glGetShaderiv(info->service_id(),
5051 GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE,
5052 &max_len);
5053 scoped_array<char> temp(new char[max_len]);
5054 GLint len = 0;
5055 glGetTranslatedShaderSourceANGLE(
5056 info->service_id(), max_len, &len, temp.get());
5057 DCHECK(max_len == 0 || len < max_len);
5058 DCHECK(len == 0 || temp[len] == '\0');
5059 info->UpdateTranslatedSource(temp.get());
5060 }
5061
[email protected]e5186162010-06-14 18:54:415062 GLint status = GL_FALSE;
5063 glGetShaderiv(info->service_id(), GL_COMPILE_STATUS, &status);
5064 if (status) {
[email protected]f57bb282010-11-12 00:51:345065 info->SetStatus(true, "", translator);
[email protected]e5186162010-06-14 18:54:415066 } else {
[email protected]d9977d42010-09-01 20:27:025067 // We cannot reach here if we are using the shader translator.
5068 // All invalid shaders must be rejected by the translator.
5069 // All translated shaders must compile.
5070 LOG_IF(ERROR, use_shader_translator_)
5071 << "Shader translator allowed/produced an invalid shader.";
[email protected]1fd26d82010-11-04 16:06:335072 GLint max_len = 0;
5073 glGetShaderiv(info->service_id(), GL_INFO_LOG_LENGTH, &max_len);
5074 scoped_array<char> temp(new char[max_len]);
[email protected]e5186162010-06-14 18:54:415075 GLint len = 0;
[email protected]1fd26d82010-11-04 16:06:335076 glGetShaderInfoLog(info->service_id(), max_len, &len, temp.get());
5077 DCHECK(max_len == 0 || len < max_len);
[email protected]d6a53e42011-10-05 00:09:365078 DCHECK(len == 0 || temp[len] == '\0');
[email protected]df6cf1ad2011-01-29 01:20:525079 info->SetStatus(false, std::string(temp.get(), len).c_str(), NULL);
[email protected]e5186162010-06-14 18:54:415080 }
[email protected]45bf5152010-02-12 00:11:315081};
5082
[email protected]ddd968b82010-03-02 00:44:295083void GLES2DecoderImpl::DoGetShaderiv(
5084 GLuint shader, GLenum pname, GLint* params) {
[email protected]6b8cf1a2010-05-06 16:13:585085 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5086 shader, "glGetShaderiv");
[email protected]ddd968b82010-03-02 00:44:295087 if (!info) {
[email protected]ddd968b82010-03-02 00:44:295088 return;
5089 }
[email protected]8f1ccdac2010-05-19 21:01:485090 switch (pname) {
5091 case GL_SHADER_SOURCE_LENGTH:
[email protected]df6cf1ad2011-01-29 01:20:525092 *params = info->source() ? info->source()->size() + 1 : 0;
[email protected]8f1ccdac2010-05-19 21:01:485093 return;
5094 case GL_COMPILE_STATUS:
[email protected]e5186162010-06-14 18:54:415095 *params = info->IsValid();
5096 return;
[email protected]8f1ccdac2010-05-19 21:01:485097 case GL_INFO_LOG_LENGTH:
[email protected]df6cf1ad2011-01-29 01:20:525098 *params = info->log_info() ? info->log_info()->size() + 1 : 0;
[email protected]e5186162010-06-14 18:54:415099 return;
[email protected]d6a53e42011-10-05 00:09:365100 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5101 *params = info->translated_source() ?
5102 info->translated_source()->size() + 1 : 0;
5103 return;
[email protected]8f1ccdac2010-05-19 21:01:485104 default:
5105 break;
[email protected]ddd968b82010-03-02 00:44:295106 }
[email protected]8f1ccdac2010-05-19 21:01:485107 glGetShaderiv(info->service_id(), pname, params);
[email protected]ddd968b82010-03-02 00:44:295108}
5109
[email protected]ae51d192010-04-27 00:48:035110error::Error GLES2DecoderImpl::HandleGetShaderSource(
5111 uint32 immediate_data_size, const gles2::GetShaderSource& c) {
5112 GLuint shader = c.shader;
[email protected]ae51d192010-04-27 00:48:035113 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
5114 Bucket* bucket = CreateBucket(bucket_id);
[email protected]6b8cf1a2010-05-06 16:13:585115 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5116 shader, "glGetShaderSource");
[email protected]df6cf1ad2011-01-29 01:20:525117 if (!info || !info->source()) {
[email protected]8eee29c2010-04-29 03:38:295118 bucket->SetSize(0);
[email protected]8eee29c2010-04-29 03:38:295119 return error::kNoError;
5120 }
[email protected]df6cf1ad2011-01-29 01:20:525121 bucket->SetFromString(info->source()->c_str());
[email protected]ae51d192010-04-27 00:48:035122 return error::kNoError;
5123}
5124
[email protected]d6a53e42011-10-05 00:09:365125error::Error GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
5126 uint32 immediate_data_size,
5127 const gles2::GetTranslatedShaderSourceANGLE& c) {
5128 GLuint shader = c.shader;
5129
5130 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
5131 Bucket* bucket = CreateBucket(bucket_id);
5132 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5133 shader, "glTranslatedGetShaderSourceANGLE");
5134 if (!info) {
5135 bucket->SetSize(0);
5136 return error::kNoError;
5137 }
5138
5139 bucket->SetFromString(info->translated_source() ?
5140 info->translated_source()->c_str() : NULL);
5141 return error::kNoError;
5142}
5143
[email protected]ae51d192010-04-27 00:48:035144error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
5145 uint32 immediate_data_size, const gles2::GetProgramInfoLog& c) {
5146 GLuint program = c.program;
[email protected]6b8cf1a2010-05-06 16:13:585147 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
5148 Bucket* bucket = CreateBucket(bucket_id);
5149 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
5150 program, "glGetProgramInfoLog");
[email protected]df6cf1ad2011-01-29 01:20:525151 if (!info || !info->log_info()) {
[email protected]9a14ae612011-08-08 17:51:465152 bucket->SetFromString("");
[email protected]ae51d192010-04-27 00:48:035153 return error::kNoError;
[email protected]45bf5152010-02-12 00:11:315154 }
[email protected]df6cf1ad2011-01-29 01:20:525155 bucket->SetFromString(info->log_info()->c_str());
[email protected]ae51d192010-04-27 00:48:035156 return error::kNoError;
5157}
5158
5159error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
5160 uint32 immediate_data_size, const gles2::GetShaderInfoLog& c) {
5161 GLuint shader = c.shader;
[email protected]6b8cf1a2010-05-06 16:13:585162 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
5163 Bucket* bucket = CreateBucket(bucket_id);
5164 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5165 shader, "glGetShaderInfoLog");
[email protected]df6cf1ad2011-01-29 01:20:525166 if (!info || !info->log_info()) {
[email protected]9a14ae612011-08-08 17:51:465167 bucket->SetFromString("");
[email protected]ae51d192010-04-27 00:48:035168 return error::kNoError;
5169 }
[email protected]df6cf1ad2011-01-29 01:20:525170 bucket->SetFromString(info->log_info()->c_str());
[email protected]ae51d192010-04-27 00:48:035171 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325172}
5173
[email protected]1958e0e2010-04-22 05:17:155174bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
[email protected]a0b78dc2011-11-11 10:43:105175 const BufferManager::BufferInfo* buffer = GetBufferInfo(client_id);
5176 return buffer && buffer->IsValid() && !buffer->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155177}
5178
5179bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
[email protected]a0b78dc2011-11-11 10:43:105180 const FramebufferManager::FramebufferInfo* framebuffer =
[email protected]06c8b082011-01-05 18:00:365181 GetFramebufferInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:105182 return framebuffer && framebuffer->IsValid() && !framebuffer->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155183}
5184
5185bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:365186 // IsProgram is true for programs as soon as they are created, until they are
5187 // deleted and no longer in use.
[email protected]a0b78dc2011-11-11 10:43:105188 const ProgramManager::ProgramInfo* program = GetProgramInfo(client_id);
5189 return program != NULL && !program->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155190}
5191
5192bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
[email protected]a0b78dc2011-11-11 10:43:105193 const RenderbufferManager::RenderbufferInfo* renderbuffer =
[email protected]06c8b082011-01-05 18:00:365194 GetRenderbufferInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:105195 return renderbuffer && renderbuffer->IsValid() && !renderbuffer->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155196}
5197
5198bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:365199 // IsShader is true for shaders as soon as they are created, until they
5200 // are deleted and not attached to any programs.
[email protected]a0b78dc2011-11-11 10:43:105201 const ShaderManager::ShaderInfo* shader = GetShaderInfo(client_id);
5202 return shader != NULL && !shader->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155203}
5204
5205bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
[email protected]a0b78dc2011-11-11 10:43:105206 const TextureManager::TextureInfo* texture = GetTextureInfo(client_id);
5207 return texture && texture->IsValid() && !texture->IsDeleted();
[email protected]ae51d192010-04-27 00:48:035208}
5209
5210void GLES2DecoderImpl::DoAttachShader(
5211 GLuint program_client_id, GLint shader_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:585212 ProgramManager::ProgramInfo* program_info = GetProgramInfoNotShader(
5213 program_client_id, "glAttachShader");
[email protected]ae51d192010-04-27 00:48:035214 if (!program_info) {
[email protected]ae51d192010-04-27 00:48:035215 return;
[email protected]1958e0e2010-04-22 05:17:155216 }
[email protected]6b8cf1a2010-05-06 16:13:585217 ShaderManager::ShaderInfo* shader_info = GetShaderInfoNotProgram(
5218 shader_client_id, "glAttachShader");
[email protected]ae51d192010-04-27 00:48:035219 if (!shader_info) {
[email protected]ae51d192010-04-27 00:48:035220 return;
5221 }
[email protected]ca488e12010-12-13 20:06:145222 if (!program_info->AttachShader(shader_manager(), shader_info)) {
[email protected]fb96c8e2010-08-12 04:10:315223 SetGLError(GL_INVALID_OPERATION,
5224 "glAttachShader: can not attach more than"
5225 " one shader of the same type.");
5226 return;
5227 }
[email protected]ae51d192010-04-27 00:48:035228 glAttachShader(program_info->service_id(), shader_info->service_id());
5229}
5230
5231void GLES2DecoderImpl::DoDetachShader(
5232 GLuint program_client_id, GLint shader_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:585233 ProgramManager::ProgramInfo* program_info = GetProgramInfoNotShader(
5234 program_client_id, "glDetachShader");
[email protected]ae51d192010-04-27 00:48:035235 if (!program_info) {
[email protected]ae51d192010-04-27 00:48:035236 return;
5237 }
[email protected]6b8cf1a2010-05-06 16:13:585238 ShaderManager::ShaderInfo* shader_info = GetShaderInfoNotProgram(
5239 shader_client_id, "glDetachShader");
[email protected]ae51d192010-04-27 00:48:035240 if (!shader_info) {
[email protected]ae51d192010-04-27 00:48:035241 return;
5242 }
[email protected]9a0ccd42011-03-16 23:58:225243 if (!program_info->DetachShader(shader_manager(), shader_info)) {
5244 SetGLError(GL_INVALID_OPERATION,
5245 "glDetachShader: shader not attached to program");
5246 return;
5247 }
[email protected]ae51d192010-04-27 00:48:035248 glDetachShader(program_info->service_id(), shader_info->service_id());
5249}
5250
5251void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:585252 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
5253 program_client_id, "glValidateProgram");
[email protected]ae51d192010-04-27 00:48:035254 if (!info) {
[email protected]ae51d192010-04-27 00:48:035255 return;
5256 }
[email protected]d685a682011-04-29 16:19:575257 info->Validate();
[email protected]1958e0e2010-04-22 05:17:155258}
5259
[email protected]b1122982010-05-17 23:04:245260void GLES2DecoderImpl::DoGetVertexAttribfv(
5261 GLuint index, GLenum pname, GLfloat* params) {
5262 VertexAttribManager::VertexAttribInfo* info =
5263 vertex_attrib_manager_.GetVertexAttribInfo(index);
5264 if (!info) {
5265 SetGLError(GL_INVALID_VALUE, "glGetVertexAttribfv: index out of range");
5266 return;
5267 }
5268 switch (pname) {
5269 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
5270 BufferManager::BufferInfo* buffer = info->buffer();
5271 if (buffer && !buffer->IsDeleted()) {
5272 GLuint client_id;
5273 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
5274 *params = static_cast<GLfloat>(client_id);
5275 }
5276 break;
5277 }
5278 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5279 *params = static_cast<GLfloat>(info->enabled());
5280 break;
5281 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5282 *params = static_cast<GLfloat>(info->size());
5283 break;
5284 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5285 *params = static_cast<GLfloat>(info->gl_stride());
5286 break;
5287 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5288 *params = static_cast<GLfloat>(info->type());
5289 break;
5290 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5291 *params = static_cast<GLfloat>(info->normalized());
5292 break;
5293 case GL_CURRENT_VERTEX_ATTRIB:
5294 params[0] = info->value().v[0];
5295 params[1] = info->value().v[1];
5296 params[2] = info->value().v[2];
5297 params[3] = info->value().v[3];
5298 break;
5299 default:
5300 NOTREACHED();
5301 break;
5302 }
5303}
5304
5305void GLES2DecoderImpl::DoGetVertexAttribiv(
5306 GLuint index, GLenum pname, GLint* params) {
5307 VertexAttribManager::VertexAttribInfo* info =
5308 vertex_attrib_manager_.GetVertexAttribInfo(index);
5309 if (!info) {
5310 SetGLError(GL_INVALID_VALUE, "glGetVertexAttribiv: index out of range");
5311 return;
5312 }
5313 switch (pname) {
5314 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
5315 BufferManager::BufferInfo* buffer = info->buffer();
5316 if (buffer && !buffer->IsDeleted()) {
5317 GLuint client_id;
5318 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
5319 *params = client_id;
5320 }
5321 break;
5322 }
5323 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5324 *params = info->enabled();
5325 break;
5326 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5327 *params = info->size();
5328 break;
5329 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5330 *params = info->gl_stride();
5331 break;
5332 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5333 *params = info->type();
5334 break;
5335 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5336 *params = static_cast<GLint>(info->normalized());
5337 break;
5338 case GL_CURRENT_VERTEX_ATTRIB:
5339 params[0] = static_cast<GLint>(info->value().v[0]);
5340 params[1] = static_cast<GLint>(info->value().v[1]);
5341 params[2] = static_cast<GLint>(info->value().v[2]);
5342 params[3] = static_cast<GLint>(info->value().v[3]);
5343 break;
5344 default:
5345 NOTREACHED();
5346 break;
5347 }
5348}
5349
5350void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
5351 VertexAttribManager::VertexAttribInfo* info =
5352 vertex_attrib_manager_.GetVertexAttribInfo(index);
5353 if (!info) {
5354 SetGLError(GL_INVALID_VALUE, "glVertexAttrib1f: index out of range");
5355 return;
5356 }
5357 VertexAttribManager::VertexAttribInfo::Vec4 value;
5358 value.v[0] = v0;
5359 value.v[1] = 0.0f;
5360 value.v[2] = 0.0f;
5361 value.v[3] = 1.0f;
5362 info->set_value(value);
5363 glVertexAttrib1f(index, v0);
5364}
5365
5366void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
5367 VertexAttribManager::VertexAttribInfo* info =
5368 vertex_attrib_manager_.GetVertexAttribInfo(index);
5369 if (!info) {
5370 SetGLError(GL_INVALID_VALUE, "glVertexAttrib2f: index out of range");
5371 return;
5372 }
5373 VertexAttribManager::VertexAttribInfo::Vec4 value;
5374 value.v[0] = v0;
5375 value.v[1] = v1;
5376 value.v[2] = 0.0f;
5377 value.v[3] = 1.0f;
5378 info->set_value(value);
5379 glVertexAttrib2f(index, v0, v1);
5380}
5381
5382void GLES2DecoderImpl::DoVertexAttrib3f(
5383 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
5384 VertexAttribManager::VertexAttribInfo* info =
5385 vertex_attrib_manager_.GetVertexAttribInfo(index);
5386 if (!info) {
5387 SetGLError(GL_INVALID_VALUE, "glVertexAttrib3f: index out of range");
5388 return;
5389 }
5390 VertexAttribManager::VertexAttribInfo::Vec4 value;
5391 value.v[0] = v0;
5392 value.v[1] = v1;
5393 value.v[2] = v2;
5394 value.v[3] = 1.0f;
5395 info->set_value(value);
5396 glVertexAttrib3f(index, v0, v1, v2);
5397}
5398
5399void GLES2DecoderImpl::DoVertexAttrib4f(
5400 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
5401 VertexAttribManager::VertexAttribInfo* info =
5402 vertex_attrib_manager_.GetVertexAttribInfo(index);
5403 if (!info) {
5404 SetGLError(GL_INVALID_VALUE, "glVertexAttrib4f: index out of range");
5405 return;
5406 }
5407 VertexAttribManager::VertexAttribInfo::Vec4 value;
5408 value.v[0] = v0;
5409 value.v[1] = v1;
5410 value.v[2] = v2;
5411 value.v[3] = v3;
5412 info->set_value(value);
5413 glVertexAttrib4f(index, v0, v1, v2, v3);
5414}
5415
5416void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
5417 VertexAttribManager::VertexAttribInfo* info =
5418 vertex_attrib_manager_.GetVertexAttribInfo(index);
5419 if (!info) {
5420 SetGLError(GL_INVALID_VALUE, "glVertexAttrib1fv: index out of range");
5421 return;
5422 }
5423 VertexAttribManager::VertexAttribInfo::Vec4 value;
5424 value.v[0] = v[0];
5425 value.v[1] = 0.0f;
5426 value.v[2] = 0.0f;
5427 value.v[3] = 1.0f;
5428 info->set_value(value);
5429 glVertexAttrib1fv(index, v);
5430}
5431
5432void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
5433 VertexAttribManager::VertexAttribInfo* info =
5434 vertex_attrib_manager_.GetVertexAttribInfo(index);
5435 if (!info) {
5436 SetGLError(GL_INVALID_VALUE, "glVertexAttrib2fv: index out of range");
5437 return;
5438 }
5439 VertexAttribManager::VertexAttribInfo::Vec4 value;
5440 value.v[0] = v[0];
5441 value.v[1] = v[1];
5442 value.v[2] = 0.0f;
5443 value.v[3] = 1.0f;
5444 info->set_value(value);
5445 glVertexAttrib2fv(index, v);
5446}
5447
5448void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
5449 VertexAttribManager::VertexAttribInfo* info =
5450 vertex_attrib_manager_.GetVertexAttribInfo(index);
5451 if (!info) {
5452 SetGLError(GL_INVALID_VALUE, "glVertexAttrib3fv: index out of range");
5453 return;
5454 }
5455 VertexAttribManager::VertexAttribInfo::Vec4 value;
5456 value.v[0] = v[0];
5457 value.v[1] = v[1];
5458 value.v[2] = v[2];
5459 value.v[3] = 1.0f;
5460 info->set_value(value);
5461 glVertexAttrib3fv(index, v);
5462}
5463
5464void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
5465 VertexAttribManager::VertexAttribInfo* info =
5466 vertex_attrib_manager_.GetVertexAttribInfo(index);
5467 if (!info) {
5468 SetGLError(GL_INVALID_VALUE, "glVertexAttrib4fv: index out of range");
5469 return;
5470 }
5471 VertexAttribManager::VertexAttribInfo::Vec4 value;
5472 value.v[0] = v[0];
5473 value.v[1] = v[1];
5474 value.v[2] = v[2];
5475 value.v[3] = v[3];
5476 info->set_value(value);
5477 glVertexAttrib4fv(index, v);
5478}
5479
[email protected]f7a64ee2010-02-01 22:24:145480error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
[email protected]b9849abf2009-11-25 19:13:195481 uint32 immediate_data_size, const gles2::VertexAttribPointer& c) {
[email protected]8eee29c2010-04-29 03:38:295482 if (!bound_array_buffer_ || bound_array_buffer_->IsDeleted()) {
5483 SetGLError(GL_INVALID_VALUE,
5484 "glVertexAttribPointer: no array buffer bound");
5485 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325486 }
[email protected]8eee29c2010-04-29 03:38:295487
5488 GLuint indx = c.indx;
5489 GLint size = c.size;
5490 GLenum type = c.type;
5491 GLboolean normalized = c.normalized;
5492 GLsizei stride = c.stride;
5493 GLsizei offset = c.offset;
5494 const void* ptr = reinterpret_cast<const void*>(offset);
[email protected]9438b012010-06-15 22:55:055495 if (!validators_->vertex_attrib_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:295496 SetGLError(GL_INVALID_ENUM,
5497 "glVertexAttribPointer: type GL_INVALID_ENUM");
5498 return error::kNoError;
5499 }
[email protected]9438b012010-06-15 22:55:055500 if (!validators_->vertex_attrib_size.IsValid(size)) {
[email protected]ff81c192011-01-07 23:04:315501 SetGLError(GL_INVALID_VALUE,
[email protected]8eee29c2010-04-29 03:38:295502 "glVertexAttribPointer: size GL_INVALID_VALUE");
5503 return error::kNoError;
5504 }
5505 if (indx >= group_->max_vertex_attribs()) {
5506 SetGLError(GL_INVALID_VALUE, "glVertexAttribPointer: index out of range");
5507 return error::kNoError;
5508 }
5509 if (stride < 0) {
5510 SetGLError(GL_INVALID_VALUE,
5511 "glVertexAttribPointer: stride < 0");
5512 return error::kNoError;
5513 }
5514 if (stride > 255) {
5515 SetGLError(GL_INVALID_VALUE,
5516 "glVertexAttribPointer: stride > 255");
5517 return error::kNoError;
5518 }
5519 if (offset < 0) {
5520 SetGLError(GL_INVALID_VALUE,
5521 "glVertexAttribPointer: offset < 0");
5522 return error::kNoError;
5523 }
5524 GLsizei component_size =
[email protected]ff81c192011-01-07 23:04:315525 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
[email protected]8eee29c2010-04-29 03:38:295526 if (offset % component_size > 0) {
[email protected]ff81c192011-01-07 23:04:315527 SetGLError(GL_INVALID_OPERATION,
5528 "glVertexAttribPointer: offset not valid for type");
5529 return error::kNoError;
5530 }
5531 if (stride % component_size > 0) {
5532 SetGLError(GL_INVALID_OPERATION,
[email protected]8eee29c2010-04-29 03:38:295533 "glVertexAttribPointer: stride not valid for type");
5534 return error::kNoError;
5535 }
[email protected]8fbedc02010-11-18 18:43:405536 vertex_attrib_manager_.SetAttribInfo(
5537 indx,
[email protected]8eee29c2010-04-29 03:38:295538 bound_array_buffer_,
5539 size,
5540 type,
[email protected]b1122982010-05-17 23:04:245541 normalized,
5542 stride,
5543 stride != 0 ? stride : component_size * size,
[email protected]8eee29c2010-04-29 03:38:295544 offset);
[email protected]8fbedc02010-11-18 18:43:405545 if (type != GL_FIXED) {
5546 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
5547 }
[email protected]f7a64ee2010-02-01 22:24:145548 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325549}
5550
[email protected]f7a64ee2010-02-01 22:24:145551error::Error GLES2DecoderImpl::HandleReadPixels(
[email protected]b9849abf2009-11-25 19:13:195552 uint32 immediate_data_size, const gles2::ReadPixels& c) {
[email protected]612d2f82009-12-08 20:49:315553 GLint x = c.x;
5554 GLint y = c.y;
5555 GLsizei width = c.width;
5556 GLsizei height = c.height;
5557 GLenum format = c.format;
5558 GLenum type = c.type;
[email protected]57f223832010-03-19 01:57:565559 if (width < 0 || height < 0) {
[email protected]8eee29c2010-04-29 03:38:295560 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions < 0");
[email protected]57f223832010-03-19 01:57:565561 return error::kNoError;
5562 }
[email protected]a51788e2010-02-24 21:54:255563 typedef gles2::ReadPixels::Result Result;
[email protected]a76b0052010-03-05 00:33:185564 uint32 pixels_size;
5565 if (!GLES2Util::ComputeImageDataSize(
5566 width, height, format, type, pack_alignment_, &pixels_size)) {
5567 return error::kOutOfBounds;
5568 }
[email protected]612d2f82009-12-08 20:49:315569 void* pixels = GetSharedMemoryAs<void*>(
5570 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
[email protected]a51788e2010-02-24 21:54:255571 Result* result = GetSharedMemoryAs<Result*>(
5572 c.result_shm_id, c.result_shm_offset, sizeof(*result));
5573 if (!pixels || !result) {
[email protected]f7a64ee2010-02-01 22:24:145574 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:465575 }
[email protected]a51788e2010-02-24 21:54:255576
[email protected]9438b012010-06-15 22:55:055577 if (!validators_->read_pixel_format.IsValid(format)) {
[email protected]8eee29c2010-04-29 03:38:295578 SetGLError(GL_INVALID_ENUM, "glReadPixels: format GL_INVALID_ENUM");
5579 return error::kNoError;
5580 }
[email protected]9438b012010-06-15 22:55:055581 if (!validators_->pixel_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:295582 SetGLError(GL_INVALID_ENUM, "glReadPixels: type GL_INVALID_ENUM");
[email protected]d2cf0a2d2010-02-25 21:36:125583 return error::kNoError;
5584 }
[email protected]57f223832010-03-19 01:57:565585 if (width == 0 || height == 0) {
5586 return error::kNoError;
5587 }
5588
[email protected]57f223832010-03-19 01:57:565589 // Get the size of the current fbo or backbuffer.
[email protected]8e3e0662010-08-23 18:46:305590 gfx::Size max_size = GetBoundReadFrameBufferSize();
[email protected]57f223832010-03-19 01:57:565591
5592 GLint max_x;
5593 GLint max_y;
5594 if (!SafeAdd(x, width, &max_x) || !SafeAdd(y, height, &max_y)) {
[email protected]8eee29c2010-04-29 03:38:295595 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]f7a64ee2010-02-01 22:24:145596 return error::kNoError;
[email protected]612d2f82009-12-08 20:49:315597 }
[email protected]57f223832010-03-19 01:57:565598
[email protected]0d6bfdc2011-11-02 01:32:205599 if (!CheckBoundFramebuffersValid("glReadPixels")) {
5600 return error::kNoError;
5601 }
5602
[email protected]a0b78dc2011-11-11 10:43:105603 CopyRealGLErrorsToWrapper();
5604
5605 ScopedResolvedFrameBufferBinder binder(this, false, true);
5606
[email protected]d37231fa2010-04-09 21:16:025607 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
[email protected]57f223832010-03-19 01:57:565608 // The user requested an out of range area. Get the results 1 line
5609 // at a time.
5610 uint32 temp_size;
5611 if (!GLES2Util::ComputeImageDataSize(
5612 width, 1, format, type, pack_alignment_, &temp_size)) {
[email protected]8eee29c2010-04-29 03:38:295613 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:565614 return error::kNoError;
5615 }
5616 GLsizei unpadded_row_size = temp_size;
5617 if (!GLES2Util::ComputeImageDataSize(
5618 width, 2, format, type, pack_alignment_, &temp_size)) {
[email protected]8eee29c2010-04-29 03:38:295619 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:565620 return error::kNoError;
5621 }
5622 GLsizei padded_row_size = temp_size - unpadded_row_size;
5623 if (padded_row_size < 0 || unpadded_row_size < 0) {
[email protected]8eee29c2010-04-29 03:38:295624 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:565625 return error::kNoError;
5626 }
5627
5628 GLint dest_x_offset = std::max(-x, 0);
5629 uint32 dest_row_offset;
5630 if (!GLES2Util::ComputeImageDataSize(
5631 dest_x_offset, 1, format, type, pack_alignment_, &dest_row_offset)) {
[email protected]8eee29c2010-04-29 03:38:295632 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:565633 return error::kNoError;
5634 }
5635
5636 // Copy each row into the larger dest rect.
5637 int8* dst = static_cast<int8*>(pixels);
5638 GLint read_x = std::max(0, x);
[email protected]d37231fa2010-04-09 21:16:025639 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
[email protected]57f223832010-03-19 01:57:565640 GLint read_width = read_end_x - read_x;
5641 for (GLint yy = 0; yy < height; ++yy) {
5642 GLint ry = y + yy;
5643
5644 // Clear the row.
5645 memset(dst, 0, unpadded_row_size);
5646
5647 // If the row is in range, copy it.
[email protected]d37231fa2010-04-09 21:16:025648 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
[email protected]57f223832010-03-19 01:57:565649 glReadPixels(
5650 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
5651 }
5652 dst += padded_row_size;
5653 }
5654 } else {
5655 glReadPixels(x, y, width, height, format, type, pixels);
5656 }
[email protected]1002c2d2011-06-28 22:39:045657 GLenum error = PeekGLError();
[email protected]a51788e2010-02-24 21:54:255658 if (error == GL_NO_ERROR) {
5659 *result = true;
[email protected]4848b9f82011-03-10 18:37:565660
5661 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
5662 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
5663 if ((channels_exist & 0x0008) == 0) {
5664 // Set the alpha to 255 because some drivers are buggy in this regard.
5665 uint32 temp_size;
5666 if (!GLES2Util::ComputeImageDataSize(
5667 width, 1, format, type, pack_alignment_, &temp_size)) {
5668 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
5669 return error::kNoError;
5670 }
5671 GLsizei unpadded_row_size = temp_size;
5672 if (!GLES2Util::ComputeImageDataSize(
5673 width, 2, format, type, pack_alignment_, &temp_size)) {
5674 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
5675 return error::kNoError;
5676 }
5677 GLsizei padded_row_size = temp_size - unpadded_row_size;
5678 if (padded_row_size < 0 || unpadded_row_size < 0) {
5679 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
5680 return error::kNoError;
5681 }
5682 // NOTE: Assumes the type is GL_UNSIGNED_BYTE which was true at the time
5683 // of this implementation.
5684 if (type != GL_UNSIGNED_BYTE) {
5685 SetGLError(GL_INVALID_OPERATION, "unsupported readPixel format");
5686 return error::kNoError;
5687 }
5688 switch (format) {
5689 case GL_RGBA:
[email protected]297ca1c2011-06-20 23:08:465690 case GL_BGRA_EXT:
[email protected]4848b9f82011-03-10 18:37:565691 case GL_ALPHA: {
5692 int offset = (format == GL_ALPHA) ? 0 : 3;
5693 int step = (format == GL_ALPHA) ? 1 : 4;
5694 uint8* dst = static_cast<uint8*>(pixels) + offset;
5695 for (GLint yy = 0; yy < height; ++yy) {
5696 uint8* end = dst + unpadded_row_size;
5697 for (uint8* d = dst; d < end; d += step) {
5698 *d = 255;
5699 }
5700 dst += padded_row_size;
5701 }
5702 break;
5703 }
5704 default:
5705 break;
5706 }
5707 }
[email protected]a51788e2010-02-24 21:54:255708 }
[email protected]4848b9f82011-03-10 18:37:565709
[email protected]f7a64ee2010-02-01 22:24:145710 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325711}
5712
[email protected]f7a64ee2010-02-01 22:24:145713error::Error GLES2DecoderImpl::HandlePixelStorei(
[email protected]b9849abf2009-11-25 19:13:195714 uint32 immediate_data_size, const gles2::PixelStorei& c) {
5715 GLenum pname = c.pname;
5716 GLenum param = c.param;
[email protected]9438b012010-06-15 22:55:055717 if (!validators_->pixel_store.IsValid(pname)) {
[email protected]8eee29c2010-04-29 03:38:295718 SetGLError(GL_INVALID_ENUM, "glPixelStorei: pname GL_INVALID_ENUM");
[email protected]d2cf0a2d2010-02-25 21:36:125719 return error::kNoError;
5720 }
[email protected]9438b012010-06-15 22:55:055721 if (!validators_->pixel_store_alignment.IsValid(param)) {
[email protected]8eee29c2010-04-29 03:38:295722 SetGLError(GL_INVALID_VALUE, "glPixelSTore: param GL_INVALID_VALUE");
[email protected]f7a64ee2010-02-01 22:24:145723 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195724 }
5725 glPixelStorei(pname, param);
5726 switch (pname) {
5727 case GL_PACK_ALIGNMENT:
5728 pack_alignment_ = param;
5729 break;
5730 case GL_UNPACK_ALIGNMENT:
5731 unpack_alignment_ = param;
5732 break;
5733 default:
5734 // Validation should have prevented us from getting here.
[email protected]656dcaad2010-05-07 17:18:375735 NOTREACHED();
[email protected]b9849abf2009-11-25 19:13:195736 break;
5737 }
[email protected]f7a64ee2010-02-01 22:24:145738 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195739}
5740
[email protected]1c75a3702011-11-11 14:15:285741error::Error GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
5742 uint32 immediate_data_size, const gles2::PostSubBufferCHROMIUM& c) {
5743 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
5744 if (!surface_->SupportsPostSubBuffer()) {
5745 SetGLError(GL_INVALID_OPERATION,
5746 "glPostSubBufferCHROMIUM: command not supported by surface");
5747 return error::kNoError;
5748 }
5749 if (surface_->PostSubBuffer(c.x, c.y, c.width, c.height))
5750 return error::kNoError;
5751 else
5752 return error::kLostContext;
5753}
5754
[email protected]558847a2010-03-24 07:02:545755error::Error GLES2DecoderImpl::GetAttribLocationHelper(
5756 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
5757 const std::string& name_str) {
[email protected]258a3313f2011-10-18 20:13:575758 if (!StringIsValidForGLES(name_str.c_str())) {
5759 SetGLError(GL_INVALID_VALUE, "glGetAttribLocation: Invalid character");
5760 return error::kNoError;
5761 }
[email protected]6b8cf1a2010-05-06 16:13:585762 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
5763 client_id, "glGetAttribLocation");
[email protected]ae51d192010-04-27 00:48:035764 if (!info) {
[email protected]f7a64ee2010-02-01 22:24:145765 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195766 }
[email protected]ae51d192010-04-27 00:48:035767 if (!info->IsValid()) {
[email protected]8eee29c2010-04-29 03:38:295768 SetGLError(GL_INVALID_OPERATION, "glGetAttribLocation: program not linked");
[email protected]0bfd9882010-02-05 23:02:255769 return error::kNoError;
5770 }
[email protected]b9849abf2009-11-25 19:13:195771 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:545772 location_shm_id, location_shm_offset, sizeof(GLint));
5773 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:145774 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:195775 }
[email protected]558847a2010-03-24 07:02:545776 // Require the client to init this incase the context is lost and we are no
5777 // longer executing commands.
5778 if (*location != -1) {
5779 return error::kGenericError;
5780 }
[email protected]0bfd9882010-02-05 23:02:255781 *location = info->GetAttribLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:145782 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195783}
5784
[email protected]558847a2010-03-24 07:02:545785error::Error GLES2DecoderImpl::HandleGetAttribLocation(
5786 uint32 immediate_data_size, const gles2::GetAttribLocation& c) {
5787 uint32 name_size = c.data_size;
5788 const char* name = GetSharedMemoryAs<const char*>(
5789 c.name_shm_id, c.name_shm_offset, name_size);
5790 if (!name) {
5791 return error::kOutOfBounds;
5792 }
5793 String name_str(name, name_size);
5794 return GetAttribLocationHelper(
5795 c.program, c.location_shm_id, c.location_shm_offset, name_str);
5796}
5797
[email protected]f7a64ee2010-02-01 22:24:145798error::Error GLES2DecoderImpl::HandleGetAttribLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:195799 uint32 immediate_data_size, const gles2::GetAttribLocationImmediate& c) {
[email protected]558847a2010-03-24 07:02:545800 uint32 name_size = c.data_size;
5801 const char* name = GetImmediateDataAs<const char*>(
5802 c, name_size, immediate_data_size);
5803 if (!name) {
5804 return error::kOutOfBounds;
5805 }
5806 String name_str(name, name_size);
5807 return GetAttribLocationHelper(
5808 c.program, c.location_shm_id, c.location_shm_offset, name_str);
5809}
5810
5811error::Error GLES2DecoderImpl::HandleGetAttribLocationBucket(
5812 uint32 immediate_data_size, const gles2::GetAttribLocationBucket& c) {
5813 Bucket* bucket = GetBucket(c.name_bucket_id);
5814 if (!bucket) {
5815 return error::kInvalidArguments;
5816 }
5817 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:185818 if (!bucket->GetAsString(&name_str)) {
5819 return error::kInvalidArguments;
5820 }
[email protected]558847a2010-03-24 07:02:545821 return GetAttribLocationHelper(
5822 c.program, c.location_shm_id, c.location_shm_offset, name_str);
5823}
5824
5825error::Error GLES2DecoderImpl::GetUniformLocationHelper(
5826 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
5827 const std::string& name_str) {
[email protected]258a3313f2011-10-18 20:13:575828 if (!StringIsValidForGLES(name_str.c_str())) {
5829 SetGLError(GL_INVALID_VALUE, "glGetUniformLocation: Invalid character");
5830 return error::kNoError;
5831 }
[email protected]6b8cf1a2010-05-06 16:13:585832 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
5833 client_id, "glUniformLocation");
[email protected]ae51d192010-04-27 00:48:035834 if (!info) {
[email protected]f7a64ee2010-02-01 22:24:145835 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195836 }
[email protected]ae51d192010-04-27 00:48:035837 if (!info->IsValid()) {
[email protected]8eee29c2010-04-29 03:38:295838 SetGLError(GL_INVALID_OPERATION,
5839 "glGetUniformLocation: program not linked");
[email protected]0bfd9882010-02-05 23:02:255840 return error::kNoError;
5841 }
[email protected]b9849abf2009-11-25 19:13:195842 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:545843 location_shm_id, location_shm_offset, sizeof(GLint));
5844 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:145845 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:195846 }
[email protected]558847a2010-03-24 07:02:545847 // Require the client to init this incase the context is lost an we are no
5848 // longer executing commands.
5849 if (*location != -1) {
5850 return error::kGenericError;
5851 }
5852 *location = info->GetUniformLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:145853 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195854}
5855
[email protected]f7a64ee2010-02-01 22:24:145856error::Error GLES2DecoderImpl::HandleGetUniformLocation(
[email protected]b9849abf2009-11-25 19:13:195857 uint32 immediate_data_size, const gles2::GetUniformLocation& c) {
[email protected]b9849abf2009-11-25 19:13:195858 uint32 name_size = c.data_size;
5859 const char* name = GetSharedMemoryAs<const char*>(
5860 c.name_shm_id, c.name_shm_offset, name_size);
[email protected]558847a2010-03-24 07:02:545861 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:145862 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:195863 }
5864 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:545865 return GetUniformLocationHelper(
5866 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:195867}
5868
[email protected]f7a64ee2010-02-01 22:24:145869error::Error GLES2DecoderImpl::HandleGetUniformLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:195870 uint32 immediate_data_size, const gles2::GetUniformLocationImmediate& c) {
[email protected]b9849abf2009-11-25 19:13:195871 uint32 name_size = c.data_size;
[email protected]07f54fcc2009-12-22 02:46:305872 const char* name = GetImmediateDataAs<const char*>(
5873 c, name_size, immediate_data_size);
[email protected]558847a2010-03-24 07:02:545874 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:145875 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:195876 }
5877 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:545878 return GetUniformLocationHelper(
5879 c.program, c.location_shm_id, c.location_shm_offset, name_str);
5880}
5881
5882error::Error GLES2DecoderImpl::HandleGetUniformLocationBucket(
5883 uint32 immediate_data_size, const gles2::GetUniformLocationBucket& c) {
5884 Bucket* bucket = GetBucket(c.name_bucket_id);
5885 if (!bucket) {
5886 return error::kInvalidArguments;
5887 }
5888 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:185889 if (!bucket->GetAsString(&name_str)) {
5890 return error::kInvalidArguments;
5891 }
[email protected]558847a2010-03-24 07:02:545892 return GetUniformLocationHelper(
5893 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:195894}
5895
[email protected]ddd968b82010-03-02 00:44:295896error::Error GLES2DecoderImpl::HandleGetString(
5897 uint32 immediate_data_size, const gles2::GetString& c) {
5898 GLenum name = static_cast<GLenum>(c.name);
[email protected]9438b012010-06-15 22:55:055899 if (!validators_->string_type.IsValid(name)) {
[email protected]8eee29c2010-04-29 03:38:295900 SetGLError(GL_INVALID_ENUM, "glGetString: name GL_INVALID_ENUM");
[email protected]ddd968b82010-03-02 00:44:295901 return error::kNoError;
5902 }
[email protected]1958e0e2010-04-22 05:17:155903 const char* gl_str = reinterpret_cast<const char*>(glGetString(name));
5904 const char* str = NULL;
[email protected]f0d74742011-10-03 16:31:045905 std::string extensions;
[email protected]1958e0e2010-04-22 05:17:155906 switch (name) {
5907 case GL_VERSION:
5908 str = "OpenGL ES 2.0 Chromium";
5909 break;
5910 case GL_SHADING_LANGUAGE_VERSION:
5911 str = "OpenGL ES GLSL ES 1.0 Chromium";
5912 break;
5913 case GL_EXTENSIONS:
[email protected]f0d74742011-10-03 16:31:045914 {
5915 // For WebGL contexts, strip out the OES derivatives extension if it has
5916 // not been enabled.
5917 if (force_webgl_glsl_validation_ &&
5918 !derivatives_explicitly_enabled_) {
5919 extensions = feature_info_->extensions();
5920 size_t offset = extensions.find(kOESDerivativeExtension);
5921 if (std::string::npos != offset) {
5922 extensions.replace(offset,
5923 offset + arraysize(kOESDerivativeExtension),
5924 std::string());
5925 }
5926 str = extensions.c_str();
5927 } else {
5928 str = feature_info_->extensions().c_str();
5929 }
5930
5931 }
[email protected]1958e0e2010-04-22 05:17:155932 break;
5933 default:
5934 str = gl_str;
5935 break;
5936 }
[email protected]ddd968b82010-03-02 00:44:295937 Bucket* bucket = CreateBucket(c.bucket_id);
[email protected]1958e0e2010-04-22 05:17:155938 bucket->SetFromString(str);
[email protected]ddd968b82010-03-02 00:44:295939 return error::kNoError;
5940}
5941
[email protected]0c86dbf2010-03-05 08:14:115942void GLES2DecoderImpl::DoBufferData(
[email protected]b9363b22010-06-09 22:06:155943 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage) {
[email protected]9438b012010-06-15 22:55:055944 if (!validators_->buffer_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:295945 SetGLError(GL_INVALID_ENUM, "glBufferData: target GL_INVALID_ENUM");
5946 return;
5947 }
[email protected]9438b012010-06-15 22:55:055948 if (!validators_->buffer_usage.IsValid(usage)) {
[email protected]8eee29c2010-04-29 03:38:295949 SetGLError(GL_INVALID_ENUM, "glBufferData: usage GL_INVALID_ENUM");
[email protected]0c86dbf2010-03-05 08:14:115950 return;
[email protected]3b6ec202010-03-05 05:16:235951 }
5952 if (size < 0) {
[email protected]8eee29c2010-04-29 03:38:295953 SetGLError(GL_INVALID_VALUE, "glBufferData: size < 0");
[email protected]037896bd2010-04-21 19:07:285954 return;
[email protected]3b6ec202010-03-05 05:16:235955 }
5956 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
5957 if (!info) {
[email protected]8eee29c2010-04-29 03:38:295958 SetGLError(GL_INVALID_VALUE, "glBufferData: unknown buffer");
[email protected]037896bd2010-04-21 19:07:285959 return;
[email protected]3b6ec202010-03-05 05:16:235960 }
5961 // Clear the buffer to 0 if no initial data was passed in.
5962 scoped_array<int8> zero;
5963 if (!data) {
5964 zero.reset(new int8[size]);
5965 memset(zero.get(), 0, size);
5966 data = zero.get();
5967 }
[email protected]473c01ccb2011-06-07 01:33:305968
5969 if (!bufferdata_faster_than_buffersubdata_ &&
5970 size == info->size() && usage == info->usage()) {
5971 glBufferSubData(target, 0, size, data);
5972 info->SetRange(0, size, data);
5973 return;
5974 }
5975
[email protected]3b6ec202010-03-05 05:16:235976 CopyRealGLErrorsToWrapper();
5977 glBufferData(target, size, data, usage);
[email protected]1002c2d2011-06-28 22:39:045978 GLenum error = PeekGLError();
5979 if (error == GL_NO_ERROR) {
[email protected]473c01ccb2011-06-07 01:33:305980 buffer_manager()->SetInfo(info, size, usage);
[email protected]0c86dbf2010-03-05 08:14:115981 info->SetRange(0, size, data);
[email protected]3b6ec202010-03-05 05:16:235982 }
[email protected]0c86dbf2010-03-05 08:14:115983}
5984
5985error::Error GLES2DecoderImpl::HandleBufferData(
5986 uint32 immediate_data_size, const gles2::BufferData& c) {
5987 GLenum target = static_cast<GLenum>(c.target);
5988 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
5989 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
5990 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
5991 GLenum usage = static_cast<GLenum>(c.usage);
5992 const void* data = NULL;
5993 if (data_shm_id != 0 || data_shm_offset != 0) {
5994 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
5995 if (!data) {
5996 return error::kOutOfBounds;
5997 }
5998 }
5999 DoBufferData(target, size, data, usage);
[email protected]f7a64ee2010-02-01 22:24:146000 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196001}
6002
[email protected]f7a64ee2010-02-01 22:24:146003error::Error GLES2DecoderImpl::HandleBufferDataImmediate(
[email protected]b9849abf2009-11-25 19:13:196004 uint32 immediate_data_size, const gles2::BufferDataImmediate& c) {
6005 GLenum target = static_cast<GLenum>(c.target);
6006 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
[email protected]07f54fcc2009-12-22 02:46:306007 const void* data = GetImmediateDataAs<const void*>(
6008 c, size, immediate_data_size);
6009 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:146010 return error::kOutOfBounds;
[email protected]07f54fcc2009-12-22 02:46:306011 }
[email protected]b9849abf2009-11-25 19:13:196012 GLenum usage = static_cast<GLenum>(c.usage);
[email protected]0c86dbf2010-03-05 08:14:116013 DoBufferData(target, size, data, usage);
6014 return error::kNoError;
6015}
6016
6017void GLES2DecoderImpl::DoBufferSubData(
6018 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
[email protected]3916c97e2010-02-25 03:20:506019 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:476020 if (!info) {
[email protected]8eee29c2010-04-29 03:38:296021 SetGLError(GL_INVALID_VALUE, "glBufferSubData: unknown buffer");
[email protected]037896bd2010-04-21 19:07:286022 return;
[email protected]a93bb842010-02-16 23:03:476023 }
[email protected]0c86dbf2010-03-05 08:14:116024 if (!info->SetRange(offset, size, data)) {
[email protected]8eee29c2010-04-29 03:38:296025 SetGLError(GL_INVALID_VALUE, "glBufferSubData: out of range");
[email protected]473c01ccb2011-06-07 01:33:306026 return;
[email protected]07f54fcc2009-12-22 02:46:306027 }
[email protected]473c01ccb2011-06-07 01:33:306028 if (bufferdata_faster_than_buffersubdata_ &&
6029 offset == 0 && size == info->size()) {
6030 glBufferData(target, size, data, info->usage());
6031 return;
6032 }
6033 glBufferSubData(target, offset, size, data);
[email protected]b9849abf2009-11-25 19:13:196034}
6035
[email protected]0d6bfdc2011-11-02 01:32:206036bool GLES2DecoderImpl::ClearLevel(
6037 unsigned service_id,
6038 unsigned bind_target,
6039 unsigned target,
6040 int level,
6041 unsigned format,
6042 unsigned type,
6043 int width,
6044 int height) {
6045 // Assumes the size has already been checked.
6046 uint32 pixels_size = 0;
6047 if (!GLES2Util::ComputeImageDataSize(
6048 width, height, format, type, unpack_alignment_, &pixels_size)) {
6049 return false;
6050 }
6051 scoped_array<char> zero(new char[pixels_size]);
6052 memset(zero.get(), 0, pixels_size);
6053 glBindTexture(bind_target, service_id);
6054 WrappedTexImage2D(
6055 target, level, format, width, height, 0, format, type, zero.get());
6056 TextureManager::TextureInfo* info = GetTextureInfoForTarget(bind_target);
6057 glBindTexture(bind_target, info ? info->service_id() : 0);
6058 return true;
6059}
6060
[email protected]a93bb842010-02-16 23:03:476061error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
6062 GLenum target,
6063 GLint level,
6064 GLenum internal_format,
6065 GLsizei width,
6066 GLsizei height,
6067 GLint border,
6068 GLsizei image_size,
6069 const void* data) {
[email protected]a93bb842010-02-16 23:03:476070 // TODO(gman): Validate image_size is correct for width, height and format.
[email protected]9438b012010-06-15 22:55:056071 if (!validators_->texture_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:296072 SetGLError(GL_INVALID_ENUM,
6073 "glCompressedTexImage2D: target GL_INVALID_ENUM");
6074 return error::kNoError;
6075 }
[email protected]9438b012010-06-15 22:55:056076 if (!validators_->compressed_texture_format.IsValid(
6077 internal_format)) {
[email protected]8eee29c2010-04-29 03:38:296078 SetGLError(GL_INVALID_ENUM,
6079 "glCompressedTexImage2D: internal_format GL_INVALID_ENUM");
[email protected]a93bb842010-02-16 23:03:476080 return error::kNoError;
6081 }
[email protected]915a59a12010-09-30 21:29:116082 if (!texture_manager()->ValidForTarget(
6083 feature_info_, target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:476084 border != 0) {
[email protected]8eee29c2010-04-29 03:38:296085 SetGLError(GL_INVALID_VALUE,
6086 "glCompressedTexImage2D: dimensions out of range");
[email protected]a93bb842010-02-16 23:03:476087 return error::kNoError;
6088 }
[email protected]3916c97e2010-02-25 03:20:506089 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:476090 if (!info) {
[email protected]8eee29c2010-04-29 03:38:296091 SetGLError(GL_INVALID_VALUE,
6092 "glCompressedTexImage2D: unknown texture target");
[email protected]a93bb842010-02-16 23:03:476093 return error::kNoError;
6094 }
6095 scoped_array<int8> zero;
6096 if (!data) {
6097 zero.reset(new int8[image_size]);
6098 memset(zero.get(), 0, image_size);
6099 data = zero.get();
6100 }
[email protected]cadde4a2010-07-31 17:10:436101 CopyRealGLErrorsToWrapper();
[email protected]a93bb842010-02-16 23:03:476102 glCompressedTexImage2D(
6103 target, level, internal_format, width, height, border, image_size, data);
[email protected]1002c2d2011-06-28 22:39:046104 GLenum error = PeekGLError();
[email protected]cadde4a2010-07-31 17:10:436105 if (error == GL_NO_ERROR) {
6106 texture_manager()->SetLevelInfo(
[email protected]915a59a12010-09-30 21:29:116107 feature_info_,
[email protected]0d6bfdc2011-11-02 01:32:206108 info, target, level, internal_format, width, height, 1, border, 0, 0,
6109 true);
[email protected]cadde4a2010-07-31 17:10:436110 }
[email protected]a93bb842010-02-16 23:03:476111 return error::kNoError;
6112}
6113
[email protected]f7a64ee2010-02-01 22:24:146114error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:196115 uint32 immediate_data_size, const gles2::CompressedTexImage2D& c) {
6116 GLenum target = static_cast<GLenum>(c.target);
6117 GLint level = static_cast<GLint>(c.level);
6118 GLenum internal_format = static_cast<GLenum>(c.internalformat);
6119 GLsizei width = static_cast<GLsizei>(c.width);
6120 GLsizei height = static_cast<GLsizei>(c.height);
6121 GLint border = static_cast<GLint>(c.border);
6122 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
6123 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
6124 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
6125 const void* data = NULL;
6126 if (data_shm_id != 0 || data_shm_offset != 0) {
6127 data = GetSharedMemoryAs<const void*>(
6128 data_shm_id, data_shm_offset, image_size);
[email protected]ba3176a2009-12-16 18:19:466129 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:146130 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196131 }
6132 }
[email protected]a93bb842010-02-16 23:03:476133 return DoCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:196134 target, level, internal_format, width, height, border, image_size, data);
[email protected]b9849abf2009-11-25 19:13:196135}
6136
[email protected]f7a64ee2010-02-01 22:24:146137error::Error GLES2DecoderImpl::HandleCompressedTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:196138 uint32 immediate_data_size, const gles2::CompressedTexImage2DImmediate& c) {
6139 GLenum target = static_cast<GLenum>(c.target);
6140 GLint level = static_cast<GLint>(c.level);
6141 GLenum internal_format = static_cast<GLenum>(c.internalformat);
6142 GLsizei width = static_cast<GLsizei>(c.width);
6143 GLsizei height = static_cast<GLsizei>(c.height);
6144 GLint border = static_cast<GLint>(c.border);
6145 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
[email protected]07f54fcc2009-12-22 02:46:306146 const void* data = GetImmediateDataAs<const void*>(
6147 c, image_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:466148 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:146149 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:466150 }
[email protected]a93bb842010-02-16 23:03:476151 return DoCompressedTexImage2D(
6152 target, level, internal_format, width, height, border, image_size, data);
6153}
6154
[email protected]b6140d02010-05-17 14:47:166155error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
6156 uint32 immediate_data_size, const gles2::CompressedTexImage2DBucket& c) {
6157 GLenum target = static_cast<GLenum>(c.target);
6158 GLint level = static_cast<GLint>(c.level);
6159 GLenum internal_format = static_cast<GLenum>(c.internalformat);
6160 GLsizei width = static_cast<GLsizei>(c.width);
6161 GLsizei height = static_cast<GLsizei>(c.height);
6162 GLint border = static_cast<GLint>(c.border);
6163 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:286164 if (!bucket) {
6165 return error::kInvalidArguments;
6166 }
6167 uint32 data_size = bucket->size();
6168 GLsizei imageSize = data_size;
6169 const void* data = bucket->GetData(0, data_size);
6170 if (!data) {
6171 return error::kInvalidArguments;
6172 }
[email protected]b6140d02010-05-17 14:47:166173 return DoCompressedTexImage2D(
6174 target, level, internal_format, width, height, border,
[email protected]12f93d82011-10-17 21:16:286175 imageSize, data);
[email protected]b6140d02010-05-17 14:47:166176}
6177
6178error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
6179 uint32 immediate_data_size,
6180 const gles2::CompressedTexSubImage2DBucket& c) {
6181 GLenum target = static_cast<GLenum>(c.target);
6182 GLint level = static_cast<GLint>(c.level);
6183 GLint xoffset = static_cast<GLint>(c.xoffset);
6184 GLint yoffset = static_cast<GLint>(c.yoffset);
6185 GLsizei width = static_cast<GLsizei>(c.width);
6186 GLsizei height = static_cast<GLsizei>(c.height);
6187 GLenum format = static_cast<GLenum>(c.format);
6188 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:286189 if (!bucket) {
6190 return error::kInvalidArguments;
6191 }
[email protected]b6140d02010-05-17 14:47:166192 uint32 data_size = bucket->size();
6193 GLsizei imageSize = data_size;
6194 const void* data = bucket->GetData(0, data_size);
[email protected]12f93d82011-10-17 21:16:286195 if (!data) {
6196 return error::kInvalidArguments;
6197 }
[email protected]9438b012010-06-15 22:55:056198 if (!validators_->texture_target.IsValid(target)) {
[email protected]b6140d02010-05-17 14:47:166199 SetGLError(
6200 GL_INVALID_ENUM, "glCompressedTexSubImage2D: target GL_INVALID_ENUM");
6201 return error::kNoError;
6202 }
[email protected]9438b012010-06-15 22:55:056203 if (!validators_->compressed_texture_format.IsValid(format)) {
6204 SetGLError(GL_INVALID_ENUM,
6205 "glCompressedTexSubImage2D: format GL_INVALID_ENUM");
6206 return error::kNoError;
6207 }
[email protected]b6140d02010-05-17 14:47:166208 if (width < 0) {
6209 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: width < 0");
6210 return error::kNoError;
6211 }
6212 if (height < 0) {
6213 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: height < 0");
6214 return error::kNoError;
6215 }
6216 if (imageSize < 0) {
6217 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: imageSize < 0");
6218 return error::kNoError;
6219 }
[email protected]cadde4a2010-07-31 17:10:436220 DoCompressedTexSubImage2D(
[email protected]b6140d02010-05-17 14:47:166221 target, level, xoffset, yoffset, width, height, format, imageSize, data);
6222 return error::kNoError;
6223}
6224
[email protected]a93bb842010-02-16 23:03:476225error::Error GLES2DecoderImpl::DoTexImage2D(
6226 GLenum target,
6227 GLint level,
6228 GLenum internal_format,
6229 GLsizei width,
6230 GLsizei height,
6231 GLint border,
6232 GLenum format,
6233 GLenum type,
6234 const void* pixels,
6235 uint32 pixels_size) {
[email protected]9438b012010-06-15 22:55:056236 if (!validators_->texture_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:296237 SetGLError(GL_INVALID_ENUM, "glTexImage2D: target GL_INVALID_ENUM");
6238 return error::kNoError;
6239 }
[email protected]9438b012010-06-15 22:55:056240 if (!validators_->texture_format.IsValid(internal_format)) {
[email protected]8eee29c2010-04-29 03:38:296241 SetGLError(GL_INVALID_ENUM,
6242 "glTexImage2D: internal_format GL_INVALID_ENUM");
6243 return error::kNoError;
6244 }
[email protected]9438b012010-06-15 22:55:056245 if (!validators_->texture_format.IsValid(format)) {
[email protected]8eee29c2010-04-29 03:38:296246 SetGLError(GL_INVALID_ENUM, "glTexImage2D: format GL_INVALID_ENUM");
6247 return error::kNoError;
6248 }
[email protected]9438b012010-06-15 22:55:056249 if (!validators_->pixel_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:296250 SetGLError(GL_INVALID_ENUM, "glTexImage2D: type GL_INVALID_ENUM");
[email protected]f7a64ee2010-02-01 22:24:146251 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196252 }
[email protected]7b92c412010-07-20 17:48:256253 if (format != internal_format) {
6254 SetGLError(GL_INVALID_OPERATION, "glTexImage2D: format != internalFormat");
6255 return error::kNoError;
6256 }
[email protected]915a59a12010-09-30 21:29:116257 if (!texture_manager()->ValidForTarget(
6258 feature_info_, target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:476259 border != 0) {
[email protected]8eee29c2010-04-29 03:38:296260 SetGLError(GL_INVALID_VALUE, "glTexImage2D: dimensions out of range");
[email protected]a93bb842010-02-16 23:03:476261 return error::kNoError;
6262 }
[email protected]3916c97e2010-02-25 03:20:506263 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:476264 if (!info) {
[email protected]8eee29c2010-04-29 03:38:296265 SetGLError(GL_INVALID_OPERATION,
6266 "glTexImage2D: unknown texture for target");
[email protected]a93bb842010-02-16 23:03:476267 return error::kNoError;
6268 }
[email protected]0226c112011-07-22 03:25:076269
6270 GLsizei tex_width = 0;
6271 GLsizei tex_height = 0;
6272 GLenum tex_type = 0;
6273 GLenum tex_format = 0;
6274 bool level_is_same =
6275 info->GetLevelSize(target, level, &tex_width, &tex_height) &&
6276 info->GetLevelType(target, level, &tex_type, &tex_format) &&
6277 width == tex_width && height == tex_height &&
6278 type == tex_type && format == tex_format;
6279
6280 if (level_is_same && !pixels) {
[email protected]ea72ed222011-08-17 18:58:436281 tex_image_2d_failed_ = false;
[email protected]0226c112011-07-22 03:25:076282 return error::kNoError;
6283 }
6284
[email protected]297ca1c2011-06-20 23:08:466285 if (info->IsAttachedToFramebuffer()) {
6286 state_dirty_ = true;
6287 }
6288
[email protected]0226c112011-07-22 03:25:076289 if (!teximage2d_faster_than_texsubimage2d_ && level_is_same) {
6290 glTexSubImage2D(target, level, 0, 0, width, height, format, type, pixels);
6291 tex_image_2d_failed_ = false;
6292 return error::kNoError;
[email protected]7488d962010-07-16 02:41:586293 }
[email protected]876f6fee2010-08-02 23:10:326294
[email protected]cadde4a2010-07-31 17:10:436295 CopyRealGLErrorsToWrapper();
[email protected]473c01ccb2011-06-07 01:33:306296 WrappedTexImage2D(
6297 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:476298 pixels);
[email protected]1002c2d2011-06-28 22:39:046299 GLenum error = PeekGLError();
[email protected]cadde4a2010-07-31 17:10:436300 if (error == GL_NO_ERROR) {
[email protected]0d6bfdc2011-11-02 01:32:206301 texture_manager()->SetLevelInfo(
6302 feature_info_, info,
6303 target, level, internal_format, width, height, 1, border, format, type,
6304 pixels != NULL);
[email protected]b493ee622011-04-13 23:52:006305 tex_image_2d_failed_ = false;
[email protected]cadde4a2010-07-31 17:10:436306 }
[email protected]f7a64ee2010-02-01 22:24:146307 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196308}
6309
[email protected]f7a64ee2010-02-01 22:24:146310error::Error GLES2DecoderImpl::HandleTexImage2D(
[email protected]b9849abf2009-11-25 19:13:196311 uint32 immediate_data_size, const gles2::TexImage2D& c) {
[email protected]366ae242011-05-10 02:23:586312 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexImage2D");
[email protected]b493ee622011-04-13 23:52:006313 tex_image_2d_failed_ = true;
[email protected]b9849abf2009-11-25 19:13:196314 GLenum target = static_cast<GLenum>(c.target);
6315 GLint level = static_cast<GLint>(c.level);
6316 GLint internal_format = static_cast<GLint>(c.internalformat);
6317 GLsizei width = static_cast<GLsizei>(c.width);
6318 GLsizei height = static_cast<GLsizei>(c.height);
6319 GLint border = static_cast<GLint>(c.border);
6320 GLenum format = static_cast<GLenum>(c.format);
6321 GLenum type = static_cast<GLenum>(c.type);
6322 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
6323 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
[email protected]a76b0052010-03-05 00:33:186324 uint32 pixels_size;
6325 if (!GLES2Util::ComputeImageDataSize(
6326 width, height, format, type, unpack_alignment_, &pixels_size)) {
6327 return error::kOutOfBounds;
6328 }
[email protected]b9849abf2009-11-25 19:13:196329 const void* pixels = NULL;
6330 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
6331 pixels = GetSharedMemoryAs<const void*>(
6332 pixels_shm_id, pixels_shm_offset, pixels_size);
[email protected]ba3176a2009-12-16 18:19:466333 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:146334 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196335 }
6336 }
[email protected]a93bb842010-02-16 23:03:476337 return DoTexImage2D(
[email protected]b9849abf2009-11-25 19:13:196338 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:476339 pixels, pixels_size);
[email protected]b9849abf2009-11-25 19:13:196340}
6341
[email protected]f7a64ee2010-02-01 22:24:146342error::Error GLES2DecoderImpl::HandleTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:196343 uint32 immediate_data_size, const gles2::TexImage2DImmediate& c) {
6344 GLenum target = static_cast<GLenum>(c.target);
6345 GLint level = static_cast<GLint>(c.level);
[email protected]ba3176a2009-12-16 18:19:466346 GLint internal_format = static_cast<GLint>(c.internalformat);
[email protected]b9849abf2009-11-25 19:13:196347 GLsizei width = static_cast<GLsizei>(c.width);
6348 GLsizei height = static_cast<GLsizei>(c.height);
6349 GLint border = static_cast<GLint>(c.border);
6350 GLenum format = static_cast<GLenum>(c.format);
6351 GLenum type = static_cast<GLenum>(c.type);
[email protected]a76b0052010-03-05 00:33:186352 uint32 size;
6353 if (!GLES2Util::ComputeImageDataSize(
6354 width, height, format, type, unpack_alignment_, &size)) {
6355 return error::kOutOfBounds;
6356 }
[email protected]07f54fcc2009-12-22 02:46:306357 const void* pixels = GetImmediateDataAs<const void*>(
6358 c, size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:466359 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:146360 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:466361 }
[email protected]a93bb842010-02-16 23:03:476362 DoTexImage2D(
[email protected]ba3176a2009-12-16 18:19:466363 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:476364 pixels, size);
[email protected]f7a64ee2010-02-01 22:24:146365 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326366}
6367
[email protected]cadde4a2010-07-31 17:10:436368void GLES2DecoderImpl::DoCompressedTexSubImage2D(
6369 GLenum target,
6370 GLint level,
6371 GLint xoffset,
6372 GLint yoffset,
6373 GLsizei width,
6374 GLsizei height,
6375 GLenum format,
6376 GLsizei image_size,
6377 const void * data) {
6378 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
6379 if (!info) {
6380 SetGLError(GL_INVALID_OPERATION,
6381 "glCompressedTexSubImage2D: unknown texture for target");
6382 return;
6383 }
6384 GLenum type = 0;
[email protected]df6cf1ad2011-01-29 01:20:526385 GLenum internal_format = 0;
6386 if (!info->GetLevelType(target, level, &type, &internal_format)) {
6387 SetGLError(
6388 GL_INVALID_OPERATION,
6389 "glCompressdTexSubImage2D: level does not exist.");
6390 return;
6391 }
6392 if (internal_format != format) {
6393 SetGLError(
6394 GL_INVALID_OPERATION,
6395 "glCompressdTexSubImage2D: format does not match internal format.");
6396 return;
6397 }
6398 if (!info->ValidForTexture(
6399 target, level, xoffset, yoffset, width, height, format, type)) {
[email protected]cadde4a2010-07-31 17:10:436400 SetGLError(GL_INVALID_VALUE,
6401 "glCompressdTexSubImage2D: bad dimensions.");
6402 return;
6403 }
[email protected]0d6bfdc2011-11-02 01:32:206404 // Note: There is no need to deal with texture cleared tracking here
6405 // because the validation above means you can only get here if the level
6406 // is already a matching compressed format and in that case
6407 // CompressedTexImage2D already cleared the texture.
[email protected]cadde4a2010-07-31 17:10:436408 glCompressedTexSubImage2D(
6409 target, level, xoffset, yoffset, width, height, format, image_size, data);
6410}
6411
[email protected]6e288612010-12-21 20:45:036412static void Clip(
6413 GLint start, GLint range, GLint sourceRange,
6414 GLint* out_start, GLint* out_range) {
6415 DCHECK(out_start);
6416 DCHECK(out_range);
6417 if (start < 0) {
6418 range += start;
6419 start = 0;
6420 }
6421 GLint end = start + range;
6422 if (end > sourceRange) {
6423 range -= end - sourceRange;
6424 }
6425 *out_start = start;
6426 *out_range = range;
6427}
6428
[email protected]cadde4a2010-07-31 17:10:436429void GLES2DecoderImpl::DoCopyTexImage2D(
6430 GLenum target,
6431 GLint level,
6432 GLenum internal_format,
6433 GLint x,
6434 GLint y,
6435 GLsizei width,
6436 GLsizei height,
6437 GLint border) {
6438 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
6439 if (!info) {
6440 SetGLError(GL_INVALID_OPERATION,
6441 "glCopyTexImage2D: unknown texture for target");
6442 return;
6443 }
[email protected]915a59a12010-09-30 21:29:116444 if (!texture_manager()->ValidForTarget(
6445 feature_info_, target, level, width, height, 1) ||
[email protected]f5719fb2010-08-04 18:27:186446 border != 0) {
6447 SetGLError(GL_INVALID_VALUE, "glCopyTexImage2D: dimensions out of range");
6448 return;
6449 }
6450
[email protected]9edc6b22010-12-23 02:00:266451 // Check we have compatible formats.
6452 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
6453 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
6454 uint32 channels_needed = GLES2Util::GetChannelsForFormat(internal_format);
6455
6456 if ((channels_needed & channels_exist) != channels_needed) {
6457 SetGLError(GL_INVALID_OPERATION, "glCopyTexImage2D: incompatible format");
6458 return;
6459 }
6460
[email protected]a0b78dc2011-11-11 10:43:106461 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
6462 return;
6463 }
6464
[email protected]cadde4a2010-07-31 17:10:436465 CopyRealGLErrorsToWrapper();
[email protected]de26b3c2011-08-03 21:54:276466 ScopedResolvedFrameBufferBinder binder(this, false, true);
[email protected]6e288612010-12-21 20:45:036467 gfx::Size size = GetBoundReadFrameBufferSize();
[email protected]9edc6b22010-12-23 02:00:266468
[email protected]297ca1c2011-06-20 23:08:466469 if (info->IsAttachedToFramebuffer()) {
6470 state_dirty_ = true;
6471 }
6472
[email protected]9edc6b22010-12-23 02:00:266473 // Clip to size to source dimensions
[email protected]6e288612010-12-21 20:45:036474 GLint copyX = 0;
6475 GLint copyY = 0;
6476 GLint copyWidth = 0;
6477 GLint copyHeight = 0;
6478 Clip(x, width, size.width(), &copyX, &copyWidth);
6479 Clip(y, height, size.height(), &copyY, &copyHeight);
6480
6481 if (copyX != x ||
6482 copyY != y ||
6483 copyWidth != width ||
6484 copyHeight != height) {
6485 // some part was clipped so clear the texture.
[email protected]0d6bfdc2011-11-02 01:32:206486 if (!ClearLevel(
6487 info->service_id(), info->target(),
6488 target, level, internal_format, GL_UNSIGNED_BYTE, width, height)) {
6489 SetGLError(GL_OUT_OF_MEMORY, "glCopyTexImage2D: dimensions too big");
[email protected]6e288612010-12-21 20:45:036490 return;
6491 }
[email protected]6e288612010-12-21 20:45:036492 if (copyHeight > 0 && copyWidth > 0) {
6493 GLint dx = copyX - x;
6494 GLint dy = copyY - y;
6495 GLint destX = dx;
6496 GLint destY = dy;
6497 glCopyTexSubImage2D(target, level,
6498 destX, destY, copyX, copyY,
6499 copyWidth, copyHeight);
6500 }
6501 } else {
6502 glCopyTexImage2D(target, level, internal_format,
6503 copyX, copyY, copyWidth, copyHeight, border);
6504 }
[email protected]1002c2d2011-06-28 22:39:046505 GLenum error = PeekGLError();
[email protected]cadde4a2010-07-31 17:10:436506 if (error == GL_NO_ERROR) {
6507 texture_manager()->SetLevelInfo(
[email protected]915a59a12010-09-30 21:29:116508 feature_info_, info, target, level, internal_format, width, height, 1,
[email protected]0d6bfdc2011-11-02 01:32:206509 border, internal_format, GL_UNSIGNED_BYTE, true);
[email protected]cadde4a2010-07-31 17:10:436510 }
6511}
6512
6513void GLES2DecoderImpl::DoCopyTexSubImage2D(
6514 GLenum target,
6515 GLint level,
6516 GLint xoffset,
6517 GLint yoffset,
6518 GLint x,
6519 GLint y,
6520 GLsizei width,
6521 GLsizei height) {
6522 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
6523 if (!info) {
6524 SetGLError(GL_INVALID_OPERATION,
6525 "glCopyTexSubImage2D: unknown texture for target");
6526 return;
6527 }
6528 GLenum type = 0;
6529 GLenum format = 0;
6530 if (!info->GetLevelType(target, level, &type, &format) ||
6531 !info->ValidForTexture(
6532 target, level, xoffset, yoffset, width, height, format, type)) {
6533 SetGLError(GL_INVALID_VALUE,
6534 "glCopyTexSubImage2D: bad dimensions.");
6535 return;
6536 }
[email protected]9edc6b22010-12-23 02:00:266537
6538 // Check we have compatible formats.
6539 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
6540 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
6541 uint32 channels_needed = GLES2Util::GetChannelsForFormat(format);
6542
6543 if ((channels_needed & channels_exist) != channels_needed) {
6544 SetGLError(
6545 GL_INVALID_OPERATION, "glCopyTexSubImage2D: incompatible format");
6546 return;
6547 }
6548
[email protected]a0b78dc2011-11-11 10:43:106549 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
6550 return;
6551 }
6552
[email protected]de26b3c2011-08-03 21:54:276553 ScopedResolvedFrameBufferBinder binder(this, false, true);
[email protected]6e288612010-12-21 20:45:036554 gfx::Size size = GetBoundReadFrameBufferSize();
6555 GLint copyX = 0;
6556 GLint copyY = 0;
6557 GLint copyWidth = 0;
6558 GLint copyHeight = 0;
6559 Clip(x, width, size.width(), &copyX, &copyWidth);
6560 Clip(y, height, size.height(), &copyY, &copyHeight);
[email protected]0d6bfdc2011-11-02 01:32:206561
6562 if (!texture_manager()->ClearTextureLevel(this, info, target, level)) {
6563 SetGLError(GL_OUT_OF_MEMORY, "glCopyTexSubImage2D: dimensions too big");
6564 return;
6565 }
6566
[email protected]6e288612010-12-21 20:45:036567 if (copyX != x ||
6568 copyY != y ||
6569 copyWidth != width ||
6570 copyHeight != height) {
[email protected]0d6bfdc2011-11-02 01:32:206571 // some part was clipped so clear the sub rect.
[email protected]6e288612010-12-21 20:45:036572 uint32 pixels_size = 0;
6573 if (!GLES2Util::ComputeImageDataSize(
6574 width, height, format, type, unpack_alignment_, &pixels_size)) {
6575 SetGLError(GL_INVALID_VALUE, "glCopyTexSubImage2D: dimensions too large");
6576 return;
6577 }
6578 scoped_array<char> zero(new char[pixels_size]);
6579 memset(zero.get(), 0, pixels_size);
6580 glTexSubImage2D(
6581 target, level, xoffset, yoffset, width, height,
6582 format, type, zero.get());
6583 }
[email protected]0d6bfdc2011-11-02 01:32:206584
[email protected]6e288612010-12-21 20:45:036585 if (copyHeight > 0 && copyWidth > 0) {
6586 GLint dx = copyX - x;
6587 GLint dy = copyY - y;
6588 GLint destX = xoffset + dx;
6589 GLint destY = yoffset + dy;
6590 glCopyTexSubImage2D(target, level,
6591 destX, destY, copyX, copyY,
6592 copyWidth, copyHeight);
6593 }
[email protected]cadde4a2010-07-31 17:10:436594}
6595
6596void GLES2DecoderImpl::DoTexSubImage2D(
6597 GLenum target,
6598 GLint level,
6599 GLint xoffset,
6600 GLint yoffset,
6601 GLsizei width,
6602 GLsizei height,
6603 GLenum format,
6604 GLenum type,
6605 const void * data) {
6606 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
6607 if (!info) {
6608 SetGLError(GL_INVALID_OPERATION,
6609 "glTexSubImage2D: unknown texture for target");
6610 return;
6611 }
[email protected]df6cf1ad2011-01-29 01:20:526612 GLenum current_type = 0;
6613 GLenum internal_format = 0;
6614 if (!info->GetLevelType(target, level, &current_type, &internal_format)) {
6615 SetGLError(
6616 GL_INVALID_OPERATION,
6617 "glTexSubImage2D: level does not exist.");
6618 return;
6619 }
6620 if (format != internal_format) {
6621 SetGLError(GL_INVALID_OPERATION,
6622 "glTexSubImage2D: format does not match internal format.");
6623 return;
6624 }
6625 if (type != current_type) {
6626 SetGLError(GL_INVALID_OPERATION,
6627 "glTexSubImage2D: type does not match type of texture.");
6628 return;
6629 }
6630
[email protected]cadde4a2010-07-31 17:10:436631 if (!info->ValidForTexture(
6632 target, level, xoffset, yoffset, width, height, format, type)) {
6633 SetGLError(GL_INVALID_VALUE,
6634 "glTexSubImage2D: bad dimensions.");
6635 return;
6636 }
[email protected]473c01ccb2011-06-07 01:33:306637
6638 // See if we can call glTexImage2D instead since it appears to be faster.
6639 if (teximage2d_faster_than_texsubimage2d_ && xoffset == 0 && yoffset == 0) {
6640 GLsizei tex_width = 0;
6641 GLsizei tex_height = 0;
6642 bool ok = info->GetLevelSize(target, level, &tex_width, &tex_height);
6643 DCHECK(ok);
6644 if (width == tex_width && height == tex_height) {
6645 // NOTE: In OpenGL ES 2.0 border is always zero and format is always the
6646 // same as internal_foramt. If that changes we'll need to look them up.
6647 WrappedTexImage2D(
6648 target, level, format, width, height, 0, format, type, data);
[email protected]0d6bfdc2011-11-02 01:32:206649 texture_manager()->SetLevelCleared(info, target, level);
[email protected]473c01ccb2011-06-07 01:33:306650 return;
6651 }
6652 }
[email protected]0d6bfdc2011-11-02 01:32:206653 if (!texture_manager()->ClearTextureLevel(this, info, target, level)) {
6654 SetGLError(GL_OUT_OF_MEMORY, "glTexSubImage2D: dimensions too big");
6655 return;
6656 }
[email protected]cadde4a2010-07-31 17:10:436657 glTexSubImage2D(
6658 target, level, xoffset, yoffset, width, height, format, type, data);
6659}
6660
[email protected]b493ee622011-04-13 23:52:006661error::Error GLES2DecoderImpl::HandleTexSubImage2D(
6662 uint32 immediate_data_size, const gles2::TexSubImage2D& c) {
[email protected]366ae242011-05-10 02:23:586663 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexSubImage2D");
[email protected]b493ee622011-04-13 23:52:006664 GLboolean internal = static_cast<GLboolean>(c.internal);
6665 if (internal == GL_TRUE && tex_image_2d_failed_)
6666 return error::kNoError;
6667
6668 GLenum target = static_cast<GLenum>(c.target);
6669 GLint level = static_cast<GLint>(c.level);
6670 GLint xoffset = static_cast<GLint>(c.xoffset);
6671 GLint yoffset = static_cast<GLint>(c.yoffset);
6672 GLsizei width = static_cast<GLsizei>(c.width);
6673 GLsizei height = static_cast<GLsizei>(c.height);
6674 GLenum format = static_cast<GLenum>(c.format);
6675 GLenum type = static_cast<GLenum>(c.type);
6676 uint32 data_size;
6677 if (!GLES2Util::ComputeImageDataSize(
6678 width, height, format, type, unpack_alignment_, &data_size)) {
6679 return error::kOutOfBounds;
6680 }
6681 const void* pixels = GetSharedMemoryAs<const void*>(
6682 c.pixels_shm_id, c.pixels_shm_offset, data_size);
6683 if (!validators_->texture_target.IsValid(target)) {
6684 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: target GL_INVALID_ENUM");
6685 return error::kNoError;
6686 }
6687 if (width < 0) {
6688 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: width < 0");
6689 return error::kNoError;
6690 }
6691 if (height < 0) {
6692 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: height < 0");
6693 return error::kNoError;
6694 }
6695 if (!validators_->texture_format.IsValid(format)) {
6696 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: format GL_INVALID_ENUM");
6697 return error::kNoError;
6698 }
6699 if (!validators_->pixel_type.IsValid(type)) {
6700 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: type GL_INVALID_ENUM");
6701 return error::kNoError;
6702 }
6703 if (pixels == NULL) {
6704 return error::kOutOfBounds;
6705 }
6706 DoTexSubImage2D(
6707 target, level, xoffset, yoffset, width, height, format, type, pixels);
6708 return error::kNoError;
6709}
6710
6711error::Error GLES2DecoderImpl::HandleTexSubImage2DImmediate(
6712 uint32 immediate_data_size, const gles2::TexSubImage2DImmediate& c) {
6713 GLboolean internal = static_cast<GLboolean>(c.internal);
6714 if (internal == GL_TRUE && tex_image_2d_failed_)
6715 return error::kNoError;
6716
6717 GLenum target = static_cast<GLenum>(c.target);
6718 GLint level = static_cast<GLint>(c.level);
6719 GLint xoffset = static_cast<GLint>(c.xoffset);
6720 GLint yoffset = static_cast<GLint>(c.yoffset);
6721 GLsizei width = static_cast<GLsizei>(c.width);
6722 GLsizei height = static_cast<GLsizei>(c.height);
6723 GLenum format = static_cast<GLenum>(c.format);
6724 GLenum type = static_cast<GLenum>(c.type);
6725 uint32 data_size;
6726 if (!GLES2Util::ComputeImageDataSize(
6727 width, height, format, type, unpack_alignment_, &data_size)) {
6728 return error::kOutOfBounds;
6729 }
6730 const void* pixels = GetImmediateDataAs<const void*>(
6731 c, data_size, immediate_data_size);
6732 if (!validators_->texture_target.IsValid(target)) {
6733 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: target GL_INVALID_ENUM");
6734 return error::kNoError;
6735 }
6736 if (width < 0) {
6737 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: width < 0");
6738 return error::kNoError;
6739 }
6740 if (height < 0) {
6741 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: height < 0");
6742 return error::kNoError;
6743 }
6744 if (!validators_->texture_format.IsValid(format)) {
6745 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: format GL_INVALID_ENUM");
6746 return error::kNoError;
6747 }
6748 if (!validators_->pixel_type.IsValid(type)) {
6749 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: type GL_INVALID_ENUM");
6750 return error::kNoError;
6751 }
6752 if (pixels == NULL) {
6753 return error::kOutOfBounds;
6754 }
6755 DoTexSubImage2D(
6756 target, level, xoffset, yoffset, width, height, format, type, pixels);
6757 return error::kNoError;
6758}
6759
[email protected]f7a64ee2010-02-01 22:24:146760error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
[email protected]b9849abf2009-11-25 19:13:196761 uint32 immediate_data_size, const gles2::GetVertexAttribPointerv& c) {
[email protected]8bf5a3e2010-01-29 04:21:366762 GLuint index = static_cast<GLuint>(c.index);
6763 GLenum pname = static_cast<GLenum>(c.pname);
[email protected]0bfd9882010-02-05 23:02:256764 typedef gles2::GetVertexAttribPointerv::Result Result;
6765 Result* result = GetSharedMemoryAs<Result*>(
6766 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
[email protected]8bf5a3e2010-01-29 04:21:366767 if (!result) {
[email protected]f7a64ee2010-02-01 22:24:146768 return error::kOutOfBounds;
[email protected]8bf5a3e2010-01-29 04:21:366769 }
[email protected]07d0cc82010-02-17 04:51:406770 // Check that the client initialized the result.
6771 if (result->size != 0) {
6772 return error::kInvalidArguments;
6773 }
[email protected]9438b012010-06-15 22:55:056774 if (!validators_->vertex_pointer.IsValid(pname)) {
[email protected]8eee29c2010-04-29 03:38:296775 SetGLError(GL_INVALID_ENUM,
6776 "glGetVertexAttribPointerv: pname GL_INVALID_ENUM");
[email protected]f7a64ee2010-02-01 22:24:146777 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:366778 }
[email protected]3916c97e2010-02-25 03:20:506779 if (index >= group_->max_vertex_attribs()) {
[email protected]8eee29c2010-04-29 03:38:296780 SetGLError(GL_INVALID_VALUE,
6781 "glGetVertexAttribPointerv: index out of range.");
[email protected]f7a64ee2010-02-01 22:24:146782 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:366783 }
[email protected]0bfd9882010-02-05 23:02:256784 result->SetNumResults(1);
[email protected]f39f4b3f2010-05-12 17:04:086785 *result->GetData() =
6786 vertex_attrib_manager_.GetVertexAttribInfo(index)->offset();
[email protected]f7a64ee2010-02-01 22:24:146787 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326788}
6789
[email protected]f7b85372010-02-03 01:11:376790bool GLES2DecoderImpl::GetUniformSetup(
6791 GLuint program, GLint location,
6792 uint32 shm_id, uint32 shm_offset,
[email protected]939e7362010-05-13 20:49:106793 error::Error* error, GLuint* service_id, void** result_pointer,
6794 GLenum* result_type) {
6795 DCHECK(error);
6796 DCHECK(service_id);
6797 DCHECK(result_pointer);
6798 DCHECK(result_type);
[email protected]f7b85372010-02-03 01:11:376799 *error = error::kNoError;
6800 // Make sure we have enough room for the result on failure.
[email protected]0bfd9882010-02-05 23:02:256801 SizedResult<GLint>* result;
6802 result = GetSharedMemoryAs<SizedResult<GLint>*>(
6803 shm_id, shm_offset, SizedResult<GLint>::ComputeSize(0));
6804 if (!result) {
[email protected]f7b85372010-02-03 01:11:376805 *error = error::kOutOfBounds;
6806 return false;
6807 }
[email protected]0bfd9882010-02-05 23:02:256808 *result_pointer = result;
[email protected]f7b85372010-02-03 01:11:376809 // Set the result size to 0 so the client does not have to check for success.
[email protected]0bfd9882010-02-05 23:02:256810 result->SetNumResults(0);
[email protected]6b8cf1a2010-05-06 16:13:586811 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
6812 program, "glGetUniform");
[email protected]f7b85372010-02-03 01:11:376813 if (!info) {
[email protected]ae51d192010-04-27 00:48:036814 return false;
6815 }
6816 if (!info->IsValid()) {
[email protected]f7b85372010-02-03 01:11:376817 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]8eee29c2010-04-29 03:38:296818 SetGLError(GL_INVALID_OPERATION, "glGetUniform: program not linked");
[email protected]f7b85372010-02-03 01:11:376819 return false;
6820 }
[email protected]ae51d192010-04-27 00:48:036821 *service_id = info->service_id();
[email protected]43c2f1f2011-03-25 18:35:366822 GLint array_index = -1;
6823 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
6824 info->GetUniformInfoByLocation(location, &array_index);
6825 if (!uniform_info) {
[email protected]f7b85372010-02-03 01:11:376826 // No such location.
[email protected]8eee29c2010-04-29 03:38:296827 SetGLError(GL_INVALID_OPERATION, "glGetUniform: unknown location");
[email protected]f7b85372010-02-03 01:11:376828 return false;
6829 }
[email protected]43c2f1f2011-03-25 18:35:366830 GLenum type = uniform_info->type;
[email protected]3916c97e2010-02-25 03:20:506831 GLsizei size = GLES2Util::GetGLDataTypeSizeForUniforms(type);
[email protected]f7b85372010-02-03 01:11:376832 if (size == 0) {
[email protected]8eee29c2010-04-29 03:38:296833 SetGLError(GL_INVALID_OPERATION, "glGetUniform: unknown type");
[email protected]f7b85372010-02-03 01:11:376834 return false;
6835 }
[email protected]0bfd9882010-02-05 23:02:256836 result = GetSharedMemoryAs<SizedResult<GLint>*>(
6837 shm_id, shm_offset, SizedResult<GLint>::ComputeSizeFromBytes(size));
6838 if (!result) {
[email protected]f7b85372010-02-03 01:11:376839 *error = error::kOutOfBounds;
6840 return false;
6841 }
[email protected]0bfd9882010-02-05 23:02:256842 result->size = size;
[email protected]939e7362010-05-13 20:49:106843 *result_type = type;
[email protected]f7b85372010-02-03 01:11:376844 return true;
6845}
6846
[email protected]f7a64ee2010-02-01 22:24:146847error::Error GLES2DecoderImpl::HandleGetUniformiv(
[email protected]b9849abf2009-11-25 19:13:196848 uint32 immediate_data_size, const gles2::GetUniformiv& c) {
[email protected]f7b85372010-02-03 01:11:376849 GLuint program = c.program;
6850 GLint location = c.location;
6851 GLuint service_id;
[email protected]939e7362010-05-13 20:49:106852 GLenum result_type;
[email protected]f7b85372010-02-03 01:11:376853 Error error;
[email protected]0bfd9882010-02-05 23:02:256854 void* result;
[email protected]f7b85372010-02-03 01:11:376855 if (GetUniformSetup(
6856 program, location, c.params_shm_id, c.params_shm_offset,
[email protected]939e7362010-05-13 20:49:106857 &error, &service_id, &result, &result_type)) {
[email protected]0bfd9882010-02-05 23:02:256858 glGetUniformiv(
6859 service_id, location,
6860 static_cast<gles2::GetUniformiv::Result*>(result)->GetData());
[email protected]f7b85372010-02-03 01:11:376861 }
6862 return error;
[email protected]96449d2c2009-11-25 00:01:326863}
6864
[email protected]f7a64ee2010-02-01 22:24:146865error::Error GLES2DecoderImpl::HandleGetUniformfv(
[email protected]b9849abf2009-11-25 19:13:196866 uint32 immediate_data_size, const gles2::GetUniformfv& c) {
[email protected]f7b85372010-02-03 01:11:376867 GLuint program = c.program;
6868 GLint location = c.location;
6869 GLuint service_id;
6870 Error error;
[email protected]0bfd9882010-02-05 23:02:256871 typedef gles2::GetUniformfv::Result Result;
[email protected]939e7362010-05-13 20:49:106872 Result* result;
6873 GLenum result_type;
[email protected]f7b85372010-02-03 01:11:376874 if (GetUniformSetup(
6875 program, location, c.params_shm_id, c.params_shm_offset,
[email protected]939e7362010-05-13 20:49:106876 &error, &service_id, reinterpret_cast<void**>(&result), &result_type)) {
6877 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
6878 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
6879 GLsizei num_values = result->GetNumResults();
6880 scoped_array<GLint> temp(new GLint[num_values]);
6881 glGetUniformiv(service_id, location, temp.get());
6882 GLfloat* dst = result->GetData();
6883 for (GLsizei ii = 0; ii < num_values; ++ii) {
6884 dst[ii] = (temp[ii] != 0);
6885 }
6886 } else {
6887 glGetUniformfv(service_id, location, result->GetData());
6888 }
[email protected]f7b85372010-02-03 01:11:376889 }
6890 return error;
[email protected]96449d2c2009-11-25 00:01:326891}
6892
[email protected]f7a64ee2010-02-01 22:24:146893error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
[email protected]b9849abf2009-11-25 19:13:196894 uint32 immediate_data_size, const gles2::GetShaderPrecisionFormat& c) {
[email protected]0bfd9882010-02-05 23:02:256895 GLenum shader_type = static_cast<GLenum>(c.shadertype);
6896 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
6897 typedef gles2::GetShaderPrecisionFormat::Result Result;
6898 Result* result = GetSharedMemoryAs<Result*>(
6899 c.result_shm_id, c.result_shm_offset, sizeof(*result));
6900 if (!result) {
6901 return error::kOutOfBounds;
6902 }
[email protected]07d0cc82010-02-17 04:51:406903 // Check that the client initialized the result.
6904 if (result->success != 0) {
6905 return error::kInvalidArguments;
6906 }
[email protected]9438b012010-06-15 22:55:056907 if (!validators_->shader_type.IsValid(shader_type)) {
[email protected]8eee29c2010-04-29 03:38:296908 SetGLError(GL_INVALID_ENUM,
6909 "glGetShaderPrecisionFormat: shader_type GL_INVALID_ENUM");
6910 return error::kNoError;
6911 }
[email protected]9438b012010-06-15 22:55:056912 if (!validators_->shader_precision.IsValid(precision_type)) {
[email protected]8eee29c2010-04-29 03:38:296913 SetGLError(GL_INVALID_ENUM,
6914 "glGetShaderPrecisionFormat: precision_type GL_INVALID_ENUM");
6915 return error::kNoError;
6916 }
6917
6918 result->success = 1; // true
6919 switch (precision_type) {
6920 case GL_LOW_INT:
6921 case GL_MEDIUM_INT:
6922 case GL_HIGH_INT:
6923 result->min_range = -31;
6924 result->max_range = 31;
6925 result->precision = 0;
[email protected]4e8a5b122010-05-08 22:00:106926 break;
[email protected]8eee29c2010-04-29 03:38:296927 case GL_LOW_FLOAT:
6928 case GL_MEDIUM_FLOAT:
6929 case GL_HIGH_FLOAT:
6930 result->min_range = -62;
6931 result->max_range = 62;
6932 result->precision = -16;
6933 break;
6934 default:
6935 NOTREACHED();
6936 break;
[email protected]0bfd9882010-02-05 23:02:256937 }
[email protected]f7a64ee2010-02-01 22:24:146938 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326939}
6940
[email protected]f7a64ee2010-02-01 22:24:146941error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
[email protected]b9849abf2009-11-25 19:13:196942 uint32 immediate_data_size, const gles2::GetAttachedShaders& c) {
[email protected]0bfd9882010-02-05 23:02:256943 uint32 result_size = c.result_size;
[email protected]6b8cf1a2010-05-06 16:13:586944 GLuint program = static_cast<GLuint>(c.program);
6945 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
6946 program, "glGetAttachedShaders");
[email protected]ae51d192010-04-27 00:48:036947 if (!info) {
[email protected]0bfd9882010-02-05 23:02:256948 return error::kNoError;
6949 }
6950 typedef gles2::GetAttachedShaders::Result Result;
6951 uint32 max_count = Result::ComputeMaxResults(result_size);
6952 Result* result = GetSharedMemoryAs<Result*>(
6953 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
6954 if (!result) {
6955 return error::kOutOfBounds;
6956 }
[email protected]07d0cc82010-02-17 04:51:406957 // Check that the client initialized the result.
6958 if (result->size != 0) {
6959 return error::kInvalidArguments;
6960 }
[email protected]0bfd9882010-02-05 23:02:256961 GLsizei count = 0;
[email protected]ae51d192010-04-27 00:48:036962 glGetAttachedShaders(
6963 info->service_id(), max_count, &count, result->GetData());
[email protected]0bfd9882010-02-05 23:02:256964 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]ae51d192010-04-27 00:48:036965 if (!shader_manager()->GetClientId(result->GetData()[ii],
6966 &result->GetData()[ii])) {
[email protected]0bfd9882010-02-05 23:02:256967 NOTREACHED();
6968 return error::kGenericError;
6969 }
6970 }
6971 result->SetNumResults(count);
[email protected]f7a64ee2010-02-01 22:24:146972 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326973}
6974
[email protected]f7a64ee2010-02-01 22:24:146975error::Error GLES2DecoderImpl::HandleGetActiveUniform(
[email protected]b9849abf2009-11-25 19:13:196976 uint32 immediate_data_size, const gles2::GetActiveUniform& c) {
[email protected]0bfd9882010-02-05 23:02:256977 GLuint program = c.program;
6978 GLuint index = c.index;
6979 uint32 name_bucket_id = c.name_bucket_id;
[email protected]0bfd9882010-02-05 23:02:256980 typedef gles2::GetActiveUniform::Result Result;
6981 Result* result = GetSharedMemoryAs<Result*>(
6982 c.result_shm_id, c.result_shm_offset, sizeof(*result));
6983 if (!result) {
6984 return error::kOutOfBounds;
6985 }
[email protected]07d0cc82010-02-17 04:51:406986 // Check that the client initialized the result.
6987 if (result->success != 0) {
6988 return error::kInvalidArguments;
6989 }
[email protected]6b8cf1a2010-05-06 16:13:586990 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
6991 program, "glGetActiveUniform");
[email protected]ae51d192010-04-27 00:48:036992 if (!info) {
[email protected]0bfd9882010-02-05 23:02:256993 return error::kNoError;
6994 }
6995 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
6996 info->GetUniformInfo(index);
6997 if (!uniform_info) {
[email protected]8eee29c2010-04-29 03:38:296998 SetGLError(GL_INVALID_VALUE, "glGetActiveUniform: index out of range");
[email protected]0bfd9882010-02-05 23:02:256999 return error::kNoError;
7000 }
7001 result->success = 1; // true.
7002 result->size = uniform_info->size;
7003 result->type = uniform_info->type;
7004 Bucket* bucket = CreateBucket(name_bucket_id);
[email protected]262d7aa2010-12-03 22:07:297005 bucket->SetFromString(uniform_info->name.c_str());
[email protected]f7a64ee2010-02-01 22:24:147006 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:327007}
7008
[email protected]f7a64ee2010-02-01 22:24:147009error::Error GLES2DecoderImpl::HandleGetActiveAttrib(
[email protected]b9849abf2009-11-25 19:13:197010 uint32 immediate_data_size, const gles2::GetActiveAttrib& c) {
[email protected]0bfd9882010-02-05 23:02:257011 GLuint program = c.program;
7012 GLuint index = c.index;
7013 uint32 name_bucket_id = c.name_bucket_id;
[email protected]0bfd9882010-02-05 23:02:257014 typedef gles2::GetActiveAttrib::Result Result;
7015 Result* result = GetSharedMemoryAs<Result*>(
7016 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7017 if (!result) {
7018 return error::kOutOfBounds;
7019 }
[email protected]07d0cc82010-02-17 04:51:407020 // Check that the client initialized the result.
7021 if (result->success != 0) {
7022 return error::kInvalidArguments;
7023 }
[email protected]6b8cf1a2010-05-06 16:13:587024 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
7025 program, "glGetActiveAttrib");
[email protected]ae51d192010-04-27 00:48:037026 if (!info) {
[email protected]0bfd9882010-02-05 23:02:257027 return error::kNoError;
7028 }
7029 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
7030 info->GetAttribInfo(index);
7031 if (!attrib_info) {
[email protected]8eee29c2010-04-29 03:38:297032 SetGLError(GL_INVALID_VALUE, "glGetActiveAttrib: index out of range");
[email protected]0bfd9882010-02-05 23:02:257033 return error::kNoError;
7034 }
7035 result->success = 1; // true.
7036 result->size = attrib_info->size;
7037 result->type = attrib_info->type;
7038 Bucket* bucket = CreateBucket(name_bucket_id);
[email protected]262d7aa2010-12-03 22:07:297039 bucket->SetFromString(attrib_info->name.c_str());
[email protected]f7a64ee2010-02-01 22:24:147040 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:327041}
7042
[email protected]b273e432010-04-12 17:23:587043error::Error GLES2DecoderImpl::HandleShaderBinary(
7044 uint32 immediate_data_size, const gles2::ShaderBinary& c) {
7045#if 1 // No binary shader support.
[email protected]8eee29c2010-04-29 03:38:297046 SetGLError(GL_INVALID_OPERATION, "glShaderBinary: not supported");
[email protected]b273e432010-04-12 17:23:587047 return error::kNoError;
7048#else
7049 GLsizei n = static_cast<GLsizei>(c.n);
7050 if (n < 0) {
[email protected]8eee29c2010-04-29 03:38:297051 SetGLError(GL_INVALID_VALUE, "glShaderBinary: n < 0");
[email protected]b273e432010-04-12 17:23:587052 return error::kNoError;
7053 }
7054 GLsizei length = static_cast<GLsizei>(c.length);
7055 if (length < 0) {
[email protected]8eee29c2010-04-29 03:38:297056 SetGLError(GL_INVALID_VALUE, "glShaderBinary: length < 0");
[email protected]b273e432010-04-12 17:23:587057 return error::kNoError;
7058 }
7059 uint32 data_size;
7060 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
7061 return error::kOutOfBounds;
7062 }
7063 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
7064 c.shaders_shm_id, c.shaders_shm_offset, data_size);
7065 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
7066 const void* binary = GetSharedMemoryAs<const void*>(
7067 c.binary_shm_id, c.binary_shm_offset, length);
7068 if (shaders == NULL || binary == NULL) {
7069 return error::kOutOfBounds;
7070 }
7071 scoped_array<GLuint> service_ids(new GLuint[n]);
7072 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:037073 ShaderManager::ShaderInfo* info = GetShaderInfo(shaders[ii]);
7074 if (!info) {
[email protected]8eee29c2010-04-29 03:38:297075 SetGLError(GL_INVALID_VALUE, "glShaderBinary: unknown shader");
[email protected]b273e432010-04-12 17:23:587076 return error::kNoError;
7077 }
[email protected]ae51d192010-04-27 00:48:037078 service_ids[ii] = info->service_id();
[email protected]b273e432010-04-12 17:23:587079 }
7080 // TODO(gman): call glShaderBinary
7081 return error::kNoError;
7082#endif
7083}
7084
[email protected]6217d392010-03-25 22:08:357085error::Error GLES2DecoderImpl::HandleSwapBuffers(
7086 uint32 immediate_data_size, const gles2::SwapBuffers& c) {
[email protected]64ace852011-05-19 21:49:497087 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
7088 int this_frame_number = frame_number_++;
[email protected]da151512011-11-11 23:27:387089 // TRACE_EVENT for gpu tests:
7090 TRACE_EVENT_INSTANT1("test_gpu", "SwapBuffers",
7091 "GLImpl", static_cast<int>(gfx::GetGLImplementation()));
[email protected]64ace852011-05-19 21:49:497092 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleSwapBuffers",
7093 "offscreen", is_offscreen,
7094 "frame", this_frame_number);
[email protected]6217d392010-03-25 22:08:357095 // If offscreen then don't actually SwapBuffers to the display. Just copy
7096 // the rendered frame to another frame buffer.
[email protected]64ace852011-05-19 21:49:497097 if (is_offscreen) {
[email protected]1fb8c482011-08-31 01:01:537098 if (offscreen_size_ != offscreen_saved_color_texture_->size()) {
7099 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
7100 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
7101 // fix this.
7102 if (needs_mac_nvidia_driver_workaround_) {
7103 offscreen_saved_frame_buffer_->Create();
7104 glFinish();
7105 }
7106
7107 // Allocate the offscreen saved color texture.
7108 DCHECK(offscreen_saved_color_format_);
7109 offscreen_saved_color_texture_->AllocateStorage(
7110 offscreen_size_, offscreen_saved_color_format_);
7111
7112 offscreen_saved_frame_buffer_->AttachRenderTexture(
7113 offscreen_saved_color_texture_.get());
7114 if (offscreen_saved_frame_buffer_->CheckStatus() !=
7115 GL_FRAMEBUFFER_COMPLETE) {
7116 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
7117 << "because offscreen saved FBO was incomplete.";
7118 return error::kLostContext;
7119 }
7120
[email protected]1fb8c482011-08-31 01:01:537121 // Clear the offscreen color texture.
7122 // TODO(piman): Is this still necessary?
7123 {
7124 ScopedFrameBufferBinder binder(this,
7125 offscreen_saved_frame_buffer_->id());
7126 glClearColor(0, 0, 0, 0);
7127 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
7128 glDisable(GL_SCISSOR_TEST);
7129 glClear(GL_COLOR_BUFFER_BIT);
7130 RestoreClearState();
7131 }
7132
7133 UpdateParentTextureInfo();
7134 }
7135
[email protected]6217d392010-03-25 22:08:357136 ScopedGLErrorSuppressor suppressor(this);
7137
[email protected]34ff8b0c2010-10-01 20:06:027138 if (IsOffscreenBufferMultisampled()) {
7139 // For multisampled buffers, bind the resolved frame buffer so that
7140 // callbacks can call ReadPixels or CopyTexImage2D.
[email protected]de26b3c2011-08-03 21:54:277141 ScopedResolvedFrameBufferBinder binder(this, true, false);
[email protected]9d37f062011-11-22 01:24:527142 if (!swap_buffers_callback_.is_null()) {
7143 swap_buffers_callback_.Run();
[email protected]34ff8b0c2010-10-01 20:06:027144 }
[email protected]a96a6022011-11-04 00:58:127145
[email protected]89d6ed02011-04-20 00:23:237146 return error::kNoError;
[email protected]b86b14982010-10-11 18:45:487147 } else {
[email protected]0c8c9d22010-06-25 17:36:397148 ScopedFrameBufferBinder binder(this,
7149 offscreen_target_frame_buffer_->id());
[email protected]c007aa02010-09-02 22:22:407150
[email protected]9a5afa432011-07-22 18:16:397151 if (surface_->IsOffscreen()) {
[email protected]b86b14982010-10-11 18:45:487152 // Copy the target frame buffer to the saved offscreen texture.
7153 offscreen_saved_color_texture_->Copy(
[email protected]3a4d0c52011-06-29 23:11:587154 offscreen_saved_color_texture_->size(),
7155 offscreen_saved_color_format_);
[email protected]b86b14982010-10-11 18:45:487156
[email protected]a3ded6d2010-10-19 06:44:397157 // Ensure the side effects of the copy are visible to the parent
7158 // context. There is no need to do this for ANGLE because it uses a
7159 // single D3D device for all contexts.
[email protected]b86b14982010-10-11 18:45:487160 if (!IsAngle())
7161 glFlush();
7162 }
7163
7164 // Run the callback with |binder| in scope, so that the callback can call
7165 // ReadPixels or CopyTexImage2D.
[email protected]9d37f062011-11-22 01:24:527166 if (!swap_buffers_callback_.is_null()) {
7167 swap_buffers_callback_.Run();
[email protected]b86b14982010-10-11 18:45:487168 }
[email protected]a96a6022011-11-04 00:58:127169
[email protected]89d6ed02011-04-20 00:23:237170 return error::kNoError;
[email protected]0c8c9d22010-06-25 17:36:397171 }
[email protected]6217d392010-03-25 22:08:357172 } else {
[email protected]64ace852011-05-19 21:49:497173 TRACE_EVENT1("gpu", "GLContext::SwapBuffers", "frame", this_frame_number);
[email protected]f62a5ab2011-05-23 20:34:157174 if (!surface_->SwapBuffers()) {
[email protected]d0498742010-09-20 20:27:017175 LOG(ERROR) << "Context lost because SwapBuffers failed.";
[email protected]5259ead82010-09-10 18:02:027176 return error::kLostContext;
[email protected]d0498742010-09-20 20:27:017177 }
[email protected]6217d392010-03-25 22:08:357178 }
7179
[email protected]9d37f062011-11-22 01:24:527180 if (!swap_buffers_callback_.is_null()) {
7181 swap_buffers_callback_.Run();
[email protected]6217d392010-03-25 22:08:357182 }
[email protected]6217d392010-03-25 22:08:357183
[email protected]89d6ed02011-04-20 00:23:237184 return error::kNoError;
[email protected]6217d392010-03-25 22:08:357185}
7186
[email protected]d4239852011-08-12 04:51:227187error::Error GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
7188 uint32 immediate_data_size, const gles2::EnableFeatureCHROMIUM& c) {
[email protected]b1d2dcb2010-05-17 19:24:187189 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:287190 if (!bucket || bucket->size() == 0) {
7191 return error::kInvalidArguments;
7192 }
[email protected]d4239852011-08-12 04:51:227193 typedef gles2::EnableFeatureCHROMIUM::Result Result;
[email protected]b1d2dcb2010-05-17 19:24:187194 Result* result = GetSharedMemoryAs<Result*>(
7195 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7196 if (!result) {
7197 return error::kOutOfBounds;
[email protected]4e8a5b122010-05-08 22:00:107198 }
[email protected]b1d2dcb2010-05-17 19:24:187199 // Check that the client initialized the result.
7200 if (*result != 0) {
7201 return error::kInvalidArguments;
7202 }
7203 std::string feature_str;
7204 if (!bucket->GetAsString(&feature_str)) {
7205 return error::kInvalidArguments;
7206 }
7207
7208 // TODO(gman): make this some kind of table to function pointer thingy.
[email protected]d4239852011-08-12 04:51:227209 if (feature_str.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
[email protected]b1d2dcb2010-05-17 19:24:187210 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
[email protected]d4239852011-08-12 04:51:227211 } else if (feature_str.compare("pepper3d_support_fixed_attribs") == 0) {
[email protected]8fbedc02010-11-18 18:43:407212 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
7213 // TODO(gman): decide how to remove the need for this const_cast.
7214 // I could make validators_ non const but that seems bad as this is the only
7215 // place it is needed. I could make some special friend class of validators
7216 // just to allow this to set them. That seems silly. I could refactor this
7217 // code to use the extension mechanism or the initialization attributes to
7218 // turn this feature on. Given that the only real point of this is to make
7219 // the conformance tests pass and given that there is lots of real work that
7220 // needs to be done it seems like refactoring for one to one of those
7221 // methods is a very low priority.
7222 const_cast<Validators*>(validators_)->vertex_attrib_type.AddValue(GL_FIXED);
[email protected]f0d74742011-10-03 16:31:047223 } else if (feature_str.compare("webgl_enable_glsl_webgl_validation") == 0) {
7224 force_webgl_glsl_validation_ = true;
7225 InitializeShaderTranslator();
[email protected]b1d2dcb2010-05-17 19:24:187226 } else {
7227 return error::kNoError;
7228 }
7229
7230 *result = 1; // true.
7231 return error::kNoError;
[email protected]4e8a5b122010-05-08 22:00:107232}
7233
[email protected]c2f8c8402010-12-06 18:07:247234error::Error GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
7235 uint32 immediate_data_size,
7236 const gles2::GetRequestableExtensionsCHROMIUM& c) {
7237 Bucket* bucket = CreateBucket(c.bucket_id);
7238 scoped_ptr<FeatureInfo> info(new FeatureInfo());
[email protected]e82fb792011-09-22 00:33:297239 info->Initialize(disallowed_features_, NULL);
[email protected]c2f8c8402010-12-06 18:07:247240 bucket->SetFromString(info->extensions().c_str());
7241 return error::kNoError;
7242}
7243
7244error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
7245 uint32 immediate_data_size, const gles2::RequestExtensionCHROMIUM& c) {
7246 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:287247 if (!bucket || bucket->size() == 0) {
7248 return error::kInvalidArguments;
7249 }
[email protected]c2f8c8402010-12-06 18:07:247250 std::string feature_str;
7251 if (!bucket->GetAsString(&feature_str)) {
7252 return error::kInvalidArguments;
7253 }
7254
7255 bool std_derivatives_enabled =
7256 feature_info_->feature_flags().oes_standard_derivatives;
7257 bool webglsl_enabled =
7258 feature_info_->feature_flags().chromium_webglsl;
7259
7260 feature_info_->AddFeatures(feature_str.c_str());
7261
[email protected]f0d74742011-10-03 16:31:047262 bool initialization_required = false;
7263 if (force_webgl_glsl_validation_ && !derivatives_explicitly_enabled_) {
7264 size_t derivatives_offset = feature_str.find(kOESDerivativeExtension);
7265 if (std::string::npos != derivatives_offset) {
7266 derivatives_explicitly_enabled_ = true;
7267 initialization_required = true;
7268 }
7269 }
7270
[email protected]c2f8c8402010-12-06 18:07:247271 // If we just enabled a feature which affects the shader translator,
7272 // we may need to re-initialize it.
7273 if (std_derivatives_enabled !=
7274 feature_info_->feature_flags().oes_standard_derivatives ||
7275 webglsl_enabled !=
[email protected]f0d74742011-10-03 16:31:047276 feature_info_->feature_flags().chromium_webglsl ||
7277 initialization_required) {
[email protected]c2f8c8402010-12-06 18:07:247278 InitializeShaderTranslator();
7279 }
7280
[email protected]302ce6d2011-07-07 23:28:117281 UpdateCapabilities();
7282
[email protected]c2f8c8402010-12-06 18:07:247283 return error::kNoError;
7284}
7285
[email protected]372e0412011-06-28 16:08:567286error::Error GLES2DecoderImpl::HandleGetMultipleIntegervCHROMIUM(
7287 uint32 immediate_data_size, const gles2::GetMultipleIntegervCHROMIUM& c) {
7288 GLuint count = c.count;
7289 uint32 pnames_size;
7290 if (!SafeMultiplyUint32(count, sizeof(GLenum), &pnames_size)) {
7291 return error::kOutOfBounds;
7292 }
7293 const GLenum* pnames = GetSharedMemoryAs<const GLenum*>(
7294 c.pnames_shm_id, c.pnames_shm_offset, pnames_size);
7295 if (pnames == NULL) {
7296 return error::kOutOfBounds;
7297 }
7298
7299 // We have to copy them since we use them twice so the client
7300 // can't change them between the time we validate them and the time we use
7301 // them.
7302 scoped_array<GLenum> enums(new GLenum[count]);
7303 memcpy(enums.get(), pnames, pnames_size);
7304
7305 // Count up the space needed for the result.
7306 uint32 num_results = 0;
7307 for (GLuint ii = 0; ii < count; ++ii) {
7308 uint32 num = util_.GLGetNumValuesReturned(enums[ii]);
7309 if (num == 0) {
7310 SetGLError(GL_INVALID_ENUM,
7311 "glGetMulitpleCHROMIUM: pname GL_INVALID_ENUM");
7312 return error::kNoError;
7313 }
7314 // Num will never be more than 4.
7315 DCHECK_LE(num, 4u);
7316 if (!SafeAdd(num_results, num, &num_results)) {
7317 return error::kOutOfBounds;
7318 }
7319 }
7320
7321 uint32 result_size = 0;
7322 if (!SafeMultiplyUint32(num_results, sizeof(GLint), &result_size)) {
7323 return error::kOutOfBounds;
7324 }
7325
7326 if (result_size != static_cast<uint32>(c.size)) {
7327 SetGLError(GL_INVALID_VALUE,
7328 "glGetMulitpleCHROMIUM: bad size GL_INVALID_VALUE");
7329 return error::kNoError;
7330 }
7331
7332 GLint* results = GetSharedMemoryAs<GLint*>(
7333 c.results_shm_id, c.results_shm_offset, result_size);
7334 if (results == NULL) {
7335 return error::kOutOfBounds;
7336 }
7337
7338 // Check the results have been cleared in case the context was lost.
7339 for (uint32 ii = 0; ii < num_results; ++ii) {
7340 if (results[ii]) {
7341 return error::kInvalidArguments;
7342 }
7343 }
7344
7345 // Get each result.
7346 GLint* start = results;
7347 for (GLuint ii = 0; ii < count; ++ii) {
7348 GLsizei num_written = 0;
7349 if (!GetHelper(enums[ii], results, &num_written)) {
7350 glGetIntegerv(enums[ii], results);
7351 }
7352 results += num_written;
7353 }
7354
7355 // Just to verify. Should this be a DCHECK?
7356 if (static_cast<uint32>(results - start) != num_results) {
7357 return error::kOutOfBounds;
7358 }
7359
7360 return error::kNoError;
7361}
7362
[email protected]2318d342011-07-11 22:27:427363error::Error GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
7364 uint32 immediate_data_size, const gles2::GetProgramInfoCHROMIUM& c) {
7365 GLuint program = static_cast<GLuint>(c.program);
7366 uint32 bucket_id = c.bucket_id;
7367 Bucket* bucket = CreateBucket(bucket_id);
7368 bucket->SetSize(sizeof(ProgramInfoHeader)); // in case we fail.
7369 ProgramManager::ProgramInfo* info = NULL;
[email protected]9a14ae612011-08-08 17:51:467370 info = GetProgramInfo(program);
7371 if (!info || !info->IsValid()) {
7372 return error::kNoError;
[email protected]2318d342011-07-11 22:27:427373 }
7374 info->GetProgramInfo(bucket);
7375 return error::kNoError;
7376}
7377
[email protected]38d139d2011-07-14 00:38:437378error::ContextLostReason GLES2DecoderImpl::GetContextLostReason() {
7379 switch (reset_status_) {
7380 case GL_NO_ERROR:
7381 // TODO(kbr): improve the precision of the error code in this case.
7382 // Consider delegating to context for error code if MakeCurrent fails.
7383 return error::kUnknown;
7384 case GL_GUILTY_CONTEXT_RESET_ARB:
7385 return error::kGuilty;
7386 case GL_INNOCENT_CONTEXT_RESET_ARB:
7387 return error::kInnocent;
7388 case GL_UNKNOWN_CONTEXT_RESET_ARB:
7389 return error::kUnknown;
7390 }
7391
7392 NOTREACHED();
7393 return error::kUnknown;
7394}
7395
7396bool GLES2DecoderImpl::WasContextLost() {
7397 if (context_->WasAllocatedUsingARBRobustness() && has_arb_robustness_) {
7398 GLenum status = glGetGraphicsResetStatusARB();
7399 if (status != GL_NO_ERROR) {
7400 // The graphics card was reset. Signal a lost context to the application.
7401 reset_status_ = status;
7402 LOG(ERROR) << (surface_->IsOffscreen() ? "Offscreen" : "Onscreen")
7403 << " context lost via ARB_robustness. Reset status = 0x"
7404 << std::hex << status << std::dec;
7405 return true;
7406 }
7407 }
7408 return false;
7409}
7410
[email protected]b0af4f52011-09-28 22:04:427411error::Error GLES2DecoderImpl::HandleCreateStreamTextureCHROMIUM(
7412 uint32 immediate_data_size,
7413 const gles2::CreateStreamTextureCHROMIUM& c) {
7414 if (!feature_info_->feature_flags().chromium_stream_texture) {
7415 SetGLError(GL_INVALID_OPERATION,
7416 "glOpenStreamTextureCHROMIUM: "
7417 "not supported.");
7418 return error::kNoError;
7419 }
7420
7421 uint32 client_id = c.client_id;
7422 typedef gles2::CreateStreamTextureCHROMIUM::Result Result;
7423 Result* result = GetSharedMemoryAs<Result*>(
7424 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7425
7426 *result = GL_ZERO;
7427 TextureManager::TextureInfo* info =
7428 texture_manager()->GetTextureInfo(client_id);
7429 if (!info) {
7430 SetGLError(GL_INVALID_VALUE,
7431 "glCreateStreamTextureCHROMIUM: "
7432 "bad texture id.");
7433 return error::kNoError;
7434 }
7435
7436 if (info->IsStreamTexture()) {
7437 SetGLError(GL_INVALID_OPERATION,
7438 "glCreateStreamTextureCHROMIUM: "
7439 "is already a stream texture.");
7440 return error::kNoError;
7441 }
7442
7443 if (info->target() && info->target() != GL_TEXTURE_EXTERNAL_OES) {
7444 SetGLError(GL_INVALID_OPERATION,
7445 "glCreateStreamTextureCHROMIUM: "
7446 "is already bound to incompatible target.");
7447 return error::kNoError;
7448 }
7449
7450 if (!stream_texture_manager_)
7451 return error::kInvalidArguments;
7452
7453 GLuint object_id = stream_texture_manager_->CreateStreamTexture(
7454 info->service_id(), client_id);
7455
7456 if (object_id) {
7457 info->SetStreamTexture(true);
7458 } else {
7459 SetGLError(GL_OUT_OF_MEMORY,
7460 "glCreateStreamTextureCHROMIUM: "
7461 "failed to create platform texture.");
7462 }
7463
7464 *result = object_id;
7465 return error::kNoError;
7466}
7467
7468error::Error GLES2DecoderImpl::HandleDestroyStreamTextureCHROMIUM(
7469 uint32 immediate_data_size,
7470 const gles2::DestroyStreamTextureCHROMIUM& c) {
7471 GLuint client_id = c.texture;
7472 TextureManager::TextureInfo* info =
7473 texture_manager()->GetTextureInfo(client_id);
7474 if (info && info->IsStreamTexture()) {
7475 if (!stream_texture_manager_)
7476 return error::kInvalidArguments;
7477
7478 stream_texture_manager_->DestroyStreamTexture(info->service_id());
7479 info->SetStreamTexture(false);
7480 texture_manager()->SetInfoTarget(feature_info_, info, 0);
7481 } else {
7482 SetGLError(GL_INVALID_VALUE,
7483 "glDestroyStreamTextureCHROMIUM: bad texture id.");
7484 }
7485
7486 return error::kNoError;
7487}
7488
[email protected]96449d2c2009-11-25 00:01:327489// Include the auto-generated part of this file. We split this because it means
7490// we can easily edit the non-auto generated parts right here in this file
7491// instead of having to edit some template or the code generator.
7492#include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
7493
7494} // namespace gles2
[email protected]a7a27ace2009-12-12 00:11:257495} // namespace gpu