Reland r209673: "gpu: Propagate lost context signal to all contexts"
[chromium-blink-merge.git] / gpu / command_buffer / service / gles2_cmd_decoder.cc
blobafb6b149f7cfd3e5620d8463a157975f0acacf10
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
7 #include <stdio.h>
9 #include <algorithm>
10 #include <list>
11 #include <map>
12 #include <stack>
13 #include <string>
14 #include <vector>
16 #include "base/at_exit.h"
17 #include "base/atomicops.h"
18 #include "base/bind.h"
19 #include "base/command_line.h"
20 #include "base/debug/trace_event.h"
21 #if defined(OS_MACOSX)
22 #include "base/mac/scoped_cftyperef.h"
23 #endif
24 #include "base/memory/scoped_ptr.h"
25 #include "base/strings/string_number_conversions.h"
26 #include "build/build_config.h"
27 #define GLES2_GPU_SERVICE 1
28 #include "gpu/command_buffer/common/debug_marker_manager.h"
29 #include "gpu/command_buffer/common/gles2_cmd_format.h"
30 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
31 #include "gpu/command_buffer/common/id_allocator.h"
32 #include "gpu/command_buffer/common/mailbox.h"
33 #include "gpu/command_buffer/service/async_pixel_transfer_delegate.h"
34 #include "gpu/command_buffer/service/async_pixel_transfer_manager.h"
35 #include "gpu/command_buffer/service/buffer_manager.h"
36 #include "gpu/command_buffer/service/cmd_buffer_engine.h"
37 #include "gpu/command_buffer/service/context_group.h"
38 #include "gpu/command_buffer/service/context_state.h"
39 #include "gpu/command_buffer/service/error_state.h"
40 #include "gpu/command_buffer/service/feature_info.h"
41 #include "gpu/command_buffer/service/framebuffer_manager.h"
42 #include "gpu/command_buffer/service/gl_utils.h"
43 #include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h"
44 #include "gpu/command_buffer/service/gles2_cmd_validation.h"
45 #include "gpu/command_buffer/service/gpu_switches.h"
46 #include "gpu/command_buffer/service/gpu_tracer.h"
47 #include "gpu/command_buffer/service/image_manager.h"
48 #include "gpu/command_buffer/service/mailbox_manager.h"
49 #include "gpu/command_buffer/service/memory_tracking.h"
50 #include "gpu/command_buffer/service/program_manager.h"
51 #include "gpu/command_buffer/service/query_manager.h"
52 #include "gpu/command_buffer/service/renderbuffer_manager.h"
53 #include "gpu/command_buffer/service/shader_manager.h"
54 #include "gpu/command_buffer/service/shader_translator.h"
55 #include "gpu/command_buffer/service/shader_translator_cache.h"
56 #include "gpu/command_buffer/service/stream_texture.h"
57 #include "gpu/command_buffer/service/stream_texture_manager.h"
58 #include "gpu/command_buffer/service/texture_manager.h"
59 #include "gpu/command_buffer/service/vertex_array_manager.h"
60 #include "gpu/command_buffer/service/vertex_attrib_manager.h"
61 #include "ui/gl/gl_bindings.h"
62 #include "ui/gl/gl_fence.h"
63 #include "ui/gl/gl_image.h"
64 #include "ui/gl/gl_implementation.h"
65 #include "ui/gl/gl_surface.h"
67 #if defined(OS_MACOSX)
68 #include "ui/gl/io_surface_support_mac.h"
69 #endif
71 // TODO(zmo): we can't include "City.h" due to type def conflicts.
72 extern uint64 CityHash64(const char*, size_t);
74 namespace gpu {
75 namespace gles2 {
77 namespace {
79 static const char kOESDerivativeExtension[] = "GL_OES_standard_derivatives";
80 static const char kEXTFragDepthExtension[] = "GL_EXT_frag_depth";
81 static const char kEXTDrawBuffersExtension[] = "GL_EXT_draw_buffers";
83 #if !defined(ANGLE_SH_VERSION) || ANGLE_SH_VERSION < 108
84 khronos_uint64_t CityHashForAngle(const char* name, unsigned int len) {
85 return static_cast<khronos_uint64_t>(
86 CityHash64(name, static_cast<size_t>(len)));
88 #endif
90 static bool PrecisionMeetsSpecForHighpFloat(GLint rangeMin,
91 GLint rangeMax,
92 GLint precision) {
93 return (rangeMin >= 62) && (rangeMax >= 62) && (precision >= 16);
96 static void GetShaderPrecisionFormatImpl(GLenum shader_type,
97 GLenum precision_type,
98 GLint *range, GLint *precision) {
99 switch (precision_type) {
100 case GL_LOW_INT:
101 case GL_MEDIUM_INT:
102 case GL_HIGH_INT:
103 // These values are for a 32-bit twos-complement integer format.
104 range[0] = 31;
105 range[1] = 30;
106 *precision = 0;
107 break;
108 case GL_LOW_FLOAT:
109 case GL_MEDIUM_FLOAT:
110 case GL_HIGH_FLOAT:
111 // These values are for an IEEE single-precision floating-point format.
112 range[0] = 127;
113 range[1] = 127;
114 *precision = 23;
115 break;
116 default:
117 NOTREACHED();
118 break;
121 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
122 gfx::g_driver_gl.fn.glGetShaderPrecisionFormatFn) {
123 // This function is sometimes defined even though it's really just
124 // a stub, so we need to set range and precision as if it weren't
125 // defined before calling it.
126 // On Mac OS with some GPUs, calling this generates a
127 // GL_INVALID_OPERATION error. Avoid calling it on non-GLES2
128 // platforms.
129 glGetShaderPrecisionFormat(shader_type, precision_type,
130 range, precision);
132 // TODO(brianderson): Make the following official workarounds.
134 // Some drivers have bugs where they report the ranges as a negative number.
135 // Taking the absolute value here shouldn't hurt because negative numbers
136 // aren't expected anyway.
137 range[0] = abs(range[0]);
138 range[1] = abs(range[1]);
140 // If the driver reports a precision for highp float that isn't actually
141 // highp, don't pretend like it's supported because shader compilation will
142 // fail anyway.
143 if (precision_type == GL_HIGH_FLOAT &&
144 !PrecisionMeetsSpecForHighpFloat(range[0], range[1], *precision)) {
145 range[0] = 0;
146 range[1] = 0;
147 *precision = 0;
152 } // namespace
154 class GLES2DecoderImpl;
156 // Local versions of the SET_GL_ERROR macros
157 #define LOCAL_SET_GL_ERROR(error, function_name, msg) \
158 ERRORSTATE_SET_GL_ERROR(state_.GetErrorState(), error, function_name, msg)
159 #define LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, value, label) \
160 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(state_.GetErrorState(), \
161 function_name, value, label)
162 #define LOCAL_SET_GL_ERROR_INVALID_PARAM(error, function_name, pname) \
163 ERRORSTATE_SET_GL_ERROR_INVALID_PARAM(state_.GetErrorState(), error, \
164 function_name, pname)
165 #define LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name) \
166 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(state_.GetErrorState(), \
167 function_name)
168 #define LOCAL_PEEK_GL_ERROR(function_name) \
169 ERRORSTATE_PEEK_GL_ERROR(state_.GetErrorState(), function_name)
170 #define LOCAL_CLEAR_REAL_GL_ERRORS(function_name) \
171 ERRORSTATE_CLEAR_REAL_GL_ERRORS(state_.GetErrorState(), function_name)
172 #define LOCAL_PERFORMANCE_WARNING(msg) \
173 PerformanceWarning(__FILE__, __LINE__, msg)
174 #define LOCAL_RENDER_WARNING(msg) \
175 RenderWarning(__FILE__, __LINE__, msg)
177 // Check that certain assumptions the code makes are true. There are places in
178 // the code where shared memory is passed direclty to GL. Example, glUniformiv,
179 // glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
180 // a few others) are 32bits. If they are not 32bits the code will have to change
181 // to call those GL functions with service side memory and then copy the results
182 // to shared memory, converting the sizes.
183 COMPILE_ASSERT(sizeof(GLint) == sizeof(uint32), // NOLINT
184 GLint_not_same_size_as_uint32);
185 COMPILE_ASSERT(sizeof(GLsizei) == sizeof(uint32), // NOLINT
186 GLint_not_same_size_as_uint32);
187 COMPILE_ASSERT(sizeof(GLfloat) == sizeof(float), // NOLINT
188 GLfloat_not_same_size_as_float);
190 // TODO(kbr): the use of this anonymous namespace core dumps the
191 // linker on Mac OS X 10.6 when the symbol ordering file is used
192 // namespace {
194 // Returns the address of the first byte after a struct.
195 template <typename T>
196 const void* AddressAfterStruct(const T& pod) {
197 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
200 // Returns the address of the frst byte after the struct or NULL if size >
201 // immediate_data_size.
202 template <typename RETURN_TYPE, typename COMMAND_TYPE>
203 RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod,
204 uint32 size,
205 uint32 immediate_data_size) {
206 return (size <= immediate_data_size) ?
207 static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))) :
208 NULL;
211 // Computes the data size for certain gl commands like glUniform.
212 bool ComputeDataSize(
213 GLuint count,
214 size_t size,
215 unsigned int elements_per_unit,
216 uint32* dst) {
217 uint32 value;
218 if (!SafeMultiplyUint32(count, size, &value)) {
219 return false;
221 if (!SafeMultiplyUint32(value, elements_per_unit, &value)) {
222 return false;
224 *dst = value;
225 return true;
228 // A struct to hold info about each command.
229 struct CommandInfo {
230 int arg_flags; // How to handle the arguments for this command
231 int arg_count; // How many arguments are expected for this command.
234 // A table of CommandInfo for all the commands.
235 const CommandInfo g_command_info[] = {
236 #define GLES2_CMD_OP(name) { \
237 cmds::name::kArgFlags, \
238 sizeof(cmds::name) / sizeof(CommandBufferEntry) - 1, }, /* NOLINT */ \
240 GLES2_COMMAND_LIST(GLES2_CMD_OP)
242 #undef GLES2_CMD_OP
245 // Return true if a character belongs to the ASCII subset as defined in
246 // GLSL ES 1.0 spec section 3.1.
247 static bool CharacterIsValidForGLES(unsigned char c) {
248 // Printing characters are valid except " $ ` @ \ ' DEL.
249 if (c >= 32 && c <= 126 &&
250 c != '"' &&
251 c != '$' &&
252 c != '`' &&
253 c != '@' &&
254 c != '\\' &&
255 c != '\'') {
256 return true;
258 // Horizontal tab, line feed, vertical tab, form feed, carriage return
259 // are also valid.
260 if (c >= 9 && c <= 13) {
261 return true;
264 return false;
267 static bool StringIsValidForGLES(const char* str) {
268 for (; *str; ++str) {
269 if (!CharacterIsValidForGLES(*str)) {
270 return false;
273 return true;
276 // Wrapper for glEnable/glDisable that doesn't suck.
277 static void EnableDisable(GLenum pname, bool enable) {
278 if (enable) {
279 glEnable(pname);
280 } else {
281 glDisable(pname);
285 // This class prevents any GL errors that occur when it is in scope from
286 // being reported to the client.
287 class ScopedGLErrorSuppressor {
288 public:
289 explicit ScopedGLErrorSuppressor(
290 const char* function_name, GLES2DecoderImpl* decoder);
291 ~ScopedGLErrorSuppressor();
292 private:
293 const char* function_name_;
294 GLES2DecoderImpl* decoder_;
295 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor);
298 // Temporarily changes a decoder's bound 2D texture and restore it when this
299 // object goes out of scope. Also temporarily switches to using active texture
300 // unit zero in case the client has changed that to something invalid.
301 class ScopedTexture2DBinder {
302 public:
303 ScopedTexture2DBinder(GLES2DecoderImpl* decoder, GLuint id);
304 ~ScopedTexture2DBinder();
306 private:
307 GLES2DecoderImpl* decoder_;
308 DISALLOW_COPY_AND_ASSIGN(ScopedTexture2DBinder);
311 // Temporarily changes a decoder's bound render buffer and restore it when this
312 // object goes out of scope.
313 class ScopedRenderBufferBinder {
314 public:
315 ScopedRenderBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
316 ~ScopedRenderBufferBinder();
318 private:
319 GLES2DecoderImpl* decoder_;
320 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder);
323 // Temporarily changes a decoder's bound frame buffer and restore it when this
324 // object goes out of scope.
325 class ScopedFrameBufferBinder {
326 public:
327 ScopedFrameBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
328 ~ScopedFrameBufferBinder();
330 private:
331 GLES2DecoderImpl* decoder_;
332 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder);
335 // Temporarily changes a decoder's bound frame buffer to a resolved version of
336 // the multisampled offscreen render buffer if that buffer is multisampled, and,
337 // if it is bound or enforce_internal_framebuffer is true. If internal is
338 // true, the resolved framebuffer is not visible to the parent.
339 class ScopedResolvedFrameBufferBinder {
340 public:
341 ScopedResolvedFrameBufferBinder(GLES2DecoderImpl* decoder,
342 bool enforce_internal_framebuffer,
343 bool internal);
344 ~ScopedResolvedFrameBufferBinder();
346 private:
347 GLES2DecoderImpl* decoder_;
348 bool resolve_and_bind_;
349 DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder);
352 // This class records texture upload time when in scope.
353 class ScopedTextureUploadTimer {
354 public:
355 explicit ScopedTextureUploadTimer(GLES2DecoderImpl* decoder);
356 ~ScopedTextureUploadTimer();
358 private:
359 GLES2DecoderImpl* decoder_;
360 base::TimeTicks begin_time_;
361 DISALLOW_COPY_AND_ASSIGN(ScopedTextureUploadTimer);
364 // Encapsulates an OpenGL texture.
365 class BackTexture {
366 public:
367 explicit BackTexture(GLES2DecoderImpl* decoder);
368 ~BackTexture();
370 // Create a new render texture.
371 void Create();
373 // Set the initial size and format of a render texture or resize it.
374 bool AllocateStorage(const gfx::Size& size, GLenum format, bool zero);
376 // Copy the contents of the currently bound frame buffer.
377 void Copy(const gfx::Size& size, GLenum format);
379 // Destroy the render texture. This must be explicitly called before
380 // destroying this object.
381 void Destroy();
383 // Invalidate the texture. This can be used when a context is lost and it is
384 // not possible to make it current in order to free the resource.
385 void Invalidate();
387 GLuint id() const {
388 return id_;
391 gfx::Size size() const {
392 return size_;
395 size_t estimated_size() const {
396 return memory_tracker_.GetMemRepresented();
399 private:
400 GLES2DecoderImpl* decoder_;
401 MemoryTypeTracker memory_tracker_;
402 size_t bytes_allocated_;
403 GLuint id_;
404 gfx::Size size_;
405 DISALLOW_COPY_AND_ASSIGN(BackTexture);
408 // Encapsulates an OpenGL render buffer of any format.
409 class BackRenderbuffer {
410 public:
411 explicit BackRenderbuffer(GLES2DecoderImpl* decoder);
412 ~BackRenderbuffer();
414 // Create a new render buffer.
415 void Create();
417 // Set the initial size and format of a render buffer or resize it.
418 bool AllocateStorage(const gfx::Size& size, GLenum format, GLsizei samples);
420 // Destroy the render buffer. This must be explicitly called before destroying
421 // this object.
422 void Destroy();
424 // Invalidate the render buffer. This can be used when a context is lost and
425 // it is not possible to make it current in order to free the resource.
426 void Invalidate();
428 GLuint id() const {
429 return id_;
432 size_t estimated_size() const {
433 return memory_tracker_.GetMemRepresented();
436 private:
437 GLES2DecoderImpl* decoder_;
438 MemoryTypeTracker memory_tracker_;
439 size_t bytes_allocated_;
440 GLuint id_;
441 DISALLOW_COPY_AND_ASSIGN(BackRenderbuffer);
444 // Encapsulates an OpenGL frame buffer.
445 class BackFramebuffer {
446 public:
447 explicit BackFramebuffer(GLES2DecoderImpl* decoder);
448 ~BackFramebuffer();
450 // Create a new frame buffer.
451 void Create();
453 // Attach a color render buffer to a frame buffer.
454 void AttachRenderTexture(BackTexture* texture);
456 // Attach a render buffer to a frame buffer. Note that this unbinds any
457 // currently bound frame buffer.
458 void AttachRenderBuffer(GLenum target, BackRenderbuffer* render_buffer);
460 // Destroy the frame buffer. This must be explicitly called before destroying
461 // this object.
462 void Destroy();
464 // Invalidate the frame buffer. This can be used when a context is lost and it
465 // is not possible to make it current in order to free the resource.
466 void Invalidate();
468 // See glCheckFramebufferStatusEXT.
469 GLenum CheckStatus();
471 GLuint id() const {
472 return id_;
475 private:
476 GLES2DecoderImpl* decoder_;
477 GLuint id_;
478 DISALLOW_COPY_AND_ASSIGN(BackFramebuffer);
481 struct FenceCallback {
482 explicit FenceCallback()
483 : fence(gfx::GLFence::Create()) {
484 DCHECK(fence);
486 void AddCallback(base::Closure cb) {
487 callbacks.push_back(cb);
489 std::vector<base::Closure> callbacks;
490 scoped_ptr<gfx::GLFence> fence;
494 // } // anonymous namespace.
496 bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id,
497 uint32* service_texture_id) {
498 return false;
501 GLES2Decoder::GLES2Decoder()
502 : initialized_(false),
503 debug_(false),
504 log_commands_(false) {
507 GLES2Decoder::~GLES2Decoder() {
510 bool GLES2Decoder::testing_force_is_angle_;
512 void GLES2Decoder::set_testing_force_is_angle(bool force) {
513 testing_force_is_angle_ = force;
516 bool GLES2Decoder::IsAngle() {
517 #if defined(OS_WIN)
518 return testing_force_is_angle_ ||
519 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2;
520 #else
521 return testing_force_is_angle_;
522 #endif
525 // This class implements GLES2Decoder so we don't have to expose all the GLES2
526 // cmd stuff to outside this class.
527 class GLES2DecoderImpl : public GLES2Decoder {
528 public:
529 // Used by PrepForSetUniformByLocation to validate types.
530 struct BaseUniformInfo {
531 const GLenum* const valid_types;
532 size_t num_valid_types;
535 explicit GLES2DecoderImpl(ContextGroup* group);
536 virtual ~GLES2DecoderImpl();
538 // Overridden from AsyncAPIInterface.
539 virtual Error DoCommand(unsigned int command,
540 unsigned int arg_count,
541 const void* args) OVERRIDE;
543 // Overridden from AsyncAPIInterface.
544 virtual const char* GetCommandName(unsigned int command_id) const OVERRIDE;
546 // Overridden from GLES2Decoder.
547 virtual bool Initialize(const scoped_refptr<gfx::GLSurface>& surface,
548 const scoped_refptr<gfx::GLContext>& context,
549 bool offscreen,
550 const gfx::Size& size,
551 const DisallowedFeatures& disallowed_features,
552 const char* allowed_extensions,
553 const std::vector<int32>& attribs) OVERRIDE;
554 virtual void Destroy(bool have_context) OVERRIDE;
555 virtual void SetSurface(
556 const scoped_refptr<gfx::GLSurface>& surface) OVERRIDE;
557 virtual bool ProduceFrontBuffer(const Mailbox& mailbox) OVERRIDE;
558 virtual bool ResizeOffscreenFrameBuffer(const gfx::Size& size) OVERRIDE;
559 void UpdateParentTextureInfo();
560 virtual bool MakeCurrent() OVERRIDE;
561 virtual void ReleaseCurrent() OVERRIDE;
562 virtual GLES2Util* GetGLES2Util() OVERRIDE { return &util_; }
563 virtual gfx::GLContext* GetGLContext() OVERRIDE { return context_.get(); }
564 virtual ContextGroup* GetContextGroup() OVERRIDE { return group_.get(); }
565 virtual void RestoreState() const OVERRIDE;
567 virtual void RestoreActiveTexture() const OVERRIDE {
568 state_.RestoreActiveTexture();
570 virtual void RestoreAllTextureUnitBindings() const OVERRIDE {
571 state_.RestoreAllTextureUnitBindings();
573 virtual void RestoreAttribute(unsigned index) const OVERRIDE {
574 state_.RestoreAttribute(index);
576 virtual void RestoreBufferBindings() const OVERRIDE {
577 state_.RestoreBufferBindings();
579 virtual void RestoreGlobalState() const OVERRIDE {
580 state_.RestoreGlobalState();
582 virtual void RestoreProgramBindings() const OVERRIDE {
583 state_.RestoreProgramBindings();
585 virtual void RestoreRenderbufferBindings() const OVERRIDE {
586 state_.RestoreRenderbufferBindings();
588 virtual void RestoreTextureUnitBindings(unsigned unit) const OVERRIDE {
589 state_.RestoreTextureUnitBindings(unit);
591 virtual void RestoreFramebufferBindings() const OVERRIDE;
592 virtual void RestoreTextureState(unsigned service_id) const OVERRIDE;
594 virtual QueryManager* GetQueryManager() OVERRIDE {
595 return query_manager_.get();
597 virtual VertexArrayManager* GetVertexArrayManager() OVERRIDE {
598 return vertex_array_manager_.get();
600 virtual bool ProcessPendingQueries() OVERRIDE;
601 virtual bool HasMoreIdleWork() OVERRIDE;
602 virtual void PerformIdleWork() OVERRIDE;
604 virtual void WaitForReadPixels(base::Closure callback) OVERRIDE;
606 virtual void SetResizeCallback(
607 const base::Callback<void(gfx::Size, float)>& callback) OVERRIDE;
609 virtual Logger* GetLogger() OVERRIDE;
610 virtual ErrorState* GetErrorState() OVERRIDE;
612 virtual void SetShaderCacheCallback(
613 const ShaderCacheCallback& callback) OVERRIDE;
614 virtual void SetWaitSyncPointCallback(
615 const WaitSyncPointCallback& callback) OVERRIDE;
617 virtual AsyncPixelTransferManager*
618 GetAsyncPixelTransferManager() OVERRIDE;
619 virtual void ResetAsyncPixelTransferManagerForTest() OVERRIDE;
620 virtual void SetAsyncPixelTransferManagerForTest(
621 AsyncPixelTransferManager* manager) OVERRIDE;
622 void ProcessFinishedAsyncTransfers();
624 virtual bool GetServiceTextureId(uint32 client_texture_id,
625 uint32* service_texture_id) OVERRIDE;
627 virtual uint32 GetTextureUploadCount() OVERRIDE;
628 virtual base::TimeDelta GetTotalTextureUploadTime() OVERRIDE;
629 virtual base::TimeDelta GetTotalProcessingCommandsTime() OVERRIDE;
630 virtual void AddProcessingCommandsTime(base::TimeDelta) OVERRIDE;
632 // Restores the current state to the user's settings.
633 void RestoreCurrentFramebufferBindings();
634 void RestoreCurrentRenderbufferBindings();
635 void RestoreCurrentTexture2DBindings();
637 // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
638 void ApplyDirtyState();
640 // These check the state of the currently bound framebuffer or the
641 // backbuffer if no framebuffer is bound.
642 // If all_draw_buffers is false, only check with COLOR_ATTACHMENT0, otherwise
643 // check with all attached and enabled color attachments.
644 bool BoundFramebufferHasColorAttachmentWithAlpha(bool all_draw_buffers);
645 bool BoundFramebufferHasDepthAttachment();
646 bool BoundFramebufferHasStencilAttachment();
648 virtual error::ContextLostReason GetContextLostReason() OVERRIDE;
650 private:
651 friend class ScopedFrameBufferBinder;
652 friend class ScopedGLErrorSuppressor;
653 friend class ScopedResolvedFrameBufferBinder;
654 friend class ScopedTextureUploadTimer;
655 friend class BackTexture;
656 friend class BackRenderbuffer;
657 friend class BackFramebuffer;
659 // Initialize or re-initialize the shader translator.
660 bool InitializeShaderTranslator();
662 void UpdateCapabilities();
664 // Helpers for the glGen and glDelete functions.
665 bool GenTexturesHelper(GLsizei n, const GLuint* client_ids);
666 void DeleteTexturesHelper(GLsizei n, const GLuint* client_ids);
667 bool GenBuffersHelper(GLsizei n, const GLuint* client_ids);
668 void DeleteBuffersHelper(GLsizei n, const GLuint* client_ids);
669 bool GenFramebuffersHelper(GLsizei n, const GLuint* client_ids);
670 void DeleteFramebuffersHelper(GLsizei n, const GLuint* client_ids);
671 bool GenRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
672 void DeleteRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
673 bool GenQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
674 void DeleteQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
675 bool GenVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
676 void DeleteVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
678 // Workarounds
679 void OnFboChanged() const;
680 void OnUseFramebuffer() const;
682 // TODO(gman): Cache these pointers?
683 BufferManager* buffer_manager() {
684 return group_->buffer_manager();
687 RenderbufferManager* renderbuffer_manager() {
688 return group_->renderbuffer_manager();
691 FramebufferManager* framebuffer_manager() {
692 return group_->framebuffer_manager();
695 ProgramManager* program_manager() {
696 return group_->program_manager();
699 ShaderManager* shader_manager() {
700 return group_->shader_manager();
703 const TextureManager* texture_manager() const {
704 return group_->texture_manager();
707 TextureManager* texture_manager() {
708 return group_->texture_manager();
711 MailboxManager* mailbox_manager() {
712 return group_->mailbox_manager();
715 ImageManager* image_manager() {
716 return group_->image_manager();
719 VertexArrayManager* vertex_array_manager() {
720 return vertex_array_manager_.get();
723 MemoryTracker* memory_tracker() {
724 return group_->memory_tracker();
727 StreamTextureManager* stream_texture_manager() const {
728 return group_->stream_texture_manager();
731 bool EnsureGPUMemoryAvailable(size_t estimated_size) {
732 MemoryTracker* tracker = memory_tracker();
733 if (tracker) {
734 return tracker->EnsureGPUMemoryAvailable(estimated_size);
736 return true;
739 bool IsOffscreenBufferMultisampled() const {
740 return offscreen_target_samples_ > 1;
743 // Creates a Texture for the given texture.
744 TextureRef* CreateTexture(
745 GLuint client_id, GLuint service_id) {
746 return texture_manager()->CreateTexture(client_id, service_id);
749 // Gets the texture info for the given texture. Returns NULL if none exists.
750 TextureRef* GetTexture(GLuint client_id) const {
751 return texture_manager()->GetTexture(client_id);
754 // Deletes the texture info for the given texture.
755 void RemoveTexture(GLuint client_id) {
756 texture_manager()->RemoveTexture(client_id);
759 // Get the size (in pixels) of the currently bound frame buffer (either FBO
760 // or regular back buffer).
761 gfx::Size GetBoundReadFrameBufferSize();
763 // Get the format of the currently bound frame buffer (either FBO or regular
764 // back buffer)
765 GLenum GetBoundReadFrameBufferInternalFormat();
766 GLenum GetBoundDrawFrameBufferInternalFormat();
768 // Wrapper for CompressedTexImage2D commands.
769 error::Error DoCompressedTexImage2D(
770 GLenum target,
771 GLint level,
772 GLenum internal_format,
773 GLsizei width,
774 GLsizei height,
775 GLint border,
776 GLsizei image_size,
777 const void* data);
779 // Wrapper for CompressedTexSubImage2D.
780 void DoCompressedTexSubImage2D(
781 GLenum target,
782 GLint level,
783 GLint xoffset,
784 GLint yoffset,
785 GLsizei width,
786 GLsizei height,
787 GLenum format,
788 GLsizei imageSize,
789 const void * data);
791 // Wrapper for CopyTexImage2D.
792 void DoCopyTexImage2D(
793 GLenum target,
794 GLint level,
795 GLenum internal_format,
796 GLint x,
797 GLint y,
798 GLsizei width,
799 GLsizei height,
800 GLint border);
802 // Wrapper for SwapBuffers.
803 void DoSwapBuffers();
805 // Wrapper for CopyTexSubImage2D.
806 void DoCopyTexSubImage2D(
807 GLenum target,
808 GLint level,
809 GLint xoffset,
810 GLint yoffset,
811 GLint x,
812 GLint y,
813 GLsizei width,
814 GLsizei height);
816 // Validation for TexImage2D commands.
817 bool ValidateTexImage2D(
818 const char* function_name,
819 GLenum target,
820 GLint level,
821 GLenum internal_format,
822 GLsizei width,
823 GLsizei height,
824 GLint border,
825 GLenum format,
826 GLenum type,
827 const void* pixels,
828 uint32 pixels_size);
830 // Wrapper for TexImage2D commands.
831 void DoTexImage2D(
832 GLenum target,
833 GLint level,
834 GLenum internal_format,
835 GLsizei width,
836 GLsizei height,
837 GLint border,
838 GLenum format,
839 GLenum type,
840 const void* pixels,
841 uint32 pixels_size);
843 // Validation for TexSubImage2D.
844 bool ValidateTexSubImage2D(
845 error::Error* error,
846 const char* function_name,
847 GLenum target,
848 GLint level,
849 GLint xoffset,
850 GLint yoffset,
851 GLsizei width,
852 GLsizei height,
853 GLenum format,
854 GLenum type,
855 const void * data);
857 // Wrapper for TexSubImage2D.
858 error::Error DoTexSubImage2D(
859 GLenum target,
860 GLint level,
861 GLint xoffset,
862 GLint yoffset,
863 GLsizei width,
864 GLsizei height,
865 GLenum format,
866 GLenum type,
867 const void * data);
869 // Extra validation for async tex(Sub)Image2D.
870 bool ValidateAsyncTransfer(
871 const char* function_name,
872 TextureRef* texture_ref,
873 GLenum target,
874 GLint level,
875 const void * data);
877 // Wrapper for TexImageIOSurface2DCHROMIUM.
878 void DoTexImageIOSurface2DCHROMIUM(
879 GLenum target,
880 GLsizei width,
881 GLsizei height,
882 GLuint io_surface_id,
883 GLuint plane);
885 void DoCopyTextureCHROMIUM(
886 GLenum target,
887 GLuint source_id,
888 GLuint target_id,
889 GLint level,
890 GLenum internal_format,
891 GLenum dest_type);
893 // Wrapper for TexStorage2DEXT.
894 void DoTexStorage2DEXT(
895 GLenum target,
896 GLint levels,
897 GLenum internal_format,
898 GLsizei width,
899 GLsizei height);
901 void DoProduceTextureCHROMIUM(GLenum target, const GLbyte* key);
902 void DoConsumeTextureCHROMIUM(GLenum target, const GLbyte* key);
904 void DoBindTexImage2DCHROMIUM(
905 GLenum target,
906 GLint image_id);
907 void DoReleaseTexImage2DCHROMIUM(
908 GLenum target,
909 GLint image_id);
911 void DoTraceEndCHROMIUM(void);
913 void DoDrawBuffersEXT(GLsizei count, const GLenum* bufs);
915 // Creates a Program for the given program.
916 Program* CreateProgram(
917 GLuint client_id, GLuint service_id) {
918 return program_manager()->CreateProgram(client_id, service_id);
921 // Gets the program info for the given program. Returns NULL if none exists.
922 Program* GetProgram(GLuint client_id) {
923 return program_manager()->GetProgram(client_id);
926 #if defined(NDEBUG)
927 void LogClientServiceMapping(
928 const char* /* function_name */,
929 GLuint /* client_id */,
930 GLuint /* service_id */) {
932 template<typename T>
933 void LogClientServiceForInfo(
934 T* /* info */, GLuint /* client_id */, const char* /* function_name */) {
936 #else
937 void LogClientServiceMapping(
938 const char* function_name, GLuint client_id, GLuint service_id) {
939 if (service_logging_) {
940 DLOG(INFO) << "[" << logger_.GetLogPrefix() << "] " << function_name
941 << ": client_id = " << client_id
942 << ", service_id = " << service_id;
945 template<typename T>
946 void LogClientServiceForInfo(
947 T* info, GLuint client_id, const char* function_name) {
948 if (info) {
949 LogClientServiceMapping(function_name, client_id, info->service_id());
952 #endif
954 // Gets the program info for the given program. If it's not a program
955 // generates a GL error. Returns NULL if not program.
956 Program* GetProgramInfoNotShader(
957 GLuint client_id, const char* function_name) {
958 Program* program = GetProgram(client_id);
959 if (!program) {
960 if (GetShader(client_id)) {
961 LOCAL_SET_GL_ERROR(
962 GL_INVALID_OPERATION, function_name, "shader passed for program");
963 } else {
964 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "unknown program");
967 LogClientServiceForInfo(program, client_id, function_name);
968 return program;
972 // Creates a Shader for the given shader.
973 Shader* CreateShader(
974 GLuint client_id,
975 GLuint service_id,
976 GLenum shader_type) {
977 return shader_manager()->CreateShader(
978 client_id, service_id, shader_type);
981 // Gets the shader info for the given shader. Returns NULL if none exists.
982 Shader* GetShader(GLuint client_id) {
983 return shader_manager()->GetShader(client_id);
986 // Gets the shader info for the given shader. If it's not a shader generates a
987 // GL error. Returns NULL if not shader.
988 Shader* GetShaderInfoNotProgram(
989 GLuint client_id, const char* function_name) {
990 Shader* shader = GetShader(client_id);
991 if (!shader) {
992 if (GetProgram(client_id)) {
993 LOCAL_SET_GL_ERROR(
994 GL_INVALID_OPERATION, function_name, "program passed for shader");
995 } else {
996 LOCAL_SET_GL_ERROR(
997 GL_INVALID_VALUE, function_name, "unknown shader");
1000 LogClientServiceForInfo(shader, client_id, function_name);
1001 return shader;
1004 // Creates a buffer info for the given buffer.
1005 void CreateBuffer(GLuint client_id, GLuint service_id) {
1006 return buffer_manager()->CreateBuffer(client_id, service_id);
1009 // Gets the buffer info for the given buffer.
1010 Buffer* GetBuffer(GLuint client_id) {
1011 Buffer* buffer = buffer_manager()->GetBuffer(client_id);
1012 return buffer;
1015 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
1016 // on glDeleteBuffers so we can make sure the user does not try to render
1017 // with deleted buffers.
1018 void RemoveBuffer(GLuint client_id);
1020 // Creates a framebuffer info for the given framebuffer.
1021 void CreateFramebuffer(GLuint client_id, GLuint service_id) {
1022 return framebuffer_manager()->CreateFramebuffer(client_id, service_id);
1025 // Gets the framebuffer info for the given framebuffer.
1026 Framebuffer* GetFramebuffer(GLuint client_id) {
1027 return framebuffer_manager()->GetFramebuffer(client_id);
1030 // Removes the framebuffer info for the given framebuffer.
1031 void RemoveFramebuffer(GLuint client_id) {
1032 framebuffer_manager()->RemoveFramebuffer(client_id);
1035 // Creates a renderbuffer info for the given renderbuffer.
1036 void CreateRenderbuffer(GLuint client_id, GLuint service_id) {
1037 return renderbuffer_manager()->CreateRenderbuffer(
1038 client_id, service_id);
1041 // Gets the renderbuffer info for the given renderbuffer.
1042 Renderbuffer* GetRenderbuffer(GLuint client_id) {
1043 return renderbuffer_manager()->GetRenderbuffer(client_id);
1046 // Removes the renderbuffer info for the given renderbuffer.
1047 void RemoveRenderbuffer(GLuint client_id) {
1048 renderbuffer_manager()->RemoveRenderbuffer(client_id);
1051 // Gets the vertex attrib manager for the given vertex array.
1052 VertexAttribManager* GetVertexAttribManager(GLuint client_id) {
1053 VertexAttribManager* info =
1054 vertex_array_manager()->GetVertexAttribManager(client_id);
1055 return info;
1058 // Removes the vertex attrib manager for the given vertex array.
1059 void RemoveVertexAttribManager(GLuint client_id) {
1060 vertex_array_manager()->RemoveVertexAttribManager(client_id);
1063 // Creates a vertex attrib manager for the given vertex array.
1064 void CreateVertexAttribManager(GLuint client_id, GLuint service_id) {
1065 return vertex_array_manager()->CreateVertexAttribManager(
1066 client_id, service_id, group_->max_vertex_attribs());
1069 void DoBindAttribLocation(GLuint client_id, GLuint index, const char* name);
1070 void DoBindUniformLocationCHROMIUM(
1071 GLuint client_id, GLint location, const char* name);
1073 error::Error GetAttribLocationHelper(
1074 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1075 const std::string& name_str);
1077 error::Error GetUniformLocationHelper(
1078 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1079 const std::string& name_str);
1081 // Helper for glShaderSource.
1082 error::Error ShaderSourceHelper(
1083 GLuint client_id, const char* data, uint32 data_size);
1085 // Clear any textures used by the current program.
1086 bool ClearUnclearedTextures();
1088 // Clear any uncleared level in texture.
1089 // Returns false if there was a generated GL error.
1090 bool ClearTexture(Texture* texture);
1092 // Clears any uncleared attachments attached to the given frame buffer.
1093 // Returns false if there was a generated GL error.
1094 void ClearUnclearedAttachments(GLenum target, Framebuffer* framebuffer);
1096 // overridden from GLES2Decoder
1097 virtual bool ClearLevel(unsigned service_id,
1098 unsigned bind_target,
1099 unsigned target,
1100 int level,
1101 unsigned format,
1102 unsigned type,
1103 int width,
1104 int height,
1105 bool is_texture_immutable) OVERRIDE;
1107 // Restore all GL state that affects clearing.
1108 void RestoreClearState();
1110 // Remembers the state of some capabilities.
1111 // Returns: true if glEnable/glDisable should actually be called.
1112 bool SetCapabilityState(GLenum cap, bool enabled);
1114 // Check that the currently bound framebuffers are valid.
1115 // Generates GL error if not.
1116 bool CheckBoundFramebuffersValid(const char* func_name);
1118 // Check if a framebuffer meets our requirements.
1119 bool CheckFramebufferValid(
1120 Framebuffer* framebuffer,
1121 GLenum target,
1122 const char* func_name);
1124 // Checks if the current program exists and is valid. If not generates the
1125 // appropriate GL error. Returns true if the current program is in a usable
1126 // state.
1127 bool CheckCurrentProgram(const char* function_name);
1129 // Checks if the current program exists and is valid and that location is not
1130 // -1. If the current program is not valid generates the appropriate GL
1131 // error. Returns true if the current program is in a usable state and
1132 // location is not -1.
1133 bool CheckCurrentProgramForUniform(GLint location, const char* function_name);
1135 // Gets the type of a uniform for a location in the current program. Sets GL
1136 // errors if the current program is not valid. Returns true if the current
1137 // program is valid and the location exists. Adjusts count so it
1138 // does not overflow the uniform.
1139 bool PrepForSetUniformByLocation(
1140 GLint fake_location, const char* function_name,
1141 const BaseUniformInfo& base_info,
1142 GLint* real_location, GLenum* type, GLsizei* count);
1144 // Gets the service id for any simulated backbuffer fbo.
1145 GLuint GetBackbufferServiceId() const;
1147 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
1148 bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
1150 // Helper for glGetVertexAttrib
1151 void GetVertexAttribHelper(
1152 const VertexAttrib* attrib, GLenum pname, GLint* param);
1154 // Wrapper for glCreateProgram
1155 bool CreateProgramHelper(GLuint client_id);
1157 // Wrapper for glCreateShader
1158 bool CreateShaderHelper(GLenum type, GLuint client_id);
1160 // Wrapper for glActiveTexture
1161 void DoActiveTexture(GLenum texture_unit);
1163 // Wrapper for glAttachShader
1164 void DoAttachShader(GLuint client_program_id, GLint client_shader_id);
1166 // Wrapper for glBindBuffer since we need to track the current targets.
1167 void DoBindBuffer(GLenum target, GLuint buffer);
1169 // Wrapper for glBindFramebuffer since we need to track the current targets.
1170 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
1172 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1173 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
1175 // Wrapper for glBindTexture since we need to track the current targets.
1176 void DoBindTexture(GLenum target, GLuint texture);
1178 // Wrapper for glBindVertexArrayOES
1179 void DoBindVertexArrayOES(GLuint array);
1180 void EmulateVertexArrayState();
1182 // Wrapper for glBlitFramebufferEXT.
1183 void DoBlitFramebufferEXT(
1184 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
1185 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
1186 GLbitfield mask, GLenum filter);
1188 // Wrapper for glBufferData.
1189 void DoBufferData(
1190 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage);
1192 // Wrapper for glBufferSubData.
1193 void DoBufferSubData(
1194 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
1196 // Wrapper for glCheckFramebufferStatus
1197 GLenum DoCheckFramebufferStatus(GLenum target);
1199 // Wrapper for glClear
1200 error::Error DoClear(GLbitfield mask);
1202 // Wrappers for various state.
1203 void DoDepthRangef(GLclampf znear, GLclampf zfar);
1204 void DoSampleCoverage(GLclampf value, GLboolean invert);
1206 // Wrapper for glCompileShader.
1207 void DoCompileShader(GLuint shader);
1209 // Helper for DeleteSharedIdsCHROMIUM commands.
1210 void DoDeleteSharedIdsCHROMIUM(
1211 GLuint namespace_id, GLsizei n, const GLuint* ids);
1213 // Wrapper for glDetachShader
1214 void DoDetachShader(GLuint client_program_id, GLint client_shader_id);
1216 // Wrapper for glDisable
1217 void DoDisable(GLenum cap);
1219 // Wrapper for glDisableVertexAttribArray.
1220 void DoDisableVertexAttribArray(GLuint index);
1222 // Wrapper for glDiscardFramebufferEXT, since we need to track undefined
1223 // attachments.
1224 void DoDiscardFramebufferEXT(GLenum target,
1225 GLsizei numAttachments,
1226 const GLenum* attachments);
1228 // Wrapper for glEnable
1229 void DoEnable(GLenum cap);
1231 // Wrapper for glEnableVertexAttribArray.
1232 void DoEnableVertexAttribArray(GLuint index);
1234 // Wrapper for glFinish.
1235 void DoFinish();
1237 // Wrapper for glFlush.
1238 void DoFlush();
1240 // Wrapper for glFramebufferRenderbufffer.
1241 void DoFramebufferRenderbuffer(
1242 GLenum target, GLenum attachment, GLenum renderbuffertarget,
1243 GLuint renderbuffer);
1245 // Wrapper for glFramebufferTexture2D.
1246 void DoFramebufferTexture2D(
1247 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
1248 GLint level);
1250 // Wrapper for glGenerateMipmap
1251 void DoGenerateMipmap(GLenum target);
1253 // Helper for GenSharedIdsCHROMIUM commands.
1254 void DoGenSharedIdsCHROMIUM(
1255 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids);
1257 // Wrapper for DoGetBooleanv.
1258 void DoGetBooleanv(GLenum pname, GLboolean* params);
1260 // Wrapper for DoGetFloatv.
1261 void DoGetFloatv(GLenum pname, GLfloat* params);
1263 // Wrapper for glGetFramebufferAttachmentParameteriv.
1264 void DoGetFramebufferAttachmentParameteriv(
1265 GLenum target, GLenum attachment, GLenum pname, GLint* params);
1267 // Wrapper for glGetIntegerv.
1268 void DoGetIntegerv(GLenum pname, GLint* params);
1270 // Gets the max value in a range in a buffer.
1271 GLuint DoGetMaxValueInBufferCHROMIUM(
1272 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset);
1274 // Wrapper for glGetBufferParameteriv.
1275 void DoGetBufferParameteriv(
1276 GLenum target, GLenum pname, GLint* params);
1278 // Wrapper for glGetProgramiv.
1279 void DoGetProgramiv(
1280 GLuint program_id, GLenum pname, GLint* params);
1282 // Wrapper for glRenderbufferParameteriv.
1283 void DoGetRenderbufferParameteriv(
1284 GLenum target, GLenum pname, GLint* params);
1286 // Wrapper for glGetShaderiv
1287 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
1289 // Wrappers for glGetVertexAttrib.
1290 void DoGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params);
1291 void DoGetVertexAttribiv(GLuint index, GLenum pname, GLint *params);
1293 // Wrappers for glIsXXX functions.
1294 bool DoIsEnabled(GLenum cap);
1295 bool DoIsBuffer(GLuint client_id);
1296 bool DoIsFramebuffer(GLuint client_id);
1297 bool DoIsProgram(GLuint client_id);
1298 bool DoIsRenderbuffer(GLuint client_id);
1299 bool DoIsShader(GLuint client_id);
1300 bool DoIsTexture(GLuint client_id);
1301 bool DoIsVertexArrayOES(GLuint client_id);
1303 // Wrapper for glLinkProgram
1304 void DoLinkProgram(GLuint program);
1306 // Helper for RegisterSharedIdsCHROMIUM.
1307 void DoRegisterSharedIdsCHROMIUM(
1308 GLuint namespace_id, GLsizei n, const GLuint* ids);
1310 // Wrapper for glRenderbufferStorage.
1311 void DoRenderbufferStorage(
1312 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
1314 // Wrapper for glRenderbufferStorageMultisampleEXT.
1315 void DoRenderbufferStorageMultisample(
1316 GLenum target, GLsizei samples, GLenum internalformat,
1317 GLsizei width, GLsizei height);
1319 // Wrapper for glReleaseShaderCompiler.
1320 void DoReleaseShaderCompiler() { }
1322 // Wrappers for glTexParameter functions.
1323 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
1324 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
1325 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
1326 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
1328 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1329 // spec only these 2 functions can be used to set sampler uniforms.
1330 void DoUniform1i(GLint fake_location, GLint v0);
1331 void DoUniform1iv(GLint fake_location, GLsizei count, const GLint* value);
1332 void DoUniform2iv(GLint fake_location, GLsizei count, const GLint* value);
1333 void DoUniform3iv(GLint fake_location, GLsizei count, const GLint* value);
1334 void DoUniform4iv(GLint fake_location, GLsizei count, const GLint* value);
1336 // Wrappers for glUniformfv because some drivers don't correctly accept
1337 // bool uniforms.
1338 void DoUniform1fv(GLint fake_location, GLsizei count, const GLfloat* value);
1339 void DoUniform2fv(GLint fake_location, GLsizei count, const GLfloat* value);
1340 void DoUniform3fv(GLint fake_location, GLsizei count, const GLfloat* value);
1341 void DoUniform4fv(GLint fake_location, GLsizei count, const GLfloat* value);
1343 void DoUniformMatrix2fv(
1344 GLint fake_location, GLsizei count, GLboolean transpose,
1345 const GLfloat* value);
1346 void DoUniformMatrix3fv(
1347 GLint fake_location, GLsizei count, GLboolean transpose,
1348 const GLfloat* value);
1349 void DoUniformMatrix4fv(
1350 GLint fake_location, GLsizei count, GLboolean transpose,
1351 const GLfloat* value);
1353 bool SetVertexAttribValue(
1354 const char* function_name, GLuint index, const GLfloat* value);
1356 // Wrappers for glVertexAttrib??
1357 void DoVertexAttrib1f(GLuint index, GLfloat v0);
1358 void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
1359 void DoVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
1360 void DoVertexAttrib4f(
1361 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
1362 void DoVertexAttrib1fv(GLuint index, const GLfloat *v);
1363 void DoVertexAttrib2fv(GLuint index, const GLfloat *v);
1364 void DoVertexAttrib3fv(GLuint index, const GLfloat *v);
1365 void DoVertexAttrib4fv(GLuint index, const GLfloat *v);
1367 // Wrapper for glViewport
1368 void DoViewport(GLint x, GLint y, GLsizei width, GLsizei height);
1370 // Wrapper for glUseProgram
1371 void DoUseProgram(GLuint program);
1373 // Wrapper for glValidateProgram.
1374 void DoValidateProgram(GLuint program_client_id);
1376 void DoInsertEventMarkerEXT(GLsizei length, const GLchar* marker);
1377 void DoPushGroupMarkerEXT(GLsizei length, const GLchar* group);
1378 void DoPopGroupMarkerEXT(void);
1380 // Gets the number of values that will be returned by glGetXXX. Returns
1381 // false if pname is unknown.
1382 bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
1384 // Checks if the current program and vertex attributes are valid for drawing.
1385 bool IsDrawValid(
1386 const char* function_name, GLuint max_vertex_accessed, GLsizei primcount);
1388 // Returns true if successful, simulated will be true if attrib0 was
1389 // simulated.
1390 bool SimulateAttrib0(
1391 const char* function_name, GLuint max_vertex_accessed, bool* simulated);
1392 void RestoreStateForAttrib(GLuint attrib);
1394 // Returns true if textures were set.
1395 bool SetBlackTextureForNonRenderableTextures();
1396 void RestoreStateForNonRenderableTextures();
1398 // Returns true if GL_FIXED attribs were simulated.
1399 bool SimulateFixedAttribs(
1400 const char* function_name,
1401 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount);
1402 void RestoreStateForSimulatedFixedAttribs();
1404 // Handle DrawArrays and DrawElements for both instanced and non-instanced
1405 // cases (primcount is 0 for non-instanced).
1406 error::Error DoDrawArrays(
1407 const char* function_name,
1408 bool instanced, GLenum mode, GLint first, GLsizei count,
1409 GLsizei primcount);
1410 error::Error DoDrawElements(
1411 const char* function_name,
1412 bool instanced, GLenum mode, GLsizei count, GLenum type,
1413 int32 offset, GLsizei primcount);
1415 // Gets the buffer id for a given target.
1416 Buffer* GetBufferInfoForTarget(GLenum target) {
1417 DCHECK(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER);
1418 if (target == GL_ARRAY_BUFFER) {
1419 return state_.bound_array_buffer.get();
1420 } else {
1421 return state_.vertex_attrib_manager->element_array_buffer();
1425 // Gets the texture id for a given target.
1426 TextureRef* GetTextureInfoForTarget(GLenum target) {
1427 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
1428 TextureRef* texture = NULL;
1429 switch (target) {
1430 case GL_TEXTURE_2D:
1431 texture = unit.bound_texture_2d.get();
1432 break;
1433 case GL_TEXTURE_CUBE_MAP:
1434 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1435 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1436 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1437 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1438 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1439 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1440 texture = unit.bound_texture_cube_map.get();
1441 break;
1442 case GL_TEXTURE_EXTERNAL_OES:
1443 texture = unit.bound_texture_external_oes.get();
1444 break;
1445 case GL_TEXTURE_RECTANGLE_ARB:
1446 texture = unit.bound_texture_rectangle_arb.get();
1447 break;
1448 default:
1449 NOTREACHED();
1450 return NULL;
1452 return texture;
1455 TextureRef* GetTextureInfoForTargetUnlessDefault(
1456 GLenum target) {
1457 TextureRef* texture = GetTextureInfoForTarget(target);
1458 if (!texture)
1459 return NULL;
1460 if (texture == texture_manager()->GetDefaultTextureInfo(target))
1461 return NULL;
1462 return texture;
1465 GLenum GetBindTargetForSamplerType(GLenum type) {
1466 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
1467 type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB);
1468 switch (type) {
1469 case GL_SAMPLER_2D:
1470 return GL_TEXTURE_2D;
1471 case GL_SAMPLER_CUBE:
1472 return GL_TEXTURE_CUBE_MAP;
1473 case GL_SAMPLER_EXTERNAL_OES:
1474 return GL_TEXTURE_EXTERNAL_OES;
1475 case GL_SAMPLER_2D_RECT_ARB:
1476 return GL_TEXTURE_RECTANGLE_ARB;
1479 NOTREACHED();
1480 return 0;
1483 // Gets the framebuffer info for a particular target.
1484 Framebuffer* GetFramebufferInfoForTarget(GLenum target) {
1485 Framebuffer* framebuffer = NULL;
1486 switch (target) {
1487 case GL_FRAMEBUFFER:
1488 case GL_DRAW_FRAMEBUFFER_EXT:
1489 framebuffer = state_.bound_draw_framebuffer.get();
1490 break;
1491 case GL_READ_FRAMEBUFFER_EXT:
1492 framebuffer = state_.bound_read_framebuffer.get();
1493 break;
1494 default:
1495 NOTREACHED();
1496 break;
1498 return framebuffer;
1501 Renderbuffer* GetRenderbufferInfoForTarget(
1502 GLenum target) {
1503 Renderbuffer* renderbuffer = NULL;
1504 switch (target) {
1505 case GL_RENDERBUFFER:
1506 renderbuffer = state_.bound_renderbuffer.get();
1507 break;
1508 default:
1509 NOTREACHED();
1510 break;
1512 return renderbuffer;
1515 // Validates the program and location for a glGetUniform call and returns
1516 // a SizeResult setup to receive the result. Returns true if glGetUniform
1517 // should be called.
1518 bool GetUniformSetup(
1519 GLuint program, GLint fake_location,
1520 uint32 shm_id, uint32 shm_offset,
1521 error::Error* error, GLint* real_location, GLuint* service_id,
1522 void** result, GLenum* result_type);
1524 // Computes the estimated memory used for the backbuffer and passes it to
1525 // the tracing system.
1526 size_t GetBackbufferMemoryTotal();
1528 virtual bool WasContextLost() OVERRIDE;
1529 virtual bool WasContextLostByRobustnessExtension() OVERRIDE;
1530 virtual void LoseContext(uint32 reset_status) OVERRIDE;
1532 #if defined(OS_MACOSX)
1533 void ReleaseIOSurfaceForTexture(GLuint texture_id);
1534 #endif
1536 // Validates the combination of texture parameters. For example validates that
1537 // for a given format the specific type, level and targets are valid.
1538 // Synthesizes the correct GL error if invalid. Returns true if valid.
1539 bool ValidateTextureParameters(
1540 const char* function_name,
1541 GLenum target, GLenum format, GLenum type, GLint level);
1543 bool ValidateCompressedTexDimensions(
1544 const char* function_name,
1545 GLint level, GLsizei width, GLsizei height, GLenum format);
1546 bool ValidateCompressedTexFuncData(
1547 const char* function_name,
1548 GLsizei width, GLsizei height, GLenum format, size_t size);
1549 bool ValidateCompressedTexSubDimensions(
1550 const char* function_name,
1551 GLenum target, GLint level, GLint xoffset, GLint yoffset,
1552 GLsizei width, GLsizei height, GLenum format,
1553 Texture* texture);
1555 void RenderWarning(const char* filename, int line, const std::string& msg);
1556 void PerformanceWarning(
1557 const char* filename, int line, const std::string& msg);
1559 const FeatureInfo::FeatureFlags& features() const {
1560 return feature_info_->feature_flags();
1563 const FeatureInfo::Workarounds& workarounds() const {
1564 return feature_info_->workarounds();
1567 bool ShouldDeferDraws() {
1568 return !offscreen_target_frame_buffer_.get() &&
1569 state_.bound_draw_framebuffer.get() == NULL &&
1570 surface_->DeferDraws();
1573 bool ShouldDeferReads() {
1574 return !offscreen_target_frame_buffer_.get() &&
1575 state_.bound_read_framebuffer.get() == NULL &&
1576 surface_->DeferDraws();
1579 void ProcessPendingReadPixels();
1580 void FinishReadPixels(const cmds::ReadPixels& c, GLuint buffer);
1582 void ForceCompileShaderIfPending(Shader* shader);
1584 // Generate a member function prototype for each command in an automated and
1585 // typesafe way.
1586 #define GLES2_CMD_OP(name) \
1587 Error Handle ## name( \
1588 uint32 immediate_data_size, \
1589 const cmds::name& args); \
1591 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1593 #undef GLES2_CMD_OP
1595 // The GL context this decoder renders to on behalf of the client.
1596 scoped_refptr<gfx::GLSurface> surface_;
1597 scoped_refptr<gfx::GLContext> context_;
1599 // The ContextGroup for this decoder uses to track resources.
1600 scoped_refptr<ContextGroup> group_;
1602 DebugMarkerManager debug_marker_manager_;
1603 Logger logger_;
1605 // All the state for this context.
1606 ContextState state_;
1608 // Current width and height of the offscreen frame buffer.
1609 gfx::Size offscreen_size_;
1611 // Util to help with GL.
1612 GLES2Util util_;
1614 // unpack flip y as last set by glPixelStorei
1615 bool unpack_flip_y_;
1617 // unpack (un)premultiply alpha as last set by glPixelStorei
1618 bool unpack_premultiply_alpha_;
1619 bool unpack_unpremultiply_alpha_;
1621 // Default vertex attribs manager, used when no VAOs are bound.
1622 scoped_refptr<VertexAttribManager> default_vertex_attrib_manager_;
1624 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1625 GLuint attrib_0_buffer_id_;
1627 // The value currently in attrib_0.
1628 Vec4 attrib_0_value_;
1630 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1631 bool attrib_0_buffer_matches_value_;
1633 // The size of attrib 0.
1634 GLsizei attrib_0_size_;
1636 // The buffer used to simulate GL_FIXED attribs.
1637 GLuint fixed_attrib_buffer_id_;
1639 // The size of fiixed attrib buffer.
1640 GLsizei fixed_attrib_buffer_size_;
1642 // state saved for clearing so we can clear render buffers and then
1643 // restore to these values.
1644 bool clear_state_dirty_;
1646 // The offscreen frame buffer that the client renders to. With EGL, the
1647 // depth and stencil buffers are separate. With regular GL there is a single
1648 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1649 // offscreen_target_stencil_render_buffer_ is unused.
1650 scoped_ptr<BackFramebuffer> offscreen_target_frame_buffer_;
1651 scoped_ptr<BackTexture> offscreen_target_color_texture_;
1652 scoped_ptr<BackRenderbuffer> offscreen_target_color_render_buffer_;
1653 scoped_ptr<BackRenderbuffer> offscreen_target_depth_render_buffer_;
1654 scoped_ptr<BackRenderbuffer> offscreen_target_stencil_render_buffer_;
1655 GLenum offscreen_target_color_format_;
1656 GLenum offscreen_target_depth_format_;
1657 GLenum offscreen_target_stencil_format_;
1658 GLsizei offscreen_target_samples_;
1659 GLboolean offscreen_target_buffer_preserved_;
1661 // The copy that is saved when SwapBuffers is called.
1662 scoped_ptr<BackFramebuffer> offscreen_saved_frame_buffer_;
1663 scoped_ptr<BackTexture> offscreen_saved_color_texture_;
1664 scoped_refptr<TextureRef>
1665 offscreen_saved_color_texture_info_;
1667 // The copy that is used as the destination for multi-sample resolves.
1668 scoped_ptr<BackFramebuffer> offscreen_resolved_frame_buffer_;
1669 scoped_ptr<BackTexture> offscreen_resolved_color_texture_;
1670 GLenum offscreen_saved_color_format_;
1672 scoped_ptr<QueryManager> query_manager_;
1674 scoped_ptr<VertexArrayManager> vertex_array_manager_;
1676 base::Callback<void(gfx::Size, float)> resize_callback_;
1678 WaitSyncPointCallback wait_sync_point_callback_;
1680 ShaderCacheCallback shader_cache_callback_;
1682 scoped_ptr<AsyncPixelTransferManager> async_pixel_transfer_manager_;
1684 // The format of the back buffer_
1685 GLenum back_buffer_color_format_;
1686 bool back_buffer_has_depth_;
1687 bool back_buffer_has_stencil_;
1689 // Backbuffer attachments that are currently undefined.
1690 uint32 backbuffer_needs_clear_bits_;
1692 bool teximage2d_faster_than_texsubimage2d_;
1694 // The current decoder error.
1695 error::Error current_decoder_error_;
1697 bool use_shader_translator_;
1698 scoped_refptr<ShaderTranslator> vertex_translator_;
1699 scoped_refptr<ShaderTranslator> fragment_translator_;
1701 DisallowedFeatures disallowed_features_;
1703 // Cached from ContextGroup
1704 const Validators* validators_;
1705 scoped_refptr<FeatureInfo> feature_info_;
1707 // This indicates all the following texSubImage2D calls that are part of the
1708 // failed texImage2D call should be ignored.
1709 bool tex_image_2d_failed_;
1711 int frame_number_;
1713 bool has_robustness_extension_;
1714 GLenum reset_status_;
1715 bool reset_by_robustness_extension_;
1717 // These flags are used to override the state of the shared feature_info_
1718 // member. Because the same FeatureInfo instance may be shared among many
1719 // contexts, the assumptions on the availablity of extensions in WebGL
1720 // contexts may be broken. These flags override the shared state to preserve
1721 // WebGL semantics.
1722 bool force_webgl_glsl_validation_;
1723 bool derivatives_explicitly_enabled_;
1724 bool frag_depth_explicitly_enabled_;
1725 bool draw_buffers_explicitly_enabled_;
1727 bool compile_shader_always_succeeds_;
1729 // Log extra info.
1730 bool service_logging_;
1732 #if defined(OS_MACOSX)
1733 typedef std::map<GLuint, CFTypeRef> TextureToIOSurfaceMap;
1734 TextureToIOSurfaceMap texture_to_io_surface_map_;
1735 #endif
1737 scoped_ptr<CopyTextureCHROMIUMResourceManager> copy_texture_CHROMIUM_;
1739 // Cached values of the currently assigned viewport dimensions.
1740 GLsizei viewport_max_width_;
1741 GLsizei viewport_max_height_;
1743 // Command buffer stats.
1744 int texture_upload_count_;
1745 base::TimeDelta total_texture_upload_time_;
1746 base::TimeDelta total_processing_commands_time_;
1748 scoped_ptr<GPUTracer> gpu_tracer_;
1750 std::queue<linked_ptr<FenceCallback> > pending_readpixel_fences_;
1752 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
1755 ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(
1756 const char* function_name, GLES2DecoderImpl* decoder)
1757 : function_name_(function_name),
1758 decoder_(decoder) {
1759 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(decoder_->GetErrorState(),
1760 function_name_);
1763 ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
1764 ERRORSTATE_CLEAR_REAL_GL_ERRORS(decoder_->GetErrorState(), function_name_);
1767 ScopedTexture2DBinder::ScopedTexture2DBinder(GLES2DecoderImpl* decoder,
1768 GLuint id)
1769 : decoder_(decoder) {
1770 ScopedGLErrorSuppressor suppressor(
1771 "ScopedTexture2DBinder::ctor", decoder_);
1773 // TODO(apatrick): Check if there are any other states that need to be reset
1774 // before binding a new texture.
1775 glActiveTexture(GL_TEXTURE0);
1776 glBindTexture(GL_TEXTURE_2D, id);
1779 ScopedTexture2DBinder::~ScopedTexture2DBinder() {
1780 ScopedGLErrorSuppressor suppressor(
1781 "ScopedTexture2DBinder::dtor", decoder_);
1782 decoder_->RestoreCurrentTexture2DBindings();
1785 ScopedRenderBufferBinder::ScopedRenderBufferBinder(GLES2DecoderImpl* decoder,
1786 GLuint id)
1787 : decoder_(decoder) {
1788 ScopedGLErrorSuppressor suppressor(
1789 "ScopedRenderBufferBinder::ctor", decoder_);
1790 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
1793 ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
1794 ScopedGLErrorSuppressor suppressor(
1795 "ScopedRenderBufferBinder::dtor", decoder_);
1796 decoder_->RestoreCurrentRenderbufferBindings();
1799 ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
1800 GLuint id)
1801 : decoder_(decoder) {
1802 ScopedGLErrorSuppressor suppressor(
1803 "ScopedFrameBufferBinder::ctor", decoder_);
1804 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
1805 decoder->OnFboChanged();
1808 ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
1809 ScopedGLErrorSuppressor suppressor(
1810 "ScopedFrameBufferBinder::dtor", decoder_);
1811 decoder_->RestoreCurrentFramebufferBindings();
1814 ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
1815 GLES2DecoderImpl* decoder, bool enforce_internal_framebuffer, bool internal)
1816 : decoder_(decoder) {
1817 resolve_and_bind_ = (decoder_->offscreen_target_frame_buffer_.get() &&
1818 decoder_->IsOffscreenBufferMultisampled() &&
1819 (!decoder_->state_.bound_read_framebuffer.get() ||
1820 enforce_internal_framebuffer));
1821 if (!resolve_and_bind_)
1822 return;
1824 ScopedGLErrorSuppressor suppressor(
1825 "ScopedResolvedFrameBufferBinder::ctor", decoder_);
1826 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT,
1827 decoder_->offscreen_target_frame_buffer_->id());
1828 GLuint targetid;
1829 if (internal) {
1830 if (!decoder_->offscreen_resolved_frame_buffer_.get()) {
1831 decoder_->offscreen_resolved_frame_buffer_.reset(
1832 new BackFramebuffer(decoder_));
1833 decoder_->offscreen_resolved_frame_buffer_->Create();
1834 decoder_->offscreen_resolved_color_texture_.reset(
1835 new BackTexture(decoder_));
1836 decoder_->offscreen_resolved_color_texture_->Create();
1838 DCHECK(decoder_->offscreen_saved_color_format_);
1839 decoder_->offscreen_resolved_color_texture_->AllocateStorage(
1840 decoder_->offscreen_size_, decoder_->offscreen_saved_color_format_,
1841 false);
1842 decoder_->offscreen_resolved_frame_buffer_->AttachRenderTexture(
1843 decoder_->offscreen_resolved_color_texture_.get());
1844 if (decoder_->offscreen_resolved_frame_buffer_->CheckStatus() !=
1845 GL_FRAMEBUFFER_COMPLETE) {
1846 LOG(ERROR) << "ScopedResolvedFrameBufferBinder failed "
1847 << "because offscreen resolved FBO was incomplete.";
1848 return;
1851 targetid = decoder_->offscreen_resolved_frame_buffer_->id();
1852 } else {
1853 targetid = decoder_->offscreen_saved_frame_buffer_->id();
1855 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, targetid);
1856 const int width = decoder_->offscreen_size_.width();
1857 const int height = decoder_->offscreen_size_.height();
1858 glDisable(GL_SCISSOR_TEST);
1859 if (GLES2Decoder::IsAngle()) {
1860 glBlitFramebufferANGLE(0, 0, width, height, 0, 0, width, height,
1861 GL_COLOR_BUFFER_BIT, GL_NEAREST);
1862 } else {
1863 glBlitFramebufferEXT(0, 0, width, height, 0, 0, width, height,
1864 GL_COLOR_BUFFER_BIT, GL_NEAREST);
1866 glBindFramebufferEXT(GL_FRAMEBUFFER, targetid);
1869 ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
1870 if (!resolve_and_bind_)
1871 return;
1873 ScopedGLErrorSuppressor suppressor(
1874 "ScopedResolvedFrameBufferBinder::dtor", decoder_);
1875 decoder_->RestoreCurrentFramebufferBindings();
1876 if (decoder_->state_.enable_flags.scissor_test) {
1877 glEnable(GL_SCISSOR_TEST);
1881 ScopedTextureUploadTimer::ScopedTextureUploadTimer(GLES2DecoderImpl* decoder)
1882 : decoder_(decoder),
1883 begin_time_(base::TimeTicks::HighResNow()) {
1886 ScopedTextureUploadTimer::~ScopedTextureUploadTimer() {
1887 decoder_->texture_upload_count_++;
1888 decoder_->total_texture_upload_time_ +=
1889 base::TimeTicks::HighResNow() - begin_time_;
1892 BackTexture::BackTexture(GLES2DecoderImpl* decoder)
1893 : decoder_(decoder),
1894 memory_tracker_(decoder->memory_tracker(), MemoryTracker::kUnmanaged),
1895 bytes_allocated_(0),
1896 id_(0) {
1899 BackTexture::~BackTexture() {
1900 // This does not destroy the render texture because that would require that
1901 // the associated GL context was current. Just check that it was explicitly
1902 // destroyed.
1903 DCHECK_EQ(id_, 0u);
1906 void BackTexture::Create() {
1907 ScopedGLErrorSuppressor suppressor("BackTexture::Create", decoder_);
1908 Destroy();
1909 glGenTextures(1, &id_);
1910 ScopedTexture2DBinder binder(decoder_, id_);
1911 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1912 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1913 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1914 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1916 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
1917 // never called on an offscreen context, no data will ever be uploaded to the
1918 // saved offscreen color texture (it is deferred until to when SwapBuffers
1919 // is called). My idea is that some nvidia drivers might have a bug where
1920 // deleting a texture that has never been populated might cause a
1921 // crash.
1922 glTexImage2D(
1923 GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
1925 bytes_allocated_ = 16u * 16u * 4u;
1926 memory_tracker_.TrackMemAlloc(bytes_allocated_);
1929 bool BackTexture::AllocateStorage(
1930 const gfx::Size& size, GLenum format, bool zero) {
1931 DCHECK_NE(id_, 0u);
1932 ScopedGLErrorSuppressor suppressor("BackTexture::AllocateStorage", decoder_);
1933 ScopedTexture2DBinder binder(decoder_, id_);
1934 uint32 image_size = 0;
1935 GLES2Util::ComputeImageDataSizes(
1936 size.width(), size.height(), format, GL_UNSIGNED_BYTE, 8, &image_size,
1937 NULL, NULL);
1939 if (!memory_tracker_.EnsureGPUMemoryAvailable(image_size)) {
1940 return false;
1943 scoped_ptr<char[]> zero_data;
1944 if (zero) {
1945 zero_data.reset(new char[image_size]);
1946 memset(zero_data.get(), 0, image_size);
1949 glTexImage2D(GL_TEXTURE_2D,
1950 0, // mip level
1951 format,
1952 size.width(),
1953 size.height(),
1954 0, // border
1955 format,
1956 GL_UNSIGNED_BYTE,
1957 zero_data.get());
1959 size_ = size;
1961 bool success = glGetError() == GL_NO_ERROR;
1962 if (success) {
1963 memory_tracker_.TrackMemFree(bytes_allocated_);
1964 bytes_allocated_ = image_size;
1965 memory_tracker_.TrackMemAlloc(bytes_allocated_);
1967 return success;
1970 void BackTexture::Copy(const gfx::Size& size, GLenum format) {
1971 DCHECK_NE(id_, 0u);
1972 ScopedGLErrorSuppressor suppressor("BackTexture::Copy", decoder_);
1973 ScopedTexture2DBinder binder(decoder_, id_);
1974 glCopyTexImage2D(GL_TEXTURE_2D,
1975 0, // level
1976 format,
1977 0, 0,
1978 size.width(),
1979 size.height(),
1980 0); // border
1983 void BackTexture::Destroy() {
1984 if (id_ != 0) {
1985 ScopedGLErrorSuppressor suppressor("BackTexture::Destroy", decoder_);
1986 glDeleteTextures(1, &id_);
1987 id_ = 0;
1989 memory_tracker_.TrackMemFree(bytes_allocated_);
1990 bytes_allocated_ = 0;
1993 void BackTexture::Invalidate() {
1994 id_ = 0;
1997 BackRenderbuffer::BackRenderbuffer(GLES2DecoderImpl* decoder)
1998 : decoder_(decoder),
1999 memory_tracker_(decoder->memory_tracker(), MemoryTracker::kUnmanaged),
2000 bytes_allocated_(0),
2001 id_(0) {
2004 BackRenderbuffer::~BackRenderbuffer() {
2005 // This does not destroy the render buffer because that would require that
2006 // the associated GL context was current. Just check that it was explicitly
2007 // destroyed.
2008 DCHECK_EQ(id_, 0u);
2011 void BackRenderbuffer::Create() {
2012 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Create", decoder_);
2013 Destroy();
2014 glGenRenderbuffersEXT(1, &id_);
2017 bool BackRenderbuffer::AllocateStorage(const gfx::Size& size, GLenum format,
2018 GLsizei samples) {
2019 ScopedGLErrorSuppressor suppressor(
2020 "BackRenderbuffer::AllocateStorage", decoder_);
2021 ScopedRenderBufferBinder binder(decoder_, id_);
2023 uint32 estimated_size = 0;
2024 if (!RenderbufferManager::ComputeEstimatedRenderbufferSize(
2025 size.width(), size.height(), samples, format, &estimated_size)) {
2026 return false;
2029 if (!memory_tracker_.EnsureGPUMemoryAvailable(estimated_size)) {
2030 return false;
2033 if (samples <= 1) {
2034 glRenderbufferStorageEXT(GL_RENDERBUFFER,
2035 format,
2036 size.width(),
2037 size.height());
2038 } else {
2039 if (GLES2Decoder::IsAngle()) {
2040 glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER,
2041 samples,
2042 format,
2043 size.width(),
2044 size.height());
2045 } else {
2046 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER,
2047 samples,
2048 format,
2049 size.width(),
2050 size.height());
2053 bool success = glGetError() == GL_NO_ERROR;
2054 if (success) {
2055 memory_tracker_.TrackMemFree(bytes_allocated_);
2056 bytes_allocated_ = estimated_size;
2057 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2059 return success;
2062 void BackRenderbuffer::Destroy() {
2063 if (id_ != 0) {
2064 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Destroy", decoder_);
2065 glDeleteRenderbuffersEXT(1, &id_);
2066 id_ = 0;
2068 memory_tracker_.TrackMemFree(bytes_allocated_);
2069 bytes_allocated_ = 0;
2072 void BackRenderbuffer::Invalidate() {
2073 id_ = 0;
2076 BackFramebuffer::BackFramebuffer(GLES2DecoderImpl* decoder)
2077 : decoder_(decoder),
2078 id_(0) {
2081 BackFramebuffer::~BackFramebuffer() {
2082 // This does not destroy the frame buffer because that would require that
2083 // the associated GL context was current. Just check that it was explicitly
2084 // destroyed.
2085 DCHECK_EQ(id_, 0u);
2088 void BackFramebuffer::Create() {
2089 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Create", decoder_);
2090 Destroy();
2091 glGenFramebuffersEXT(1, &id_);
2094 void BackFramebuffer::AttachRenderTexture(BackTexture* texture) {
2095 DCHECK_NE(id_, 0u);
2096 ScopedGLErrorSuppressor suppressor(
2097 "BackFramebuffer::AttachRenderTexture", decoder_);
2098 ScopedFrameBufferBinder binder(decoder_, id_);
2099 GLuint attach_id = texture ? texture->id() : 0;
2100 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
2101 GL_COLOR_ATTACHMENT0,
2102 GL_TEXTURE_2D,
2103 attach_id,
2107 void BackFramebuffer::AttachRenderBuffer(GLenum target,
2108 BackRenderbuffer* render_buffer) {
2109 DCHECK_NE(id_, 0u);
2110 ScopedGLErrorSuppressor suppressor(
2111 "BackFramebuffer::AttachRenderBuffer", decoder_);
2112 ScopedFrameBufferBinder binder(decoder_, id_);
2113 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
2114 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
2115 target,
2116 GL_RENDERBUFFER,
2117 attach_id);
2120 void BackFramebuffer::Destroy() {
2121 if (id_ != 0) {
2122 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Destroy", decoder_);
2123 glDeleteFramebuffersEXT(1, &id_);
2124 id_ = 0;
2128 void BackFramebuffer::Invalidate() {
2129 id_ = 0;
2132 GLenum BackFramebuffer::CheckStatus() {
2133 DCHECK_NE(id_, 0u);
2134 ScopedGLErrorSuppressor suppressor("BackFramebuffer::CheckStatus", decoder_);
2135 ScopedFrameBufferBinder binder(decoder_, id_);
2136 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
2139 GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
2140 return new GLES2DecoderImpl(group);
2143 GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
2144 : GLES2Decoder(),
2145 group_(group),
2146 logger_(&debug_marker_manager_),
2147 state_(group_->feature_info(), &logger_),
2148 unpack_flip_y_(false),
2149 unpack_premultiply_alpha_(false),
2150 unpack_unpremultiply_alpha_(false),
2151 attrib_0_buffer_id_(0),
2152 attrib_0_buffer_matches_value_(true),
2153 attrib_0_size_(0),
2154 fixed_attrib_buffer_id_(0),
2155 fixed_attrib_buffer_size_(0),
2156 clear_state_dirty_(true),
2157 offscreen_target_color_format_(0),
2158 offscreen_target_depth_format_(0),
2159 offscreen_target_stencil_format_(0),
2160 offscreen_target_samples_(0),
2161 offscreen_target_buffer_preserved_(true),
2162 offscreen_saved_color_format_(0),
2163 back_buffer_color_format_(0),
2164 back_buffer_has_depth_(false),
2165 back_buffer_has_stencil_(false),
2166 backbuffer_needs_clear_bits_(0),
2167 teximage2d_faster_than_texsubimage2d_(true),
2168 current_decoder_error_(error::kNoError),
2169 use_shader_translator_(true),
2170 validators_(group_->feature_info()->validators()),
2171 feature_info_(group_->feature_info()),
2172 tex_image_2d_failed_(false),
2173 frame_number_(0),
2174 has_robustness_extension_(false),
2175 reset_status_(GL_NO_ERROR),
2176 reset_by_robustness_extension_(false),
2177 force_webgl_glsl_validation_(false),
2178 derivatives_explicitly_enabled_(false),
2179 frag_depth_explicitly_enabled_(false),
2180 draw_buffers_explicitly_enabled_(false),
2181 compile_shader_always_succeeds_(false),
2182 service_logging_(CommandLine::ForCurrentProcess()->HasSwitch(
2183 switches::kEnableGPUServiceLoggingGPU)),
2184 viewport_max_width_(0),
2185 viewport_max_height_(0),
2186 texture_upload_count_(0) {
2187 DCHECK(group);
2189 attrib_0_value_.v[0] = 0.0f;
2190 attrib_0_value_.v[1] = 0.0f;
2191 attrib_0_value_.v[2] = 0.0f;
2192 attrib_0_value_.v[3] = 1.0f;
2194 // The shader translator is used for WebGL even when running on EGL
2195 // because additional restrictions are needed (like only enabling
2196 // GL_OES_standard_derivatives on demand). It is used for the unit
2197 // tests because GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes
2198 // the empty string to CompileShader and this is not a valid shader.
2199 if (gfx::GetGLImplementation() == gfx::kGLImplementationMockGL ||
2200 CommandLine::ForCurrentProcess()->HasSwitch(
2201 switches::kDisableGLSLTranslator)) {
2202 use_shader_translator_ = false;
2205 // TODO(gman): Consider setting this based on GPU and/or driver.
2206 if (IsAngle()) {
2207 teximage2d_faster_than_texsubimage2d_ = false;
2211 GLES2DecoderImpl::~GLES2DecoderImpl() {
2214 bool GLES2DecoderImpl::Initialize(
2215 const scoped_refptr<gfx::GLSurface>& surface,
2216 const scoped_refptr<gfx::GLContext>& context,
2217 bool offscreen,
2218 const gfx::Size& size,
2219 const DisallowedFeatures& disallowed_features,
2220 const char* allowed_extensions,
2221 const std::vector<int32>& attribs) {
2222 TRACE_EVENT0("gpu", "GLES2DecoderImpl::Initialize");
2223 DCHECK(context->IsCurrent(surface.get()));
2224 DCHECK(!context_.get());
2226 set_initialized();
2227 gpu_tracer_ = GPUTracer::Create();
2229 if (CommandLine::ForCurrentProcess()->HasSwitch(
2230 switches::kEnableGPUDebugging)) {
2231 set_debug(true);
2234 if (CommandLine::ForCurrentProcess()->HasSwitch(
2235 switches::kEnableGPUCommandLogging)) {
2236 set_log_commands(true);
2239 compile_shader_always_succeeds_ = CommandLine::ForCurrentProcess()->HasSwitch(
2240 switches::kCompileShaderAlwaysSucceeds);
2243 // Take ownership of the context and surface. The surface can be replaced with
2244 // SetSurface.
2245 context_ = context;
2246 surface_ = surface;
2248 if (!group_->Initialize(this, disallowed_features, allowed_extensions)) {
2249 LOG(ERROR) << "GpuScheduler::InitializeCommon failed because group "
2250 << "failed to initialize.";
2251 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
2252 Destroy(true);
2253 return false;
2255 CHECK_GL_ERROR();
2257 disallowed_features_ = disallowed_features;
2259 state_.attrib_values.resize(group_->max_vertex_attribs());
2260 default_vertex_attrib_manager_ = new VertexAttribManager();
2261 default_vertex_attrib_manager_->Initialize(group_->max_vertex_attribs());
2263 // vertex_attrib_manager is set to default_vertex_attrib_manager_ by this call
2264 DoBindVertexArrayOES(0);
2266 query_manager_.reset(new QueryManager(this, feature_info_.get()));
2267 vertex_array_manager_.reset(new VertexArrayManager());
2269 util_.set_num_compressed_texture_formats(
2270 validators_->compressed_texture_format.GetValues().size());
2272 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2273 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
2274 // OpenGL ES 2.0 does not have this issue.
2275 glEnableVertexAttribArray(0);
2277 glGenBuffersARB(1, &attrib_0_buffer_id_);
2278 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
2279 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
2280 glBindBuffer(GL_ARRAY_BUFFER, 0);
2281 glGenBuffersARB(1, &fixed_attrib_buffer_id_);
2283 state_.texture_units.resize(group_->max_texture_units());
2284 for (uint32 tt = 0; tt < state_.texture_units.size(); ++tt) {
2285 glActiveTexture(GL_TEXTURE0 + tt);
2286 // We want the last bind to be 2D.
2287 TextureRef* ref;
2288 if (features().oes_egl_image_external) {
2289 ref = texture_manager()->GetDefaultTextureInfo(
2290 GL_TEXTURE_EXTERNAL_OES);
2291 state_.texture_units[tt].bound_texture_external_oes = ref;
2292 glBindTexture(GL_TEXTURE_EXTERNAL_OES, ref->service_id());
2294 if (features().arb_texture_rectangle) {
2295 ref = texture_manager()->GetDefaultTextureInfo(
2296 GL_TEXTURE_RECTANGLE_ARB);
2297 state_.texture_units[tt].bound_texture_rectangle_arb = ref;
2298 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, ref->service_id());
2300 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
2301 state_.texture_units[tt].bound_texture_cube_map = ref;
2302 glBindTexture(GL_TEXTURE_CUBE_MAP, ref->service_id());
2303 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
2304 state_.texture_units[tt].bound_texture_2d = ref;
2305 glBindTexture(GL_TEXTURE_2D, ref->service_id());
2307 glActiveTexture(GL_TEXTURE0);
2308 CHECK_GL_ERROR();
2310 ContextCreationAttribParser attrib_parser;
2311 if (!attrib_parser.Parse(attribs))
2312 return false;
2314 if (offscreen) {
2315 if (attrib_parser.samples_ > 0 && attrib_parser.sample_buffers_ > 0 &&
2316 features().chromium_framebuffer_multisample) {
2317 // Per ext_framebuffer_multisample spec, need max bound on sample count.
2318 // max_sample_count must be initialized to a sane value. If
2319 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2320 GLint max_sample_count = 1;
2321 glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count);
2322 offscreen_target_samples_ = std::min(attrib_parser.samples_,
2323 max_sample_count);
2324 } else {
2325 offscreen_target_samples_ = 1;
2327 offscreen_target_buffer_preserved_ = attrib_parser.buffer_preserved_;
2329 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
2330 const bool rgb8_supported =
2331 context_->HasExtension("GL_OES_rgb8_rgba8");
2332 // The only available default render buffer formats in GLES2 have very
2333 // little precision. Don't enable multisampling unless 8-bit render
2334 // buffer formats are available--instead fall back to 8-bit textures.
2335 if (rgb8_supported && offscreen_target_samples_ > 1) {
2336 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2337 GL_RGBA8 : GL_RGB8;
2338 } else {
2339 offscreen_target_samples_ = 1;
2340 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2341 GL_RGBA : GL_RGB;
2344 // ANGLE only supports packed depth/stencil formats, so use it if it is
2345 // available.
2346 const bool depth24_stencil8_supported =
2347 context_->HasExtension("GL_OES_packed_depth_stencil");
2348 VLOG(1) << "GL_OES_packed_depth_stencil "
2349 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
2350 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
2351 depth24_stencil8_supported) {
2352 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2353 offscreen_target_stencil_format_ = 0;
2354 } else {
2355 // It may be the case that this depth/stencil combination is not
2356 // supported, but this will be checked later by CheckFramebufferStatus.
2357 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
2358 GL_DEPTH_COMPONENT16 : 0;
2359 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
2360 GL_STENCIL_INDEX8 : 0;
2362 } else {
2363 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2364 GL_RGBA : GL_RGB;
2366 // If depth is requested at all, use the packed depth stencil format if
2367 // it's available, as some desktop GL drivers don't support any non-packed
2368 // formats for depth attachments.
2369 const bool depth24_stencil8_supported =
2370 context_->HasExtension("GL_EXT_packed_depth_stencil");
2371 VLOG(1) << "GL_EXT_packed_depth_stencil "
2372 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
2374 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
2375 depth24_stencil8_supported) {
2376 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2377 offscreen_target_stencil_format_ = 0;
2378 } else {
2379 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
2380 GL_DEPTH_COMPONENT : 0;
2381 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
2382 GL_STENCIL_INDEX : 0;
2386 offscreen_saved_color_format_ = attrib_parser.alpha_size_ > 0 ?
2387 GL_RGBA : GL_RGB;
2389 // Create the target frame buffer. This is the one that the client renders
2390 // directly to.
2391 offscreen_target_frame_buffer_.reset(new BackFramebuffer(this));
2392 offscreen_target_frame_buffer_->Create();
2393 // Due to GLES2 format limitations, either the color texture (for
2394 // non-multisampling) or the color render buffer (for multisampling) will be
2395 // attached to the offscreen frame buffer. The render buffer has more
2396 // limited formats available to it, but the texture can't do multisampling.
2397 if (IsOffscreenBufferMultisampled()) {
2398 offscreen_target_color_render_buffer_.reset(new BackRenderbuffer(this));
2399 offscreen_target_color_render_buffer_->Create();
2400 } else {
2401 offscreen_target_color_texture_.reset(new BackTexture(this));
2402 offscreen_target_color_texture_->Create();
2404 offscreen_target_depth_render_buffer_.reset(new BackRenderbuffer(this));
2405 offscreen_target_depth_render_buffer_->Create();
2406 offscreen_target_stencil_render_buffer_.reset(new BackRenderbuffer(this));
2407 offscreen_target_stencil_render_buffer_->Create();
2409 // Create the saved offscreen texture. The target frame buffer is copied
2410 // here when SwapBuffers is called.
2411 offscreen_saved_frame_buffer_.reset(new BackFramebuffer(this));
2412 offscreen_saved_frame_buffer_->Create();
2414 offscreen_saved_color_texture_.reset(new BackTexture(this));
2415 offscreen_saved_color_texture_->Create();
2417 // Allocate the render buffers at their initial size and check the status
2418 // of the frame buffers is okay.
2419 if (!ResizeOffscreenFrameBuffer(size)) {
2420 LOG(ERROR) << "Could not allocate offscreen buffer storage.";
2421 Destroy(true);
2422 return false;
2425 // Allocate the offscreen saved color texture.
2426 DCHECK(offscreen_saved_color_format_);
2427 offscreen_saved_color_texture_->AllocateStorage(
2428 gfx::Size(1, 1), offscreen_saved_color_format_, true);
2430 offscreen_saved_frame_buffer_->AttachRenderTexture(
2431 offscreen_saved_color_texture_.get());
2432 if (offscreen_saved_frame_buffer_->CheckStatus() !=
2433 GL_FRAMEBUFFER_COMPLETE) {
2434 LOG(ERROR) << "Offscreen saved FBO was incomplete.";
2435 Destroy(true);
2436 return false;
2439 // Bind to the new default frame buffer (the offscreen target frame buffer).
2440 // This should now be associated with ID zero.
2441 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2442 } else {
2443 glBindFramebufferEXT(GL_FRAMEBUFFER, GetBackbufferServiceId());
2444 // These are NOT if the back buffer has these proprorties. They are
2445 // if we want the command buffer to enforce them regardless of what
2446 // the real backbuffer is assuming the real back buffer gives us more than
2447 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2448 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2449 // can't do anything about that.
2451 GLint v = 0;
2452 glGetIntegerv(GL_ALPHA_BITS, &v);
2453 // This checks if the user requested RGBA and we have RGBA then RGBA. If the
2454 // user requested RGB then RGB. If the user did not specify a preference
2455 // than use whatever we were given. Same for DEPTH and STENCIL.
2456 back_buffer_color_format_ =
2457 (attrib_parser.alpha_size_ != 0 && v > 0) ? GL_RGBA : GL_RGB;
2458 glGetIntegerv(GL_DEPTH_BITS, &v);
2459 back_buffer_has_depth_ = attrib_parser.depth_size_ != 0 && v > 0;
2460 glGetIntegerv(GL_STENCIL_BITS, &v);
2461 back_buffer_has_stencil_ = attrib_parser.stencil_size_ != 0 && v > 0;
2464 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2465 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2466 // isn't well documented; it was discovered in the Khronos OpenGL ES
2467 // mailing list archives. It also implicitly enables the desktop GL
2468 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2469 // variable in fragment shaders.
2470 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2471 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
2472 glEnable(GL_POINT_SPRITE);
2475 has_robustness_extension_ =
2476 context->HasExtension("GL_ARB_robustness") ||
2477 context->HasExtension("GL_EXT_robustness");
2479 if (!InitializeShaderTranslator()) {
2480 return false;
2483 state_.viewport_width = size.width();
2484 state_.viewport_height = size.height();
2486 GLint viewport_params[4] = { 0 };
2487 glGetIntegerv(GL_MAX_VIEWPORT_DIMS, viewport_params);
2488 viewport_max_width_ = viewport_params[0];
2489 viewport_max_height_ = viewport_params[1];
2491 state_.scissor_width = state_.viewport_width;
2492 state_.scissor_height = state_.viewport_height;
2494 // Set all the default state because some GL drivers get it wrong.
2495 state_.InitCapabilities();
2496 state_.InitState();
2497 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
2499 DoBindBuffer(GL_ARRAY_BUFFER, 0);
2500 DoBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
2501 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2502 DoBindRenderbuffer(GL_RENDERBUFFER, 0);
2504 // Clear the backbuffer.
2505 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2507 if (feature_info_->workarounds().reverse_point_sprite_coord_origin) {
2508 glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT);
2511 if (feature_info_->workarounds().unbind_fbo_on_context_switch) {
2512 context_->SetUnbindFboOnMakeCurrent();
2515 // Only compositor contexts are known to use only the subset of GL
2516 // that can be safely migrated between the iGPU and the dGPU. Mark
2517 // those contexts as safe to forcibly transition between the GPUs.
2518 // http://crbug.com/180876, http://crbug.com/227228
2519 if (!offscreen)
2520 context_->SetSafeToForceGpuSwitch();
2522 async_pixel_transfer_manager_.reset(
2523 AsyncPixelTransferManager::Create(context.get()));
2524 async_pixel_transfer_manager_->Initialize(texture_manager());
2526 return true;
2529 void GLES2DecoderImpl::UpdateCapabilities() {
2530 util_.set_num_compressed_texture_formats(
2531 validators_->compressed_texture_format.GetValues().size());
2532 util_.set_num_shader_binary_formats(
2533 validators_->shader_binary_format.GetValues().size());
2536 bool GLES2DecoderImpl::InitializeShaderTranslator() {
2537 TRACE_EVENT0("gpu", "GLES2DecoderImpl::InitializeShaderTranslator");
2539 if (!use_shader_translator_) {
2540 return true;
2542 ShBuiltInResources resources;
2543 ShInitBuiltInResources(&resources);
2544 resources.MaxVertexAttribs = group_->max_vertex_attribs();
2545 resources.MaxVertexUniformVectors =
2546 group_->max_vertex_uniform_vectors();
2547 resources.MaxVaryingVectors = group_->max_varying_vectors();
2548 resources.MaxVertexTextureImageUnits =
2549 group_->max_vertex_texture_image_units();
2550 resources.MaxCombinedTextureImageUnits = group_->max_texture_units();
2551 resources.MaxTextureImageUnits = group_->max_texture_image_units();
2552 resources.MaxFragmentUniformVectors =
2553 group_->max_fragment_uniform_vectors();
2554 resources.MaxDrawBuffers = group_->max_draw_buffers();
2555 resources.MaxExpressionComplexity = 256;
2556 resources.MaxCallStackDepth = 256;
2558 #if (ANGLE_SH_VERSION >= 110)
2559 GLint range[2] = { 0, 0 };
2560 GLint precision = 0;
2561 GetShaderPrecisionFormatImpl(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT,
2562 range, &precision);
2563 resources.FragmentPrecisionHigh =
2564 PrecisionMeetsSpecForHighpFloat(range[0], range[1], precision);
2565 #endif
2567 if (force_webgl_glsl_validation_) {
2568 resources.OES_standard_derivatives = derivatives_explicitly_enabled_;
2569 resources.EXT_frag_depth = frag_depth_explicitly_enabled_;
2570 resources.EXT_draw_buffers = draw_buffers_explicitly_enabled_;
2571 } else {
2572 resources.OES_standard_derivatives =
2573 features().oes_standard_derivatives ? 1 : 0;
2574 resources.ARB_texture_rectangle =
2575 features().arb_texture_rectangle ? 1 : 0;
2576 resources.OES_EGL_image_external =
2577 features().oes_egl_image_external ? 1 : 0;
2578 resources.EXT_draw_buffers =
2579 features().ext_draw_buffers ? 1 : 0;
2580 resources.EXT_frag_depth =
2581 features().ext_frag_depth ? 1 : 0;
2584 ShShaderSpec shader_spec = force_webgl_glsl_validation_ ? SH_WEBGL_SPEC
2585 : SH_GLES2_SPEC;
2586 if (shader_spec == SH_WEBGL_SPEC && features().enable_shader_name_hashing)
2587 #if !defined(ANGLE_SH_VERSION) || ANGLE_SH_VERSION < 108
2588 resources.HashFunction = &CityHashForAngle;
2589 #else
2590 resources.HashFunction = &CityHash64;
2591 #endif
2592 else
2593 resources.HashFunction = NULL;
2594 ShaderTranslatorInterface::GlslImplementationType implementation_type =
2595 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 ?
2596 ShaderTranslatorInterface::kGlslES : ShaderTranslatorInterface::kGlsl;
2597 ShaderTranslatorInterface::GlslBuiltInFunctionBehavior function_behavior =
2598 workarounds().needs_glsl_built_in_function_emulation ?
2599 ShaderTranslatorInterface::kGlslBuiltInFunctionEmulated :
2600 ShaderTranslatorInterface::kGlslBuiltInFunctionOriginal;
2602 ShaderTranslatorCache* cache = ShaderTranslatorCache::GetInstance();
2603 vertex_translator_ = cache->GetTranslator(
2604 SH_VERTEX_SHADER, shader_spec, &resources,
2605 implementation_type, function_behavior);
2606 if (!vertex_translator_.get()) {
2607 LOG(ERROR) << "Could not initialize vertex shader translator.";
2608 Destroy(true);
2609 return false;
2612 fragment_translator_ = cache->GetTranslator(
2613 SH_FRAGMENT_SHADER, shader_spec, &resources,
2614 implementation_type, function_behavior);
2615 if (!fragment_translator_.get()) {
2616 LOG(ERROR) << "Could not initialize fragment shader translator.";
2617 Destroy(true);
2618 return false;
2620 return true;
2623 bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
2624 for (GLsizei ii = 0; ii < n; ++ii) {
2625 if (GetBuffer(client_ids[ii])) {
2626 return false;
2629 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
2630 glGenBuffersARB(n, service_ids.get());
2631 for (GLsizei ii = 0; ii < n; ++ii) {
2632 CreateBuffer(client_ids[ii], service_ids[ii]);
2634 return true;
2637 bool GLES2DecoderImpl::GenFramebuffersHelper(
2638 GLsizei n, const GLuint* client_ids) {
2639 for (GLsizei ii = 0; ii < n; ++ii) {
2640 if (GetFramebuffer(client_ids[ii])) {
2641 return false;
2644 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
2645 glGenFramebuffersEXT(n, service_ids.get());
2646 for (GLsizei ii = 0; ii < n; ++ii) {
2647 CreateFramebuffer(client_ids[ii], service_ids[ii]);
2649 return true;
2652 bool GLES2DecoderImpl::GenRenderbuffersHelper(
2653 GLsizei n, const GLuint* client_ids) {
2654 for (GLsizei ii = 0; ii < n; ++ii) {
2655 if (GetRenderbuffer(client_ids[ii])) {
2656 return false;
2659 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
2660 glGenRenderbuffersEXT(n, service_ids.get());
2661 for (GLsizei ii = 0; ii < n; ++ii) {
2662 CreateRenderbuffer(client_ids[ii], service_ids[ii]);
2664 return true;
2667 bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
2668 for (GLsizei ii = 0; ii < n; ++ii) {
2669 if (GetTexture(client_ids[ii])) {
2670 return false;
2673 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
2674 glGenTextures(n, service_ids.get());
2675 for (GLsizei ii = 0; ii < n; ++ii) {
2676 CreateTexture(client_ids[ii], service_ids[ii]);
2678 return true;
2681 void GLES2DecoderImpl::DeleteBuffersHelper(
2682 GLsizei n, const GLuint* client_ids) {
2683 for (GLsizei ii = 0; ii < n; ++ii) {
2684 Buffer* buffer = GetBuffer(client_ids[ii]);
2685 if (buffer && !buffer->IsDeleted()) {
2686 state_.vertex_attrib_manager->Unbind(buffer);
2687 if (state_.bound_array_buffer.get() == buffer) {
2688 state_.bound_array_buffer = NULL;
2690 RemoveBuffer(client_ids[ii]);
2695 void GLES2DecoderImpl::DeleteFramebuffersHelper(
2696 GLsizei n, const GLuint* client_ids) {
2697 bool supports_separate_framebuffer_binds =
2698 features().chromium_framebuffer_multisample;
2700 for (GLsizei ii = 0; ii < n; ++ii) {
2701 Framebuffer* framebuffer =
2702 GetFramebuffer(client_ids[ii]);
2703 if (framebuffer && !framebuffer->IsDeleted()) {
2704 if (framebuffer == state_.bound_draw_framebuffer.get()) {
2705 state_.bound_draw_framebuffer = NULL;
2706 clear_state_dirty_ = true;
2707 GLenum target = supports_separate_framebuffer_binds ?
2708 GL_DRAW_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
2709 glBindFramebufferEXT(target, GetBackbufferServiceId());
2711 if (framebuffer == state_.bound_read_framebuffer.get()) {
2712 state_.bound_read_framebuffer = NULL;
2713 GLenum target = supports_separate_framebuffer_binds ?
2714 GL_READ_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
2715 glBindFramebufferEXT(target, GetBackbufferServiceId());
2717 OnFboChanged();
2718 RemoveFramebuffer(client_ids[ii]);
2723 void GLES2DecoderImpl::DeleteRenderbuffersHelper(
2724 GLsizei n, const GLuint* client_ids) {
2725 bool supports_separate_framebuffer_binds =
2726 features().chromium_framebuffer_multisample;
2727 for (GLsizei ii = 0; ii < n; ++ii) {
2728 Renderbuffer* renderbuffer =
2729 GetRenderbuffer(client_ids[ii]);
2730 if (renderbuffer && !renderbuffer->IsDeleted()) {
2731 if (state_.bound_renderbuffer.get() == renderbuffer) {
2732 state_.bound_renderbuffer = NULL;
2734 // Unbind from current framebuffers.
2735 if (supports_separate_framebuffer_binds) {
2736 if (state_.bound_read_framebuffer.get()) {
2737 state_.bound_read_framebuffer
2738 ->UnbindRenderbuffer(GL_READ_FRAMEBUFFER_EXT, renderbuffer);
2740 if (state_.bound_draw_framebuffer.get()) {
2741 state_.bound_draw_framebuffer
2742 ->UnbindRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT, renderbuffer);
2744 } else {
2745 if (state_.bound_draw_framebuffer.get()) {
2746 state_.bound_draw_framebuffer
2747 ->UnbindRenderbuffer(GL_FRAMEBUFFER, renderbuffer);
2750 clear_state_dirty_ = true;
2751 RemoveRenderbuffer(client_ids[ii]);
2756 void GLES2DecoderImpl::DeleteTexturesHelper(
2757 GLsizei n, const GLuint* client_ids) {
2758 bool supports_separate_framebuffer_binds =
2759 features().chromium_framebuffer_multisample;
2760 for (GLsizei ii = 0; ii < n; ++ii) {
2761 TextureRef* texture_ref = GetTexture(client_ids[ii]);
2762 if (texture_ref) {
2763 Texture* texture = texture_ref->texture();
2764 if (texture->IsAttachedToFramebuffer()) {
2765 clear_state_dirty_ = true;
2767 // Unbind texture_ref from texture_ref units.
2768 for (size_t jj = 0; jj < state_.texture_units.size(); ++jj) {
2769 state_.texture_units[jj].Unbind(texture_ref);
2771 // Unbind from current framebuffers.
2772 if (supports_separate_framebuffer_binds) {
2773 if (state_.bound_read_framebuffer.get()) {
2774 state_.bound_read_framebuffer
2775 ->UnbindTexture(GL_READ_FRAMEBUFFER_EXT, texture_ref);
2777 if (state_.bound_draw_framebuffer.get()) {
2778 state_.bound_draw_framebuffer
2779 ->UnbindTexture(GL_DRAW_FRAMEBUFFER_EXT, texture_ref);
2781 } else {
2782 if (state_.bound_draw_framebuffer.get()) {
2783 state_.bound_draw_framebuffer
2784 ->UnbindTexture(GL_FRAMEBUFFER, texture_ref);
2787 #if defined(OS_MACOSX)
2788 GLuint service_id = texture->service_id();
2789 if (texture->target() == GL_TEXTURE_RECTANGLE_ARB) {
2790 ReleaseIOSurfaceForTexture(service_id);
2792 #endif
2793 RemoveTexture(client_ids[ii]);
2798 // } // anonymous namespace
2800 bool GLES2DecoderImpl::MakeCurrent() {
2801 if (!context_.get() || !context_->MakeCurrent(surface_.get()))
2802 return false;
2804 if (WasContextLost()) {
2805 LOG(ERROR) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
2807 // Some D3D drivers cannot recover from device lost in the GPU process
2808 // sandbox. Allow a new GPU process to launch.
2809 if (workarounds().exit_on_context_lost) {
2810 LOG(ERROR) << "Exiting GPU process because some drivers cannot reset"
2811 << " a D3D device in the Chrome GPU process sandbox.";
2812 exit(0);
2815 return false;
2818 ProcessFinishedAsyncTransfers();
2819 if (workarounds().flush_on_context_switch)
2820 glFlush();
2822 // Rebind the FBO if it was unbound by the context.
2823 if (workarounds().unbind_fbo_on_context_switch)
2824 RestoreFramebufferBindings();
2826 clear_state_dirty_ = true;
2828 return true;
2831 void GLES2DecoderImpl::ProcessFinishedAsyncTransfers() {
2832 ProcessPendingReadPixels();
2833 if (engine() && query_manager_.get())
2834 query_manager_->ProcessPendingTransferQueries();
2836 // TODO(epenner): Is there a better place to do this?
2837 // This needs to occur before we execute any batch of commands
2838 // from the client, as the client may have recieved an async
2839 // completion while issuing those commands.
2840 // "DidFlushStart" would be ideal if we had such a callback.
2841 async_pixel_transfer_manager_->BindCompletedAsyncTransfers();
2844 void GLES2DecoderImpl::ReleaseCurrent() {
2845 if (context_.get())
2846 context_->ReleaseCurrent(surface_.get());
2849 void GLES2DecoderImpl::RestoreCurrentRenderbufferBindings() {
2850 Renderbuffer* renderbuffer =
2851 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
2852 glBindRenderbufferEXT(
2853 GL_RENDERBUFFER, renderbuffer ? renderbuffer->service_id() : 0);
2856 static void RebindCurrentFramebuffer(
2857 GLenum target,
2858 Framebuffer* framebuffer,
2859 GLuint back_buffer_service_id) {
2860 GLuint framebuffer_id = framebuffer ? framebuffer->service_id() : 0;
2862 if (framebuffer_id == 0) {
2863 framebuffer_id = back_buffer_service_id;
2866 glBindFramebufferEXT(target, framebuffer_id);
2869 void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
2870 clear_state_dirty_ = true;
2872 if (!features().chromium_framebuffer_multisample) {
2873 RebindCurrentFramebuffer(
2874 GL_FRAMEBUFFER,
2875 state_.bound_draw_framebuffer.get(),
2876 GetBackbufferServiceId());
2877 } else {
2878 RebindCurrentFramebuffer(
2879 GL_READ_FRAMEBUFFER_EXT,
2880 state_.bound_read_framebuffer.get(),
2881 GetBackbufferServiceId());
2882 RebindCurrentFramebuffer(
2883 GL_DRAW_FRAMEBUFFER_EXT,
2884 state_.bound_draw_framebuffer.get(),
2885 GetBackbufferServiceId());
2887 OnFboChanged();
2890 void GLES2DecoderImpl::RestoreCurrentTexture2DBindings() {
2891 TextureUnit& info = state_.texture_units[0];
2892 GLuint last_id;
2893 if (info.bound_texture_2d.get()) {
2894 last_id = info.bound_texture_2d->service_id();
2895 } else {
2896 last_id = 0;
2899 glBindTexture(GL_TEXTURE_2D, last_id);
2900 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
2903 bool GLES2DecoderImpl::CheckFramebufferValid(
2904 Framebuffer* framebuffer,
2905 GLenum target, const char* func_name) {
2906 if (!framebuffer) {
2907 if (backbuffer_needs_clear_bits_) {
2908 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
2909 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1);
2910 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
2911 glClearStencil(0);
2912 glStencilMask(-1);
2913 glClearDepth(1.0f);
2914 glDepthMask(true);
2915 glDisable(GL_SCISSOR_TEST);
2916 glClear(backbuffer_needs_clear_bits_);
2917 backbuffer_needs_clear_bits_ = 0;
2918 RestoreClearState();
2920 return true;
2923 if (framebuffer_manager()->IsComplete(framebuffer)) {
2924 return true;
2927 GLenum completeness = framebuffer->IsPossiblyComplete();
2928 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
2929 LOCAL_SET_GL_ERROR(
2930 GL_INVALID_FRAMEBUFFER_OPERATION, func_name, "framebuffer incomplete");
2931 return false;
2934 // Are all the attachments cleared?
2935 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
2936 texture_manager()->HaveUnclearedMips()) {
2937 if (!framebuffer->IsCleared()) {
2938 // Can we clear them?
2939 if (framebuffer->GetStatus(texture_manager(), target) !=
2940 GL_FRAMEBUFFER_COMPLETE) {
2941 LOCAL_SET_GL_ERROR(
2942 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
2943 "framebuffer incomplete (clear)");
2944 return false;
2946 ClearUnclearedAttachments(target, framebuffer);
2950 if (!framebuffer_manager()->IsComplete(framebuffer)) {
2951 if (framebuffer->GetStatus(texture_manager(), target) !=
2952 GL_FRAMEBUFFER_COMPLETE) {
2953 LOCAL_SET_GL_ERROR(
2954 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
2955 "framebuffer incomplete (check)");
2956 return false;
2958 framebuffer_manager()->MarkAsComplete(framebuffer);
2961 // NOTE: At this point we don't know if the framebuffer is complete but
2962 // we DO know that everything that needs to be cleared has been cleared.
2963 return true;
2966 bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name) {
2967 if (!features().chromium_framebuffer_multisample) {
2968 bool valid = CheckFramebufferValid(
2969 state_.bound_draw_framebuffer.get(), GL_FRAMEBUFFER_EXT, func_name);
2971 if (valid)
2972 OnUseFramebuffer();
2974 return valid;
2976 return CheckFramebufferValid(state_.bound_draw_framebuffer.get(),
2977 GL_DRAW_FRAMEBUFFER_EXT,
2978 func_name) &&
2979 CheckFramebufferValid(state_.bound_read_framebuffer.get(),
2980 GL_READ_FRAMEBUFFER_EXT,
2981 func_name);
2984 gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
2985 Framebuffer* framebuffer =
2986 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
2987 if (framebuffer != NULL) {
2988 const Framebuffer::Attachment* attachment =
2989 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
2990 if (attachment) {
2991 return gfx::Size(attachment->width(), attachment->height());
2993 return gfx::Size(0, 0);
2994 } else if (offscreen_target_frame_buffer_.get()) {
2995 return offscreen_size_;
2996 } else {
2997 return surface_->GetSize();
3001 GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
3002 Framebuffer* framebuffer =
3003 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3004 if (framebuffer != NULL) {
3005 return framebuffer->GetColorAttachmentFormat();
3006 } else if (offscreen_target_frame_buffer_.get()) {
3007 return offscreen_target_color_format_;
3008 } else {
3009 return back_buffer_color_format_;
3013 GLenum GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
3014 Framebuffer* framebuffer =
3015 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3016 if (framebuffer != NULL) {
3017 return framebuffer->GetColorAttachmentFormat();
3018 } else if (offscreen_target_frame_buffer_.get()) {
3019 return offscreen_target_color_format_;
3020 } else {
3021 return back_buffer_color_format_;
3025 void GLES2DecoderImpl::UpdateParentTextureInfo() {
3026 if (!offscreen_saved_color_texture_info_.get())
3027 return;
3028 GLenum target = offscreen_saved_color_texture_info_->texture()->target();
3029 glBindTexture(target, offscreen_saved_color_texture_info_->service_id());
3030 texture_manager()->SetLevelInfo(
3031 offscreen_saved_color_texture_info_.get(),
3032 GL_TEXTURE_2D,
3033 0, // level
3034 GL_RGBA,
3035 offscreen_size_.width(),
3036 offscreen_size_.height(),
3037 1, // depth
3038 0, // border
3039 GL_RGBA,
3040 GL_UNSIGNED_BYTE,
3041 true);
3042 texture_manager()->SetParameter(
3043 "UpdateParentTextureInfo",
3044 GetErrorState(),
3045 offscreen_saved_color_texture_info_.get(),
3046 GL_TEXTURE_MAG_FILTER,
3047 GL_NEAREST);
3048 texture_manager()->SetParameter(
3049 "UpdateParentTextureInfo",
3050 GetErrorState(),
3051 offscreen_saved_color_texture_info_.get(),
3052 GL_TEXTURE_MIN_FILTER,
3053 GL_NEAREST);
3054 texture_manager()->SetParameter(
3055 "UpdateParentTextureInfo",
3056 GetErrorState(),
3057 offscreen_saved_color_texture_info_.get(),
3058 GL_TEXTURE_WRAP_S,
3059 GL_CLAMP_TO_EDGE);
3060 texture_manager()->SetParameter(
3061 "UpdateParentTextureInfo",
3062 GetErrorState(),
3063 offscreen_saved_color_texture_info_.get(),
3064 GL_TEXTURE_WRAP_T,
3065 GL_CLAMP_TO_EDGE);
3066 TextureRef* texture_ref = GetTextureInfoForTarget(target);
3067 glBindTexture(target, texture_ref ? texture_ref->service_id() : 0);
3070 void GLES2DecoderImpl::SetResizeCallback(
3071 const base::Callback<void(gfx::Size, float)>& callback) {
3072 resize_callback_ = callback;
3075 Logger* GLES2DecoderImpl::GetLogger() {
3076 return &logger_;
3079 ErrorState* GLES2DecoderImpl::GetErrorState() {
3080 return state_.GetErrorState();
3083 void GLES2DecoderImpl::SetShaderCacheCallback(
3084 const ShaderCacheCallback& callback) {
3085 shader_cache_callback_ = callback;
3088 void GLES2DecoderImpl::SetWaitSyncPointCallback(
3089 const WaitSyncPointCallback& callback) {
3090 wait_sync_point_callback_ = callback;
3093 AsyncPixelTransferManager*
3094 GLES2DecoderImpl::GetAsyncPixelTransferManager() {
3095 return async_pixel_transfer_manager_.get();
3098 void GLES2DecoderImpl::ResetAsyncPixelTransferManagerForTest() {
3099 async_pixel_transfer_manager_.reset();
3102 void GLES2DecoderImpl::SetAsyncPixelTransferManagerForTest(
3103 AsyncPixelTransferManager* manager) {
3104 async_pixel_transfer_manager_ = make_scoped_ptr(manager);
3107 bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
3108 uint32* service_texture_id) {
3109 TextureRef* texture_ref = texture_manager()->GetTexture(client_texture_id);
3110 if (texture_ref) {
3111 *service_texture_id = texture_ref->service_id();
3112 return true;
3114 return false;
3117 uint32 GLES2DecoderImpl::GetTextureUploadCount() {
3118 return texture_upload_count_ +
3119 async_pixel_transfer_manager_->GetTextureUploadCount();
3122 base::TimeDelta GLES2DecoderImpl::GetTotalTextureUploadTime() {
3123 return total_texture_upload_time_ +
3124 async_pixel_transfer_manager_->GetTotalTextureUploadTime();
3127 base::TimeDelta GLES2DecoderImpl::GetTotalProcessingCommandsTime() {
3128 return total_processing_commands_time_;
3131 void GLES2DecoderImpl::AddProcessingCommandsTime(base::TimeDelta time) {
3132 total_processing_commands_time_ += time;
3135 void GLES2DecoderImpl::Destroy(bool have_context) {
3136 if (!initialized())
3137 return;
3139 DCHECK(!have_context || context_->IsCurrent(NULL));
3141 // Unbind everything.
3142 state_.vertex_attrib_manager = NULL;
3143 default_vertex_attrib_manager_ = NULL;
3144 state_.texture_units.clear();
3145 state_.bound_array_buffer = NULL;
3146 state_.current_query = NULL;
3147 state_.current_program = NULL;
3148 state_.bound_read_framebuffer = NULL;
3149 state_.bound_draw_framebuffer = NULL;
3150 state_.bound_renderbuffer = NULL;
3152 if (offscreen_saved_color_texture_info_.get()) {
3153 DCHECK(offscreen_target_color_texture_);
3154 DCHECK_EQ(offscreen_saved_color_texture_info_->service_id(),
3155 offscreen_saved_color_texture_->id());
3156 offscreen_saved_color_texture_->Invalidate();
3157 offscreen_saved_color_texture_info_ = NULL;
3159 if (have_context) {
3160 if (copy_texture_CHROMIUM_.get()) {
3161 copy_texture_CHROMIUM_->Destroy();
3162 copy_texture_CHROMIUM_.reset();
3165 if (state_.current_program.get()) {
3166 program_manager()->UnuseProgram(shader_manager(),
3167 state_.current_program.get());
3168 state_.current_program = NULL;
3171 if (attrib_0_buffer_id_) {
3172 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
3174 if (fixed_attrib_buffer_id_) {
3175 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_);
3178 if (offscreen_target_frame_buffer_.get())
3179 offscreen_target_frame_buffer_->Destroy();
3180 if (offscreen_target_color_texture_.get())
3181 offscreen_target_color_texture_->Destroy();
3182 if (offscreen_target_color_render_buffer_.get())
3183 offscreen_target_color_render_buffer_->Destroy();
3184 if (offscreen_target_depth_render_buffer_.get())
3185 offscreen_target_depth_render_buffer_->Destroy();
3186 if (offscreen_target_stencil_render_buffer_.get())
3187 offscreen_target_stencil_render_buffer_->Destroy();
3188 if (offscreen_saved_frame_buffer_.get())
3189 offscreen_saved_frame_buffer_->Destroy();
3190 if (offscreen_saved_color_texture_.get())
3191 offscreen_saved_color_texture_->Destroy();
3192 if (offscreen_resolved_frame_buffer_.get())
3193 offscreen_resolved_frame_buffer_->Destroy();
3194 if (offscreen_resolved_color_texture_.get())
3195 offscreen_resolved_color_texture_->Destroy();
3196 } else {
3197 if (offscreen_target_frame_buffer_.get())
3198 offscreen_target_frame_buffer_->Invalidate();
3199 if (offscreen_target_color_texture_.get())
3200 offscreen_target_color_texture_->Invalidate();
3201 if (offscreen_target_color_render_buffer_.get())
3202 offscreen_target_color_render_buffer_->Invalidate();
3203 if (offscreen_target_depth_render_buffer_.get())
3204 offscreen_target_depth_render_buffer_->Invalidate();
3205 if (offscreen_target_stencil_render_buffer_.get())
3206 offscreen_target_stencil_render_buffer_->Invalidate();
3207 if (offscreen_saved_frame_buffer_.get())
3208 offscreen_saved_frame_buffer_->Invalidate();
3209 if (offscreen_saved_color_texture_.get())
3210 offscreen_saved_color_texture_->Invalidate();
3211 if (offscreen_resolved_frame_buffer_.get())
3212 offscreen_resolved_frame_buffer_->Invalidate();
3213 if (offscreen_resolved_color_texture_.get())
3214 offscreen_resolved_color_texture_->Invalidate();
3216 copy_texture_CHROMIUM_.reset();
3218 if (query_manager_.get()) {
3219 query_manager_->Destroy(have_context);
3220 query_manager_.reset();
3223 if (vertex_array_manager_ .get()) {
3224 vertex_array_manager_->Destroy(have_context);
3225 vertex_array_manager_.reset();
3228 offscreen_target_frame_buffer_.reset();
3229 offscreen_target_color_texture_.reset();
3230 offscreen_target_color_render_buffer_.reset();
3231 offscreen_target_depth_render_buffer_.reset();
3232 offscreen_target_stencil_render_buffer_.reset();
3233 offscreen_saved_frame_buffer_.reset();
3234 offscreen_saved_color_texture_.reset();
3235 offscreen_resolved_frame_buffer_.reset();
3236 offscreen_resolved_color_texture_.reset();
3238 // Should destroy the transfer manager before the texture manager held
3239 // by the context group.
3240 async_pixel_transfer_manager_.reset();
3242 if (group_.get()) {
3243 group_->Destroy(this, have_context);
3244 group_ = NULL;
3247 if (context_.get()) {
3248 context_->ReleaseCurrent(NULL);
3249 context_ = NULL;
3252 #if defined(OS_MACOSX)
3253 for (TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.begin();
3254 it != texture_to_io_surface_map_.end(); ++it) {
3255 CFRelease(it->second);
3257 texture_to_io_surface_map_.clear();
3258 #endif
3261 void GLES2DecoderImpl::SetSurface(
3262 const scoped_refptr<gfx::GLSurface>& surface) {
3263 DCHECK(context_->IsCurrent(NULL));
3264 DCHECK(surface_.get());
3265 surface_ = surface;
3266 RestoreCurrentFramebufferBindings();
3269 bool GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox& mailbox) {
3270 if (!offscreen_saved_color_texture_.get())
3271 return false;
3272 if (!offscreen_saved_color_texture_info_.get()) {
3273 GLuint service_id = offscreen_saved_color_texture_->id();
3274 offscreen_saved_color_texture_info_ = TextureRef::Create(
3275 texture_manager(), 0, service_id);
3276 texture_manager()->SetTarget(offscreen_saved_color_texture_info_.get(),
3277 GL_TEXTURE_2D);
3278 UpdateParentTextureInfo();
3280 gpu::gles2::MailboxName name;
3281 memcpy(name.key, mailbox.name, sizeof(mailbox.name));
3282 return mailbox_manager()->ProduceTexture(
3283 GL_TEXTURE_2D, name, offscreen_saved_color_texture_info_->texture());
3286 size_t GLES2DecoderImpl::GetBackbufferMemoryTotal() {
3287 size_t total = 0;
3288 if (offscreen_target_frame_buffer_.get()) {
3289 if (offscreen_target_color_texture_.get()) {
3290 total += offscreen_target_color_texture_->estimated_size();
3292 if (offscreen_target_color_render_buffer_.get()) {
3293 total += offscreen_target_color_render_buffer_->estimated_size();
3295 if (offscreen_target_depth_render_buffer_.get()) {
3296 total += offscreen_target_depth_render_buffer_->estimated_size();
3298 if (offscreen_target_stencil_render_buffer_.get()) {
3299 total += offscreen_target_stencil_render_buffer_->estimated_size();
3301 if (offscreen_saved_color_texture_.get()) {
3302 total += offscreen_saved_color_texture_->estimated_size();
3304 if (offscreen_resolved_color_texture_.get()) {
3305 total += offscreen_resolved_color_texture_->estimated_size();
3307 } else {
3308 gfx::Size size = surface_->GetSize();
3309 total += size.width() * size.height() *
3310 GLES2Util::RenderbufferBytesPerPixel(back_buffer_color_format_);
3312 return total;
3315 bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
3316 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
3317 if (!is_offscreen) {
3318 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
3319 << " with an onscreen framebuffer.";
3320 return false;
3323 if (offscreen_size_ == size)
3324 return true;
3326 offscreen_size_ = size;
3327 int w = offscreen_size_.width();
3328 int h = offscreen_size_.height();
3329 if (w < 0 || h < 0 || h >= (INT_MAX / 4) / (w ? w : 1)) {
3330 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3331 << "to allocate storage due to excessive dimensions.";
3332 return false;
3335 // Reallocate the offscreen target buffers.
3336 DCHECK(offscreen_target_color_format_);
3337 if (IsOffscreenBufferMultisampled()) {
3338 if (!offscreen_target_color_render_buffer_->AllocateStorage(
3339 offscreen_size_, offscreen_target_color_format_,
3340 offscreen_target_samples_)) {
3341 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3342 << "to allocate storage for offscreen target color buffer.";
3343 return false;
3345 } else {
3346 if (!offscreen_target_color_texture_->AllocateStorage(
3347 offscreen_size_, offscreen_target_color_format_, false)) {
3348 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3349 << "to allocate storage for offscreen target color texture.";
3350 return false;
3353 if (offscreen_target_depth_format_ &&
3354 !offscreen_target_depth_render_buffer_->AllocateStorage(
3355 offscreen_size_, offscreen_target_depth_format_,
3356 offscreen_target_samples_)) {
3357 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3358 << "to allocate storage for offscreen target depth buffer.";
3359 return false;
3361 if (offscreen_target_stencil_format_ &&
3362 !offscreen_target_stencil_render_buffer_->AllocateStorage(
3363 offscreen_size_, offscreen_target_stencil_format_,
3364 offscreen_target_samples_)) {
3365 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3366 << "to allocate storage for offscreen target stencil buffer.";
3367 return false;
3370 // Attach the offscreen target buffers to the target frame buffer.
3371 if (IsOffscreenBufferMultisampled()) {
3372 offscreen_target_frame_buffer_->AttachRenderBuffer(
3373 GL_COLOR_ATTACHMENT0,
3374 offscreen_target_color_render_buffer_.get());
3375 } else {
3376 offscreen_target_frame_buffer_->AttachRenderTexture(
3377 offscreen_target_color_texture_.get());
3379 if (offscreen_target_depth_format_) {
3380 offscreen_target_frame_buffer_->AttachRenderBuffer(
3381 GL_DEPTH_ATTACHMENT,
3382 offscreen_target_depth_render_buffer_.get());
3384 const bool packed_depth_stencil =
3385 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
3386 if (packed_depth_stencil) {
3387 offscreen_target_frame_buffer_->AttachRenderBuffer(
3388 GL_STENCIL_ATTACHMENT,
3389 offscreen_target_depth_render_buffer_.get());
3390 } else if (offscreen_target_stencil_format_) {
3391 offscreen_target_frame_buffer_->AttachRenderBuffer(
3392 GL_STENCIL_ATTACHMENT,
3393 offscreen_target_stencil_render_buffer_.get());
3396 if (offscreen_target_frame_buffer_->CheckStatus() !=
3397 GL_FRAMEBUFFER_COMPLETE) {
3398 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3399 << "because offscreen FBO was incomplete.";
3400 return false;
3403 // Clear the target frame buffer.
3405 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
3406 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3407 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1);
3408 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3409 glClearStencil(0);
3410 glStencilMaskSeparate(GL_FRONT, -1);
3411 glStencilMaskSeparate(GL_BACK, -1);
3412 glClearDepth(0);
3413 glDepthMask(GL_TRUE);
3414 glDisable(GL_SCISSOR_TEST);
3415 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3416 RestoreClearState();
3419 // Destroy the offscreen resolved framebuffers.
3420 if (offscreen_resolved_frame_buffer_.get())
3421 offscreen_resolved_frame_buffer_->Destroy();
3422 if (offscreen_resolved_color_texture_.get())
3423 offscreen_resolved_color_texture_->Destroy();
3424 offscreen_resolved_color_texture_.reset();
3425 offscreen_resolved_frame_buffer_.reset();
3427 return true;
3430 error::Error GLES2DecoderImpl::HandleResizeCHROMIUM(
3431 uint32 immediate_data_size, const cmds::ResizeCHROMIUM& c) {
3432 if (!offscreen_target_frame_buffer_.get() && surface_->DeferDraws())
3433 return error::kDeferCommandUntilLater;
3435 GLuint width = static_cast<GLuint>(c.width);
3436 GLuint height = static_cast<GLuint>(c.height);
3437 GLfloat scale_factor = c.scale_factor;
3438 TRACE_EVENT2("gpu", "glResizeChromium", "width", width, "height", height);
3440 width = std::max(1U, width);
3441 height = std::max(1U, height);
3443 #if defined(OS_POSIX) && !defined(OS_MACOSX) && \
3444 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
3445 // Make sure that we are done drawing to the back buffer before resizing.
3446 glFinish();
3447 #endif
3448 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
3449 if (is_offscreen) {
3450 if (!ResizeOffscreenFrameBuffer(gfx::Size(width, height))) {
3451 LOG(ERROR) << "GLES2DecoderImpl: Context lost because "
3452 << "ResizeOffscreenFrameBuffer failed.";
3453 return error::kLostContext;
3457 if (!resize_callback_.is_null()) {
3458 resize_callback_.Run(gfx::Size(width, height), scale_factor);
3459 DCHECK(context_->IsCurrent(surface_.get()));
3460 if (!context_->IsCurrent(surface_.get())) {
3461 LOG(ERROR) << "GLES2DecoderImpl: Context lost because context no longer "
3462 << "current after resize callback.";
3463 return error::kLostContext;
3467 return error::kNoError;
3470 const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
3471 if (command_id > kStartPoint && command_id < kNumCommands) {
3472 return gles2::GetCommandName(static_cast<CommandId>(command_id));
3474 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
3477 // Decode command with its arguments, and call the corresponding GL function.
3478 // Note: args is a pointer to the command buffer. As such, it could be changed
3479 // by a (malicious) client at any time, so if validation has to happen, it
3480 // should operate on a copy of them.
3481 error::Error GLES2DecoderImpl::DoCommand(
3482 unsigned int command,
3483 unsigned int arg_count,
3484 const void* cmd_data) {
3485 error::Error result = error::kNoError;
3486 if (log_commands()) {
3487 // TODO(notme): Change this to a LOG/VLOG that works in release. Tried
3488 // LOG(INFO), tried VLOG(1), no luck.
3489 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "]" << "cmd: "
3490 << GetCommandName(command);
3492 unsigned int command_index = command - kStartPoint - 1;
3493 if (command_index < arraysize(g_command_info)) {
3494 const CommandInfo& info = g_command_info[command_index];
3495 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
3496 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
3497 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
3498 uint32 immediate_data_size =
3499 (arg_count - info_arg_count) * sizeof(CommandBufferEntry); // NOLINT
3500 switch (command) {
3501 #define GLES2_CMD_OP(name) \
3502 case cmds::name::kCmdId: \
3503 result = Handle ## name( \
3504 immediate_data_size, \
3505 *static_cast<const gles2::cmds::name*>(cmd_data)); \
3506 break; \
3508 GLES2_COMMAND_LIST(GLES2_CMD_OP)
3509 #undef GLES2_CMD_OP
3511 if (debug()) {
3512 GLenum error;
3513 while ((error = glGetError()) != GL_NO_ERROR) {
3514 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "] "
3515 << "GL ERROR: " << GLES2Util::GetStringEnum(error) << " : "
3516 << GetCommandName(command);
3517 LOCAL_SET_GL_ERROR(error, "DoCommand", "GL error from driver");
3520 } else {
3521 result = error::kInvalidArguments;
3523 } else {
3524 result = DoCommonCommand(command, arg_count, cmd_data);
3526 if (result == error::kNoError && current_decoder_error_ != error::kNoError) {
3527 result = current_decoder_error_;
3528 current_decoder_error_ = error::kNoError;
3530 return result;
3533 void GLES2DecoderImpl::RemoveBuffer(GLuint client_id) {
3534 buffer_manager()->RemoveBuffer(client_id);
3537 bool GLES2DecoderImpl::CreateProgramHelper(GLuint client_id) {
3538 if (GetProgram(client_id)) {
3539 return false;
3541 GLuint service_id = glCreateProgram();
3542 if (service_id != 0) {
3543 CreateProgram(client_id, service_id);
3545 return true;
3548 bool GLES2DecoderImpl::CreateShaderHelper(GLenum type, GLuint client_id) {
3549 if (GetShader(client_id)) {
3550 return false;
3552 GLuint service_id = glCreateShader(type);
3553 if (service_id != 0) {
3554 CreateShader(client_id, service_id, type);
3556 return true;
3559 void GLES2DecoderImpl::DoFinish() {
3560 glFinish();
3561 ProcessPendingReadPixels();
3562 ProcessPendingQueries();
3565 void GLES2DecoderImpl::DoFlush() {
3566 glFlush();
3567 ProcessPendingQueries();
3570 void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
3571 GLuint texture_index = texture_unit - GL_TEXTURE0;
3572 if (texture_index >= state_.texture_units.size()) {
3573 LOCAL_SET_GL_ERROR_INVALID_ENUM(
3574 "glActiveTexture", texture_unit, "texture_unit");
3575 return;
3577 state_.active_texture_unit = texture_index;
3578 glActiveTexture(texture_unit);
3581 void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
3582 Buffer* buffer = NULL;
3583 GLuint service_id = 0;
3584 if (client_id != 0) {
3585 buffer = GetBuffer(client_id);
3586 if (!buffer) {
3587 if (!group_->bind_generates_resource()) {
3588 LOG(ERROR) << "glBindBuffer: id not generated by glGenBuffers";
3589 current_decoder_error_ = error::kGenericError;
3590 return;
3593 // It's a new id so make a buffer buffer for it.
3594 glGenBuffersARB(1, &service_id);
3595 CreateBuffer(client_id, service_id);
3596 buffer = GetBuffer(client_id);
3597 IdAllocatorInterface* id_allocator =
3598 group_->GetIdAllocator(id_namespaces::kBuffers);
3599 id_allocator->MarkAsUsed(client_id);
3602 LogClientServiceForInfo(buffer, client_id, "glBindBuffer");
3603 if (buffer) {
3604 if (!buffer_manager()->SetTarget(buffer, target)) {
3605 LOCAL_SET_GL_ERROR(
3606 GL_INVALID_OPERATION,
3607 "glBindBuffer", "buffer bound to more than 1 target");
3608 return;
3610 service_id = buffer->service_id();
3612 switch (target) {
3613 case GL_ARRAY_BUFFER:
3614 state_.bound_array_buffer = buffer;
3615 break;
3616 case GL_ELEMENT_ARRAY_BUFFER:
3617 state_.vertex_attrib_manager->SetElementArrayBuffer(buffer);
3618 break;
3619 default:
3620 NOTREACHED(); // Validation should prevent us getting here.
3621 break;
3623 glBindBuffer(target, service_id);
3626 bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha(
3627 bool all_draw_buffers) {
3628 Framebuffer* framebuffer =
3629 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3630 if (!all_draw_buffers || !framebuffer) {
3631 return (GLES2Util::GetChannelsForFormat(
3632 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
3634 return framebuffer->HasAlphaMRT();
3637 bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
3638 Framebuffer* framebuffer =
3639 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3640 if (framebuffer) {
3641 return framebuffer->HasDepthAttachment();
3643 if (offscreen_target_frame_buffer_.get()) {
3644 return offscreen_target_depth_format_ != 0;
3646 return back_buffer_has_depth_;
3649 bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
3650 Framebuffer* framebuffer =
3651 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3652 if (framebuffer) {
3653 return framebuffer->HasStencilAttachment();
3655 if (offscreen_target_frame_buffer_.get()) {
3656 return offscreen_target_stencil_format_ != 0 ||
3657 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
3659 return back_buffer_has_stencil_;
3662 void GLES2DecoderImpl::ApplyDirtyState() {
3663 if (clear_state_dirty_) {
3664 glColorMask(
3665 state_.color_mask_red, state_.color_mask_green, state_.color_mask_blue,
3666 state_.color_mask_alpha &&
3667 BoundFramebufferHasColorAttachmentWithAlpha(true));
3668 bool have_depth = BoundFramebufferHasDepthAttachment();
3669 glDepthMask(state_.depth_mask && have_depth);
3670 EnableDisable(GL_DEPTH_TEST, state_.enable_flags.depth_test && have_depth);
3671 bool have_stencil = BoundFramebufferHasStencilAttachment();
3672 glStencilMaskSeparate(
3673 GL_FRONT, have_stencil ? state_.stencil_front_writemask : 0);
3674 glStencilMaskSeparate(
3675 GL_BACK, have_stencil ? state_.stencil_back_writemask : 0);
3676 EnableDisable(
3677 GL_STENCIL_TEST, state_.enable_flags.stencil_test && have_stencil);
3678 EnableDisable(GL_CULL_FACE, state_.enable_flags.cull_face);
3679 EnableDisable(GL_SCISSOR_TEST, state_.enable_flags.scissor_test);
3680 EnableDisable(GL_BLEND, state_.enable_flags.blend);
3681 clear_state_dirty_ = false;
3685 GLuint GLES2DecoderImpl::GetBackbufferServiceId() const {
3686 return (offscreen_target_frame_buffer_.get())
3687 ? offscreen_target_frame_buffer_->id()
3688 : (surface_.get() ? surface_->GetBackingFrameBufferObject() : 0);
3691 void GLES2DecoderImpl::RestoreState() const {
3692 TRACE_EVENT1("gpu", "GLES2DecoderImpl::RestoreState",
3693 "context", logger_.GetLogPrefix());
3694 // Restore the Framebuffer first because of bugs in Intel drivers.
3695 // Intel drivers incorrectly clip the viewport settings to
3696 // the size of the current framebuffer object.
3697 RestoreFramebufferBindings();
3698 state_.RestoreState();
3701 void GLES2DecoderImpl::RestoreFramebufferBindings() const {
3702 GLuint service_id = state_.bound_draw_framebuffer.get()
3703 ? state_.bound_draw_framebuffer->service_id()
3704 : GetBackbufferServiceId();
3705 if (!features().chromium_framebuffer_multisample) {
3706 glBindFramebufferEXT(GL_FRAMEBUFFER, service_id);
3707 } else {
3708 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, service_id);
3709 service_id = state_.bound_read_framebuffer.get()
3710 ? state_.bound_read_framebuffer->service_id()
3711 : GetBackbufferServiceId();
3712 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, service_id);
3714 OnFboChanged();
3717 void GLES2DecoderImpl::RestoreTextureState(unsigned service_id) const {
3718 Texture* texture = texture_manager()->GetTextureForServiceId(service_id);
3719 if (texture) {
3720 GLenum target = texture->target();
3721 glBindTexture(target, service_id);
3722 glTexParameteri(
3723 target, GL_TEXTURE_WRAP_S, texture->wrap_s());
3724 glTexParameteri(
3725 target, GL_TEXTURE_WRAP_T, texture->wrap_t());
3726 glTexParameteri(
3727 target, GL_TEXTURE_MIN_FILTER, texture->min_filter());
3728 glTexParameteri(
3729 target, GL_TEXTURE_MAG_FILTER, texture->mag_filter());
3730 RestoreTextureUnitBindings(state_.active_texture_unit);
3734 void GLES2DecoderImpl::OnFboChanged() const {
3735 if (workarounds().restore_scissor_on_fbo_change)
3736 state_.fbo_binding_for_scissor_workaround_dirty_ = true;
3739 // Called after the FBO is checked for completeness.
3740 void GLES2DecoderImpl::OnUseFramebuffer() const {
3741 if (state_.fbo_binding_for_scissor_workaround_dirty_) {
3742 state_.fbo_binding_for_scissor_workaround_dirty_ = false;
3743 // The driver forgets the correct scissor when modifying the FBO binding.
3744 glScissor(state_.scissor_x,
3745 state_.scissor_y,
3746 state_.scissor_width,
3747 state_.scissor_height);
3749 // crbug.com/222018 - Also on QualComm, the flush here avoids flicker,
3750 // it's unclear how this bug works.
3751 glFlush();
3755 void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
3756 Framebuffer* framebuffer = NULL;
3757 GLuint service_id = 0;
3758 if (client_id != 0) {
3759 framebuffer = GetFramebuffer(client_id);
3760 if (!framebuffer) {
3761 if (!group_->bind_generates_resource()) {
3762 LOG(ERROR)
3763 << "glBindFramebuffer: id not generated by glGenFramebuffers";
3764 current_decoder_error_ = error::kGenericError;
3765 return;
3768 // It's a new id so make a framebuffer framebuffer for it.
3769 glGenFramebuffersEXT(1, &service_id);
3770 CreateFramebuffer(client_id, service_id);
3771 framebuffer = GetFramebuffer(client_id);
3772 IdAllocatorInterface* id_allocator =
3773 group_->GetIdAllocator(id_namespaces::kFramebuffers);
3774 id_allocator->MarkAsUsed(client_id);
3775 } else {
3776 service_id = framebuffer->service_id();
3778 framebuffer->MarkAsValid();
3780 LogClientServiceForInfo(framebuffer, client_id, "glBindFramebuffer");
3782 if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) {
3783 state_.bound_draw_framebuffer = framebuffer;
3785 if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) {
3786 state_.bound_read_framebuffer = framebuffer;
3789 clear_state_dirty_ = true;
3791 // If we are rendering to the backbuffer get the FBO id for any simulated
3792 // backbuffer.
3793 if (framebuffer == NULL) {
3794 service_id = GetBackbufferServiceId();
3797 glBindFramebufferEXT(target, service_id);
3798 OnFboChanged();
3801 void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
3802 Renderbuffer* renderbuffer = NULL;
3803 GLuint service_id = 0;
3804 if (client_id != 0) {
3805 renderbuffer = GetRenderbuffer(client_id);
3806 if (!renderbuffer) {
3807 if (!group_->bind_generates_resource()) {
3808 LOG(ERROR)
3809 << "glBindRenderbuffer: id not generated by glGenRenderbuffers";
3810 current_decoder_error_ = error::kGenericError;
3811 return;
3814 // It's a new id so make a renderbuffer renderbuffer for it.
3815 glGenRenderbuffersEXT(1, &service_id);
3816 CreateRenderbuffer(client_id, service_id);
3817 renderbuffer = GetRenderbuffer(client_id);
3818 IdAllocatorInterface* id_allocator =
3819 group_->GetIdAllocator(id_namespaces::kRenderbuffers);
3820 id_allocator->MarkAsUsed(client_id);
3821 } else {
3822 service_id = renderbuffer->service_id();
3824 renderbuffer->MarkAsValid();
3826 LogClientServiceForInfo(renderbuffer, client_id, "glBindRenerbuffer");
3827 state_.bound_renderbuffer = renderbuffer;
3828 glBindRenderbufferEXT(target, service_id);
3831 void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
3832 TextureRef* texture_ref = NULL;
3833 GLuint service_id = 0;
3834 if (client_id != 0) {
3835 texture_ref = GetTexture(client_id);
3836 if (!texture_ref) {
3837 if (!group_->bind_generates_resource()) {
3838 LOG(ERROR) << "glBindTexture: id not generated by glGenTextures";
3839 current_decoder_error_ = error::kGenericError;
3840 return;
3843 // It's a new id so make a texture texture for it.
3844 glGenTextures(1, &service_id);
3845 DCHECK_NE(0u, service_id);
3846 CreateTexture(client_id, service_id);
3847 texture_ref = GetTexture(client_id);
3848 IdAllocatorInterface* id_allocator =
3849 group_->GetIdAllocator(id_namespaces::kTextures);
3850 id_allocator->MarkAsUsed(client_id);
3852 } else {
3853 texture_ref = texture_manager()->GetDefaultTextureInfo(target);
3855 Texture* texture = texture_ref->texture();
3857 // Check the texture exists
3858 // Check that we are not trying to bind it to a different target.
3859 if (texture->target() != 0 && texture->target() != target) {
3860 LOCAL_SET_GL_ERROR(
3861 GL_INVALID_OPERATION,
3862 "glBindTexture", "texture bound to more than 1 target.");
3863 return;
3865 if (texture->IsStreamTexture() && target != GL_TEXTURE_EXTERNAL_OES) {
3866 LOCAL_SET_GL_ERROR(
3867 GL_INVALID_OPERATION,
3868 "glBindTexture", "illegal target for stream texture.");
3869 return;
3871 LogClientServiceForInfo(texture, client_id, "glBindTexture");
3872 if (texture->target() == 0) {
3873 texture_manager()->SetTarget(texture_ref, target);
3875 glBindTexture(target, texture->service_id());
3877 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
3878 unit.bind_target = target;
3879 switch (target) {
3880 case GL_TEXTURE_2D:
3881 unit.bound_texture_2d = texture_ref;
3882 break;
3883 case GL_TEXTURE_CUBE_MAP:
3884 unit.bound_texture_cube_map = texture_ref;
3885 break;
3886 case GL_TEXTURE_EXTERNAL_OES:
3887 unit.bound_texture_external_oes = texture_ref;
3888 if (texture->IsStreamTexture()) {
3889 DCHECK(stream_texture_manager());
3890 StreamTexture* stream_tex =
3891 stream_texture_manager()->LookupStreamTexture(
3892 texture->service_id());
3893 if (stream_tex)
3894 stream_tex->Update();
3896 break;
3897 case GL_TEXTURE_RECTANGLE_ARB:
3898 unit.bound_texture_rectangle_arb = texture_ref;
3899 break;
3900 default:
3901 NOTREACHED(); // Validation should prevent us getting here.
3902 break;
3906 void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
3907 if (state_.vertex_attrib_manager->Enable(index, false)) {
3908 if (index != 0 ||
3909 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
3910 glDisableVertexAttribArray(index);
3912 } else {
3913 LOCAL_SET_GL_ERROR(
3914 GL_INVALID_VALUE,
3915 "glDisableVertexAttribArray", "index out of range");
3919 void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target,
3920 GLsizei numAttachments,
3921 const GLenum* attachments) {
3922 Framebuffer* framebuffer =
3923 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
3925 // Validates the attachments. If one of them fails
3926 // the whole command fails.
3927 for (GLsizei i = 0; i < numAttachments; ++i) {
3928 if ((framebuffer &&
3929 !validators_->attachment.IsValid(attachments[i])) ||
3930 (!framebuffer &&
3931 !validators_->backbuffer_attachment.IsValid(attachments[i]))) {
3932 LOCAL_SET_GL_ERROR_INVALID_ENUM(
3933 "glDiscardFramebufferEXT", attachments[i], "attachments");
3934 return;
3938 // Marks each one of them as not cleared
3939 for (GLsizei i = 0; i < numAttachments; ++i) {
3940 if (framebuffer) {
3941 framebuffer->MarkAttachmentAsCleared(renderbuffer_manager(),
3942 texture_manager(),
3943 attachments[i],
3944 false);
3945 } else {
3946 switch (attachments[i]) {
3947 case GL_COLOR_EXT:
3948 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
3949 break;
3950 case GL_DEPTH_EXT:
3951 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
3952 case GL_STENCIL_EXT:
3953 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
3954 break;
3955 default:
3956 NOTREACHED();
3957 break;
3962 glDiscardFramebufferEXT(target, numAttachments, attachments);
3965 void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
3966 if (state_.vertex_attrib_manager->Enable(index, true)) {
3967 glEnableVertexAttribArray(index);
3968 } else {
3969 LOCAL_SET_GL_ERROR(
3970 GL_INVALID_VALUE, "glEnableVertexAttribArray", "index out of range");
3974 void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
3975 TextureRef* texture_ref = GetTextureInfoForTarget(target);
3976 if (!texture_ref ||
3977 !texture_manager()->CanGenerateMipmaps(texture_ref)) {
3978 LOCAL_SET_GL_ERROR(
3979 GL_INVALID_OPERATION, "glGenerateMipmap", "Can not generate mips");
3980 return;
3983 if (target == GL_TEXTURE_CUBE_MAP) {
3984 for (int i = 0; i < 6; ++i) {
3985 GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;
3986 if (!texture_manager()->ClearTextureLevel(this, texture_ref, face, 0)) {
3987 LOCAL_SET_GL_ERROR(
3988 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
3989 return;
3992 } else {
3993 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, 0)) {
3994 LOCAL_SET_GL_ERROR(
3995 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
3996 return;
4000 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glGenerateMipmap");
4001 // Workaround for Mac driver bug. In the large scheme of things setting
4002 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
4003 // hit so there's probably no need to make this conditional. The bug appears
4004 // to be that if the filtering mode is set to something that doesn't require
4005 // mipmaps for rendering, or is never set to something other than the default,
4006 // then glGenerateMipmap misbehaves.
4007 if (workarounds().set_texture_filter_before_generating_mipmap) {
4008 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
4010 glGenerateMipmapEXT(target);
4011 if (workarounds().set_texture_filter_before_generating_mipmap) {
4012 glTexParameteri(target, GL_TEXTURE_MIN_FILTER,
4013 texture_ref->texture()->min_filter());
4015 GLenum error = LOCAL_PEEK_GL_ERROR("glGenerateMipmap");
4016 if (error == GL_NO_ERROR) {
4017 texture_manager()->MarkMipmapsGenerated(texture_ref);
4021 bool GLES2DecoderImpl::GetHelper(
4022 GLenum pname, GLint* params, GLsizei* num_written) {
4023 DCHECK(num_written);
4024 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
4025 switch (pname) {
4026 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
4027 *num_written = 1;
4028 if (params) {
4029 *params = GL_RGBA; // We don't support other formats.
4031 return true;
4032 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
4033 *num_written = 1;
4034 if (params) {
4035 *params = GL_UNSIGNED_BYTE; // We don't support other types.
4037 return true;
4038 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
4039 *num_written = 1;
4040 if (params) {
4041 *params = group_->max_fragment_uniform_vectors();
4043 return true;
4044 case GL_MAX_VARYING_VECTORS:
4045 *num_written = 1;
4046 if (params) {
4047 *params = group_->max_varying_vectors();
4049 return true;
4050 case GL_MAX_VERTEX_UNIFORM_VECTORS:
4051 *num_written = 1;
4052 if (params) {
4053 *params = group_->max_vertex_uniform_vectors();
4055 return true;
4058 switch (pname) {
4059 case GL_MAX_VIEWPORT_DIMS:
4060 if (offscreen_target_frame_buffer_.get()) {
4061 *num_written = 2;
4062 if (params) {
4063 params[0] = renderbuffer_manager()->max_renderbuffer_size();
4064 params[1] = renderbuffer_manager()->max_renderbuffer_size();
4066 return true;
4068 return false;
4069 case GL_MAX_SAMPLES:
4070 *num_written = 1;
4071 if (params) {
4072 params[0] = renderbuffer_manager()->max_samples();
4074 return true;
4075 case GL_MAX_RENDERBUFFER_SIZE:
4076 *num_written = 1;
4077 if (params) {
4078 params[0] = renderbuffer_manager()->max_renderbuffer_size();
4080 return true;
4081 case GL_MAX_TEXTURE_SIZE:
4082 *num_written = 1;
4083 if (params) {
4084 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D);
4086 return true;
4087 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
4088 *num_written = 1;
4089 if (params) {
4090 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP);
4092 return true;
4093 case GL_MAX_COLOR_ATTACHMENTS_EXT:
4094 *num_written = 1;
4095 if (params) {
4096 params[0] = group_->max_color_attachments();
4098 return true;
4099 case GL_MAX_DRAW_BUFFERS_ARB:
4100 *num_written = 1;
4101 if (params) {
4102 params[0] = group_->max_draw_buffers();
4104 return true;
4105 case GL_ALPHA_BITS:
4106 *num_written = 1;
4107 if (params) {
4108 GLint v = 0;
4109 glGetIntegerv(GL_ALPHA_BITS, &v);
4110 params[0] = BoundFramebufferHasColorAttachmentWithAlpha(false) ? v : 0;
4112 return true;
4113 case GL_DEPTH_BITS:
4114 *num_written = 1;
4115 if (params) {
4116 GLint v = 0;
4117 glGetIntegerv(GL_DEPTH_BITS, &v);
4118 params[0] = BoundFramebufferHasDepthAttachment() ? v : 0;
4120 return true;
4121 case GL_STENCIL_BITS:
4122 *num_written = 1;
4123 if (params) {
4124 GLint v = 0;
4125 glGetIntegerv(GL_STENCIL_BITS, &v);
4126 params[0] = BoundFramebufferHasStencilAttachment() ? v : 0;
4128 return true;
4129 case GL_COMPRESSED_TEXTURE_FORMATS:
4130 *num_written = validators_->compressed_texture_format.GetValues().size();
4131 if (params) {
4132 for (GLint ii = 0; ii < *num_written; ++ii) {
4133 params[ii] = validators_->compressed_texture_format.GetValues()[ii];
4136 return true;
4137 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
4138 *num_written = 1;
4139 if (params) {
4140 *params = validators_->compressed_texture_format.GetValues().size();
4142 return true;
4143 case GL_NUM_SHADER_BINARY_FORMATS:
4144 *num_written = 1;
4145 if (params) {
4146 *params = validators_->shader_binary_format.GetValues().size();
4148 return true;
4149 case GL_SHADER_BINARY_FORMATS:
4150 *num_written = validators_->shader_binary_format.GetValues().size();
4151 if (params) {
4152 for (GLint ii = 0; ii < *num_written; ++ii) {
4153 params[ii] = validators_->shader_binary_format.GetValues()[ii];
4156 return true;
4157 case GL_SHADER_COMPILER:
4158 *num_written = 1;
4159 if (params) {
4160 *params = GL_TRUE;
4162 return true;
4163 case GL_ARRAY_BUFFER_BINDING:
4164 *num_written = 1;
4165 if (params) {
4166 if (state_.bound_array_buffer.get()) {
4167 GLuint client_id = 0;
4168 buffer_manager()->GetClientId(state_.bound_array_buffer->service_id(),
4169 &client_id);
4170 *params = client_id;
4171 } else {
4172 *params = 0;
4175 return true;
4176 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
4177 *num_written = 1;
4178 if (params) {
4179 if (state_.vertex_attrib_manager->element_array_buffer()) {
4180 GLuint client_id = 0;
4181 buffer_manager()->GetClientId(
4182 state_.vertex_attrib_manager->element_array_buffer()->
4183 service_id(), &client_id);
4184 *params = client_id;
4185 } else {
4186 *params = 0;
4189 return true;
4190 case GL_FRAMEBUFFER_BINDING:
4191 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
4192 *num_written = 1;
4193 if (params) {
4194 Framebuffer* framebuffer =
4195 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4196 if (framebuffer) {
4197 GLuint client_id = 0;
4198 framebuffer_manager()->GetClientId(
4199 framebuffer->service_id(), &client_id);
4200 *params = client_id;
4201 } else {
4202 *params = 0;
4205 return true;
4206 case GL_READ_FRAMEBUFFER_BINDING_EXT:
4207 *num_written = 1;
4208 if (params) {
4209 Framebuffer* framebuffer =
4210 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
4211 if (framebuffer) {
4212 GLuint client_id = 0;
4213 framebuffer_manager()->GetClientId(
4214 framebuffer->service_id(), &client_id);
4215 *params = client_id;
4216 } else {
4217 *params = 0;
4220 return true;
4221 case GL_RENDERBUFFER_BINDING:
4222 *num_written = 1;
4223 if (params) {
4224 Renderbuffer* renderbuffer =
4225 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4226 if (renderbuffer) {
4227 *params = renderbuffer->client_id();
4228 } else {
4229 *params = 0;
4232 return true;
4233 case GL_CURRENT_PROGRAM:
4234 *num_written = 1;
4235 if (params) {
4236 if (state_.current_program.get()) {
4237 GLuint client_id = 0;
4238 program_manager()->GetClientId(
4239 state_.current_program->service_id(), &client_id);
4240 *params = client_id;
4241 } else {
4242 *params = 0;
4245 return true;
4246 case GL_VERTEX_ARRAY_BINDING_OES:
4247 *num_written = 1;
4248 if (params) {
4249 if (state_.vertex_attrib_manager.get() !=
4250 default_vertex_attrib_manager_.get()) {
4251 GLuint client_id = 0;
4252 vertex_array_manager_->GetClientId(
4253 state_.vertex_attrib_manager->service_id(), &client_id);
4254 *params = client_id;
4255 } else {
4256 *params = 0;
4259 return true;
4260 case GL_TEXTURE_BINDING_2D:
4261 *num_written = 1;
4262 if (params) {
4263 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4264 if (unit.bound_texture_2d.get()) {
4265 *params = unit.bound_texture_2d->client_id();
4266 } else {
4267 *params = 0;
4270 return true;
4271 case GL_TEXTURE_BINDING_CUBE_MAP:
4272 *num_written = 1;
4273 if (params) {
4274 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4275 if (unit.bound_texture_cube_map.get()) {
4276 *params = unit.bound_texture_cube_map->client_id();
4277 } else {
4278 *params = 0;
4281 return true;
4282 case GL_TEXTURE_BINDING_EXTERNAL_OES:
4283 *num_written = 1;
4284 if (params) {
4285 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4286 if (unit.bound_texture_external_oes.get()) {
4287 *params = unit.bound_texture_external_oes->client_id();
4288 } else {
4289 *params = 0;
4292 return true;
4293 case GL_TEXTURE_BINDING_RECTANGLE_ARB:
4294 *num_written = 1;
4295 if (params) {
4296 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4297 if (unit.bound_texture_rectangle_arb.get()) {
4298 *params = unit.bound_texture_rectangle_arb->client_id();
4299 } else {
4300 *params = 0;
4303 return true;
4304 case GL_UNPACK_FLIP_Y_CHROMIUM:
4305 *num_written = 1;
4306 if (params) {
4307 params[0] = unpack_flip_y_;
4309 return true;
4310 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
4311 *num_written = 1;
4312 if (params) {
4313 params[0] = unpack_premultiply_alpha_;
4315 return true;
4316 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM:
4317 *num_written = 1;
4318 if (params) {
4319 params[0] = unpack_unpremultiply_alpha_;
4321 return true;
4322 default:
4323 if (pname >= GL_DRAW_BUFFER0_ARB &&
4324 pname < GL_DRAW_BUFFER0_ARB + group_->max_draw_buffers()) {
4325 *num_written = 1;
4326 if (params) {
4327 Framebuffer* framebuffer =
4328 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4329 if (framebuffer) {
4330 params[0] = framebuffer->GetDrawBuffer(pname);
4331 } else { // backbuffer
4332 if (pname == GL_DRAW_BUFFER0_ARB)
4333 params[0] = group_->draw_buffer();
4334 else
4335 params[0] = GL_NONE;
4338 return true;
4340 *num_written = util_.GLGetNumValuesReturned(pname);
4341 return false;
4345 bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
4346 GLenum pname, GLsizei* num_values) {
4347 if (state_.GetStateAsGLint(pname, NULL, num_values)) {
4348 return true;
4350 return GetHelper(pname, NULL, num_values);
4353 void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
4354 DCHECK(params);
4355 GLsizei num_written = 0;
4356 if (GetNumValuesReturnedForGLGet(pname, &num_written)) {
4357 scoped_ptr<GLint[]> values(new GLint[num_written]);
4358 if (!state_.GetStateAsGLint(pname, values.get(), &num_written)) {
4359 GetHelper(pname, values.get(), &num_written);
4361 for (GLsizei ii = 0; ii < num_written; ++ii) {
4362 params[ii] = static_cast<GLboolean>(values[ii]);
4364 } else {
4365 glGetBooleanv(pname, params);
4369 void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
4370 DCHECK(params);
4371 GLsizei num_written = 0;
4372 if (!state_.GetStateAsGLfloat(pname, params, &num_written)) {
4373 if (GetHelper(pname, NULL, &num_written)) {
4374 scoped_ptr<GLint[]> values(new GLint[num_written]);
4375 GetHelper(pname, values.get(), &num_written);
4376 for (GLsizei ii = 0; ii < num_written; ++ii) {
4377 params[ii] = static_cast<GLfloat>(values[ii]);
4379 } else {
4380 glGetFloatv(pname, params);
4385 void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
4386 DCHECK(params);
4387 GLsizei num_written;
4388 if (!state_.GetStateAsGLint(pname, params, &num_written) &&
4389 !GetHelper(pname, params, &num_written)) {
4390 glGetIntegerv(pname, params);
4394 void GLES2DecoderImpl::DoGetProgramiv(
4395 GLuint program_id, GLenum pname, GLint* params) {
4396 Program* program = GetProgramInfoNotShader(program_id, "glGetProgramiv");
4397 if (!program) {
4398 return;
4400 program->GetProgramiv(pname, params);
4403 void GLES2DecoderImpl::DoGetBufferParameteriv(
4404 GLenum target, GLenum pname, GLint* params) {
4405 Buffer* buffer = GetBufferInfoForTarget(target);
4406 if (!buffer) {
4407 LOCAL_SET_GL_ERROR(
4408 GL_INVALID_OPERATION, "glGetBufferParameteriv",
4409 "no buffer bound for target");
4410 return;
4412 switch (pname) {
4413 case GL_BUFFER_SIZE:
4414 *params = buffer->size();
4415 break;
4416 case GL_BUFFER_USAGE:
4417 *params = buffer->usage();
4418 break;
4419 default:
4420 NOTREACHED();
4424 void GLES2DecoderImpl::DoBindAttribLocation(
4425 GLuint program_id, GLuint index, const char* name) {
4426 if (!StringIsValidForGLES(name)) {
4427 LOCAL_SET_GL_ERROR(
4428 GL_INVALID_VALUE, "glBindAttribLocation", "Invalid character");
4429 return;
4431 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
4432 LOCAL_SET_GL_ERROR(
4433 GL_INVALID_OPERATION, "glBindAttribLocation", "reserved prefix");
4434 return;
4436 if (index >= group_->max_vertex_attribs()) {
4437 LOCAL_SET_GL_ERROR(
4438 GL_INVALID_VALUE, "glBindAttribLocation", "index out of range");
4439 return;
4441 Program* program = GetProgramInfoNotShader(
4442 program_id, "glBindAttribLocation");
4443 if (!program) {
4444 return;
4446 program->SetAttribLocationBinding(name, static_cast<GLint>(index));
4447 glBindAttribLocation(program->service_id(), index, name);
4450 error::Error GLES2DecoderImpl::HandleBindAttribLocation(
4451 uint32 immediate_data_size, const cmds::BindAttribLocation& c) {
4452 GLuint program = static_cast<GLuint>(c.program);
4453 GLuint index = static_cast<GLuint>(c.index);
4454 uint32 name_size = c.data_size;
4455 const char* name = GetSharedMemoryAs<const char*>(
4456 c.name_shm_id, c.name_shm_offset, name_size);
4457 if (name == NULL) {
4458 return error::kOutOfBounds;
4460 String name_str(name, name_size);
4461 DoBindAttribLocation(program, index, name_str.c_str());
4462 return error::kNoError;
4465 error::Error GLES2DecoderImpl::HandleBindAttribLocationImmediate(
4466 uint32 immediate_data_size, const cmds::BindAttribLocationImmediate& c) {
4467 GLuint program = static_cast<GLuint>(c.program);
4468 GLuint index = static_cast<GLuint>(c.index);
4469 uint32 name_size = c.data_size;
4470 const char* name = GetImmediateDataAs<const char*>(
4471 c, name_size, immediate_data_size);
4472 if (name == NULL) {
4473 return error::kOutOfBounds;
4475 String name_str(name, name_size);
4476 DoBindAttribLocation(program, index, name_str.c_str());
4477 return error::kNoError;
4480 error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
4481 uint32 immediate_data_size, const cmds::BindAttribLocationBucket& c) {
4482 GLuint program = static_cast<GLuint>(c.program);
4483 GLuint index = static_cast<GLuint>(c.index);
4484 Bucket* bucket = GetBucket(c.name_bucket_id);
4485 if (!bucket || bucket->size() == 0) {
4486 return error::kInvalidArguments;
4488 std::string name_str;
4489 if (!bucket->GetAsString(&name_str)) {
4490 return error::kInvalidArguments;
4492 DoBindAttribLocation(program, index, name_str.c_str());
4493 return error::kNoError;
4496 void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM(
4497 GLuint program_id, GLint location, const char* name) {
4498 if (!StringIsValidForGLES(name)) {
4499 LOCAL_SET_GL_ERROR(
4500 GL_INVALID_VALUE,
4501 "glBindUniformLocationCHROMIUM", "Invalid character");
4502 return;
4504 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
4505 LOCAL_SET_GL_ERROR(
4506 GL_INVALID_OPERATION,
4507 "glBindUniformLocationCHROMIUM", "reserved prefix");
4508 return;
4510 if (location < 0 || static_cast<uint32>(location) >=
4511 (group_->max_fragment_uniform_vectors() +
4512 group_->max_vertex_uniform_vectors()) * 4) {
4513 LOCAL_SET_GL_ERROR(
4514 GL_INVALID_VALUE,
4515 "glBindUniformLocationCHROMIUM", "location out of range");
4516 return;
4518 Program* program = GetProgramInfoNotShader(
4519 program_id, "glBindUniformLocationCHROMIUM");
4520 if (!program) {
4521 return;
4523 if (!program->SetUniformLocationBinding(name, location)) {
4524 LOCAL_SET_GL_ERROR(
4525 GL_INVALID_VALUE,
4526 "glBindUniformLocationCHROMIUM", "location out of range");
4530 error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUM(
4531 uint32 immediate_data_size, const cmds::BindUniformLocationCHROMIUM& c) {
4532 GLuint program = static_cast<GLuint>(c.program);
4533 GLint location = static_cast<GLint>(c.location);
4534 uint32 name_size = c.data_size;
4535 const char* name = GetSharedMemoryAs<const char*>(
4536 c.name_shm_id, c.name_shm_offset, name_size);
4537 if (name == NULL) {
4538 return error::kOutOfBounds;
4540 String name_str(name, name_size);
4541 DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
4542 return error::kNoError;
4545 error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMImmediate(
4546 uint32 immediate_data_size,
4547 const cmds::BindUniformLocationCHROMIUMImmediate& c) {
4548 GLuint program = static_cast<GLuint>(c.program);
4549 GLint location = static_cast<GLint>(c.location);
4550 uint32 name_size = c.data_size;
4551 const char* name = GetImmediateDataAs<const char*>(
4552 c, name_size, immediate_data_size);
4553 if (name == NULL) {
4554 return error::kOutOfBounds;
4556 String name_str(name, name_size);
4557 DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
4558 return error::kNoError;
4561 error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMBucket(
4562 uint32 immediate_data_size,
4563 const cmds::BindUniformLocationCHROMIUMBucket& c) {
4564 GLuint program = static_cast<GLuint>(c.program);
4565 GLint location = static_cast<GLint>(c.location);
4566 Bucket* bucket = GetBucket(c.name_bucket_id);
4567 if (!bucket || bucket->size() == 0) {
4568 return error::kInvalidArguments;
4570 std::string name_str;
4571 if (!bucket->GetAsString(&name_str)) {
4572 return error::kInvalidArguments;
4574 DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
4575 return error::kNoError;
4578 error::Error GLES2DecoderImpl::HandleDeleteShader(
4579 uint32 immediate_data_size, const cmds::DeleteShader& c) {
4580 GLuint client_id = c.shader;
4581 if (client_id) {
4582 Shader* shader = GetShader(client_id);
4583 if (shader) {
4584 if (!shader->IsDeleted()) {
4585 glDeleteShader(shader->service_id());
4586 shader_manager()->MarkAsDeleted(shader);
4588 } else {
4589 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glDeleteShader", "unknown shader");
4592 return error::kNoError;
4595 error::Error GLES2DecoderImpl::HandleDeleteProgram(
4596 uint32 immediate_data_size, const cmds::DeleteProgram& c) {
4597 GLuint client_id = c.program;
4598 if (client_id) {
4599 Program* program = GetProgram(client_id);
4600 if (program) {
4601 if (!program->IsDeleted()) {
4602 program_manager()->MarkAsDeleted(shader_manager(), program);
4604 } else {
4605 LOCAL_SET_GL_ERROR(
4606 GL_INVALID_VALUE, "glDeleteProgram", "unknown program");
4609 return error::kNoError;
4612 void GLES2DecoderImpl::DoDeleteSharedIdsCHROMIUM(
4613 GLuint namespace_id, GLsizei n, const GLuint* ids) {
4614 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
4615 for (GLsizei ii = 0; ii < n; ++ii) {
4616 id_allocator->FreeID(ids[ii]);
4620 error::Error GLES2DecoderImpl::HandleDeleteSharedIdsCHROMIUM(
4621 uint32 immediate_data_size, const cmds::DeleteSharedIdsCHROMIUM& c) {
4622 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4623 GLsizei n = static_cast<GLsizei>(c.n);
4624 uint32 data_size;
4625 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4626 return error::kOutOfBounds;
4628 const GLuint* ids = GetSharedMemoryAs<const GLuint*>(
4629 c.ids_shm_id, c.ids_shm_offset, data_size);
4630 if (n < 0) {
4631 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "DeleteSharedIdsCHROMIUM", "n < 0");
4632 return error::kNoError;
4634 if (ids == NULL) {
4635 return error::kOutOfBounds;
4637 DoDeleteSharedIdsCHROMIUM(namespace_id, n, ids);
4638 return error::kNoError;
4641 void GLES2DecoderImpl::DoGenSharedIdsCHROMIUM(
4642 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids) {
4643 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
4644 if (id_offset == 0) {
4645 for (GLsizei ii = 0; ii < n; ++ii) {
4646 ids[ii] = id_allocator->AllocateID();
4648 } else {
4649 for (GLsizei ii = 0; ii < n; ++ii) {
4650 ids[ii] = id_allocator->AllocateIDAtOrAbove(id_offset);
4651 id_offset = ids[ii] + 1;
4656 error::Error GLES2DecoderImpl::HandleGenSharedIdsCHROMIUM(
4657 uint32 immediate_data_size, const cmds::GenSharedIdsCHROMIUM& c) {
4658 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4659 GLuint id_offset = static_cast<GLuint>(c.id_offset);
4660 GLsizei n = static_cast<GLsizei>(c.n);
4661 uint32 data_size;
4662 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4663 return error::kOutOfBounds;
4665 GLuint* ids = GetSharedMemoryAs<GLuint*>(
4666 c.ids_shm_id, c.ids_shm_offset, data_size);
4667 if (n < 0) {
4668 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "GenSharedIdsCHROMIUM", "n < 0");
4669 return error::kNoError;
4671 if (ids == NULL) {
4672 return error::kOutOfBounds;
4674 DoGenSharedIdsCHROMIUM(namespace_id, id_offset, n, ids);
4675 return error::kNoError;
4678 void GLES2DecoderImpl::DoRegisterSharedIdsCHROMIUM(
4679 GLuint namespace_id, GLsizei n, const GLuint* ids) {
4680 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
4681 for (GLsizei ii = 0; ii < n; ++ii) {
4682 if (!id_allocator->MarkAsUsed(ids[ii])) {
4683 for (GLsizei jj = 0; jj < ii; ++jj) {
4684 id_allocator->FreeID(ids[jj]);
4686 LOCAL_SET_GL_ERROR(
4687 GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM",
4688 "attempt to register id that already exists");
4689 return;
4694 error::Error GLES2DecoderImpl::HandleRegisterSharedIdsCHROMIUM(
4695 uint32 immediate_data_size, const cmds::RegisterSharedIdsCHROMIUM& c) {
4696 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4697 GLsizei n = static_cast<GLsizei>(c.n);
4698 uint32 data_size;
4699 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4700 return error::kOutOfBounds;
4702 GLuint* ids = GetSharedMemoryAs<GLuint*>(
4703 c.ids_shm_id, c.ids_shm_offset, data_size);
4704 if (n < 0) {
4705 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM", "n < 0");
4706 return error::kNoError;
4708 if (ids == NULL) {
4709 return error::kOutOfBounds;
4711 DoRegisterSharedIdsCHROMIUM(namespace_id, n, ids);
4712 return error::kNoError;
4715 error::Error GLES2DecoderImpl::DoClear(GLbitfield mask) {
4716 DCHECK(!ShouldDeferDraws());
4717 if (CheckBoundFramebuffersValid("glClear")) {
4718 ApplyDirtyState();
4719 glClear(mask);
4721 return error::kNoError;
4724 void GLES2DecoderImpl::DoFramebufferRenderbuffer(
4725 GLenum target, GLenum attachment, GLenum renderbuffertarget,
4726 GLuint client_renderbuffer_id) {
4727 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
4728 if (!framebuffer) {
4729 LOCAL_SET_GL_ERROR(
4730 GL_INVALID_OPERATION,
4731 "glFramebufferRenderbuffer", "no framebuffer bound");
4732 return;
4734 GLuint service_id = 0;
4735 Renderbuffer* renderbuffer = NULL;
4736 if (client_renderbuffer_id) {
4737 renderbuffer = GetRenderbuffer(client_renderbuffer_id);
4738 if (!renderbuffer) {
4739 LOCAL_SET_GL_ERROR(
4740 GL_INVALID_OPERATION,
4741 "glFramebufferRenderbuffer", "unknown renderbuffer");
4742 return;
4744 service_id = renderbuffer->service_id();
4746 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glFramebufferRenderbuffer");
4747 glFramebufferRenderbufferEXT(
4748 target, attachment, renderbuffertarget, service_id);
4749 GLenum error = LOCAL_PEEK_GL_ERROR("glFramebufferRenderbuffer");
4750 if (error == GL_NO_ERROR) {
4751 framebuffer->AttachRenderbuffer(attachment, renderbuffer);
4753 if (framebuffer == state_.bound_draw_framebuffer.get()) {
4754 clear_state_dirty_ = true;
4756 OnFboChanged();
4759 void GLES2DecoderImpl::DoDisable(GLenum cap) {
4760 if (SetCapabilityState(cap, false)) {
4761 glDisable(cap);
4765 void GLES2DecoderImpl::DoEnable(GLenum cap) {
4766 if (SetCapabilityState(cap, true)) {
4767 glEnable(cap);
4771 void GLES2DecoderImpl::DoDepthRangef(GLclampf znear, GLclampf zfar) {
4772 state_.z_near = std::min(1.0f, std::max(0.0f, znear));
4773 state_.z_far = std::min(1.0f, std::max(0.0f, zfar));
4774 glDepthRange(znear, zfar);
4777 void GLES2DecoderImpl::DoSampleCoverage(GLclampf value, GLboolean invert) {
4778 state_.sample_coverage_value = std::min(1.0f, std::max(0.0f, value));
4779 state_.sample_coverage_invert = (invert != 0);
4780 glSampleCoverage(state_.sample_coverage_value, invert);
4783 // Assumes framebuffer is complete.
4784 void GLES2DecoderImpl::ClearUnclearedAttachments(
4785 GLenum target, Framebuffer* framebuffer) {
4786 if (target == GL_READ_FRAMEBUFFER_EXT) {
4787 // bind this to the DRAW point, clear then bind back to READ
4788 // TODO(gman): I don't think there is any guarantee that an FBO that
4789 // is complete on the READ attachment will be complete as a DRAW
4790 // attachment.
4791 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
4792 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, framebuffer->service_id());
4794 GLbitfield clear_bits = 0;
4795 if (framebuffer->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0)) {
4796 glClearColor(
4797 0.0f, 0.0f, 0.0f,
4798 (GLES2Util::GetChannelsForFormat(
4799 framebuffer->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0.0f :
4800 1.0f);
4801 glColorMask(true, true, true, true);
4802 clear_bits |= GL_COLOR_BUFFER_BIT;
4805 if (framebuffer->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) ||
4806 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
4807 glClearStencil(0);
4808 glStencilMask(-1);
4809 clear_bits |= GL_STENCIL_BUFFER_BIT;
4812 if (framebuffer->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
4813 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
4814 glClearDepth(1.0f);
4815 glDepthMask(true);
4816 clear_bits |= GL_DEPTH_BUFFER_BIT;
4819 glDisable(GL_SCISSOR_TEST);
4820 glClear(clear_bits);
4822 framebuffer_manager()->MarkAttachmentsAsCleared(
4823 framebuffer, renderbuffer_manager(), texture_manager());
4825 RestoreClearState();
4827 if (target == GL_READ_FRAMEBUFFER_EXT) {
4828 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, framebuffer->service_id());
4829 Framebuffer* draw_framebuffer =
4830 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4831 GLuint service_id = draw_framebuffer ? draw_framebuffer->service_id() :
4832 GetBackbufferServiceId();
4833 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, service_id);
4837 void GLES2DecoderImpl::RestoreClearState() {
4838 clear_state_dirty_ = true;
4839 glClearColor(
4840 state_.color_clear_red, state_.color_clear_green, state_.color_clear_blue,
4841 state_.color_clear_alpha);
4842 glClearStencil(state_.stencil_clear);
4843 glClearDepth(state_.depth_clear);
4844 if (state_.enable_flags.scissor_test) {
4845 glEnable(GL_SCISSOR_TEST);
4849 GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
4850 Framebuffer* framebuffer =
4851 GetFramebufferInfoForTarget(target);
4852 if (!framebuffer) {
4853 return GL_FRAMEBUFFER_COMPLETE;
4855 GLenum completeness = framebuffer->IsPossiblyComplete();
4856 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
4857 return completeness;
4859 return framebuffer->GetStatus(texture_manager(), target);
4862 void GLES2DecoderImpl::DoFramebufferTexture2D(
4863 GLenum target, GLenum attachment, GLenum textarget,
4864 GLuint client_texture_id, GLint level) {
4865 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
4866 if (!framebuffer) {
4867 LOCAL_SET_GL_ERROR(
4868 GL_INVALID_OPERATION,
4869 "glFramebufferTexture2D", "no framebuffer bound.");
4870 return;
4872 GLuint service_id = 0;
4873 TextureRef* texture_ref = NULL;
4874 if (client_texture_id) {
4875 texture_ref = GetTexture(client_texture_id);
4876 if (!texture_ref) {
4877 LOCAL_SET_GL_ERROR(
4878 GL_INVALID_OPERATION,
4879 "glFramebufferTexture2D", "unknown texture_ref");
4880 return;
4882 service_id = texture_ref->service_id();
4885 if (!texture_manager()->ValidForTarget(textarget, level, 0, 0, 1)) {
4886 LOCAL_SET_GL_ERROR(
4887 GL_INVALID_VALUE,
4888 "glFramebufferTexture2D", "level out of range");
4889 return;
4892 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glFramebufferTexture2D");
4893 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
4894 GLenum error = LOCAL_PEEK_GL_ERROR("glFramebufferTexture2D");
4895 if (error == GL_NO_ERROR) {
4896 framebuffer->AttachTexture(attachment, texture_ref, textarget, level);
4898 if (framebuffer == state_.bound_draw_framebuffer.get()) {
4899 clear_state_dirty_ = true;
4901 OnFboChanged();
4904 void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
4905 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
4906 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
4907 if (!framebuffer) {
4908 LOCAL_SET_GL_ERROR(
4909 GL_INVALID_OPERATION,
4910 "glFramebufferAttachmentParameteriv", "no framebuffer bound");
4911 return;
4913 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
4914 const Framebuffer::Attachment* attachment_object =
4915 framebuffer->GetAttachment(attachment);
4916 *params = attachment_object ? attachment_object->object_name() : 0;
4917 } else {
4918 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
4922 void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
4923 GLenum target, GLenum pname, GLint* params) {
4924 Renderbuffer* renderbuffer =
4925 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4926 if (!renderbuffer) {
4927 LOCAL_SET_GL_ERROR(
4928 GL_INVALID_OPERATION,
4929 "glGetRenderbufferParameteriv", "no renderbuffer bound");
4930 return;
4932 switch (pname) {
4933 case GL_RENDERBUFFER_INTERNAL_FORMAT:
4934 *params = renderbuffer->internal_format();
4935 break;
4936 case GL_RENDERBUFFER_WIDTH:
4937 *params = renderbuffer->width();
4938 break;
4939 case GL_RENDERBUFFER_HEIGHT:
4940 *params = renderbuffer->height();
4941 break;
4942 default:
4943 glGetRenderbufferParameterivEXT(target, pname, params);
4944 break;
4948 void GLES2DecoderImpl::DoBlitFramebufferEXT(
4949 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
4950 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
4951 GLbitfield mask, GLenum filter) {
4952 DCHECK(!ShouldDeferReads() && !ShouldDeferDraws());
4953 if (!features().chromium_framebuffer_multisample) {
4954 LOCAL_SET_GL_ERROR(
4955 GL_INVALID_OPERATION,
4956 "glBlitFramebufferEXT", "function not available");
4959 if (!CheckBoundFramebuffersValid("glBlitFramebufferEXT")) {
4960 return;
4963 glDisable(GL_SCISSOR_TEST);
4964 if (IsAngle()) {
4965 glBlitFramebufferANGLE(
4966 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
4967 } else {
4968 glBlitFramebufferEXT(
4969 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
4971 EnableDisable(GL_SCISSOR_TEST, state_.enable_flags.scissor_test);
4974 void GLES2DecoderImpl::DoRenderbufferStorageMultisample(
4975 GLenum target, GLsizei samples, GLenum internalformat,
4976 GLsizei width, GLsizei height) {
4977 if (!features().chromium_framebuffer_multisample) {
4978 LOCAL_SET_GL_ERROR(
4979 GL_INVALID_OPERATION,
4980 "glRenderbufferStorageMultisample", "function not available");
4981 return;
4984 Renderbuffer* renderbuffer =
4985 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4986 if (!renderbuffer) {
4987 LOCAL_SET_GL_ERROR(
4988 GL_INVALID_OPERATION,
4989 "glRenderbufferStorageMultisample", "no renderbuffer bound");
4990 return;
4993 if (samples > renderbuffer_manager()->max_samples()) {
4994 LOCAL_SET_GL_ERROR(
4995 GL_INVALID_VALUE,
4996 "glRenderbufferStorageMultisample", "samples too large");
4997 return;
5000 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
5001 height > renderbuffer_manager()->max_renderbuffer_size()) {
5002 LOCAL_SET_GL_ERROR(
5003 GL_INVALID_VALUE,
5004 "glRenderbufferStorageMultisample", "dimensions too large");
5005 return;
5008 uint32 estimated_size = 0;
5009 if (!RenderbufferManager::ComputeEstimatedRenderbufferSize(
5010 width, height, samples, internalformat, &estimated_size)) {
5011 LOCAL_SET_GL_ERROR(
5012 GL_OUT_OF_MEMORY,
5013 "glRenderbufferStorageMultsample", "dimensions too large");
5014 return;
5017 if (!EnsureGPUMemoryAvailable(estimated_size)) {
5018 LOCAL_SET_GL_ERROR(
5019 GL_OUT_OF_MEMORY,
5020 "glRenderbufferStorageMultsample", "out of memory");
5021 return;
5024 GLenum impl_format = RenderbufferManager::
5025 InternalRenderbufferFormatToImplFormat(internalformat);
5026 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorageMultisample");
5027 if (IsAngle()) {
5028 glRenderbufferStorageMultisampleANGLE(
5029 target, samples, impl_format, width, height);
5030 } else {
5031 glRenderbufferStorageMultisampleEXT(
5032 target, samples, impl_format, width, height);
5034 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisample");
5035 if (error == GL_NO_ERROR) {
5036 // TODO(gman): If renderbuffers tracked which framebuffers they were
5037 // attached to we could just mark those framebuffers as not complete.
5038 framebuffer_manager()->IncFramebufferStateChangeCount();
5039 renderbuffer_manager()->SetInfo(
5040 renderbuffer, samples, internalformat, width, height);
5044 void GLES2DecoderImpl::DoRenderbufferStorage(
5045 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
5046 Renderbuffer* renderbuffer =
5047 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5048 if (!renderbuffer) {
5049 LOCAL_SET_GL_ERROR(
5050 GL_INVALID_OPERATION,
5051 "glRenderbufferStorage", "no renderbuffer bound");
5052 return;
5055 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
5056 height > renderbuffer_manager()->max_renderbuffer_size()) {
5057 LOCAL_SET_GL_ERROR(
5058 GL_INVALID_VALUE, "glRenderbufferStorage", "dimensions too large");
5059 return;
5062 uint32 estimated_size = 0;
5063 if (!RenderbufferManager::ComputeEstimatedRenderbufferSize(
5064 width, height, 1, internalformat, &estimated_size)) {
5065 LOCAL_SET_GL_ERROR(
5066 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "dimensions too large");
5067 return;
5070 if (!EnsureGPUMemoryAvailable(estimated_size)) {
5071 LOCAL_SET_GL_ERROR(
5072 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "out of memory");
5073 return;
5076 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorage");
5077 glRenderbufferStorageEXT(
5078 target, RenderbufferManager::
5079 InternalRenderbufferFormatToImplFormat(internalformat),
5080 width, height);
5081 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorage");
5082 if (error == GL_NO_ERROR) {
5083 // TODO(gman): If tetxures tracked which framebuffers they were attached to
5084 // we could just mark those framebuffers as not complete.
5085 framebuffer_manager()->IncFramebufferStateChangeCount();
5086 renderbuffer_manager()->SetInfo(
5087 renderbuffer, 1, internalformat, width, height);
5091 void GLES2DecoderImpl::DoLinkProgram(GLuint program_id) {
5092 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
5093 Program* program = GetProgramInfoNotShader(
5094 program_id, "glLinkProgram");
5095 if (!program) {
5096 return;
5099 LogClientServiceForInfo(program, program_id, "glLinkProgram");
5100 ShaderTranslator* vertex_translator = NULL;
5101 ShaderTranslator* fragment_translator = NULL;
5102 if (use_shader_translator_) {
5103 vertex_translator = vertex_translator_.get();
5104 fragment_translator = fragment_translator_.get();
5106 if (program->Link(shader_manager(),
5107 vertex_translator,
5108 fragment_translator,
5109 feature_info_.get(),
5110 shader_cache_callback_)) {
5111 if (program == state_.current_program.get()) {
5112 if (workarounds().use_current_program_after_successful_link) {
5113 glUseProgram(program->service_id());
5115 program_manager()->ClearUniforms(program);
5120 void GLES2DecoderImpl::DoTexParameterf(
5121 GLenum target, GLenum pname, GLfloat param) {
5122 TextureRef* texture = GetTextureInfoForTarget(target);
5123 if (!texture) {
5124 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterf", "unknown texture");
5125 return;
5128 texture_manager()->SetParameter(
5129 "glTexParameterf", GetErrorState(), texture, pname,
5130 static_cast<GLint>(param));
5133 void GLES2DecoderImpl::DoTexParameteri(
5134 GLenum target, GLenum pname, GLint param) {
5135 TextureRef* texture = GetTextureInfoForTarget(target);
5136 if (!texture) {
5137 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameteri", "unknown texture");
5138 return;
5141 texture_manager()->SetParameter(
5142 "glTexParameteri", GetErrorState(), texture, pname, param);
5145 void GLES2DecoderImpl::DoTexParameterfv(
5146 GLenum target, GLenum pname, const GLfloat* params) {
5147 TextureRef* texture = GetTextureInfoForTarget(target);
5148 if (!texture) {
5149 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterfv", "unknown texture");
5150 return;
5153 texture_manager()->SetParameter(
5154 "glTexParameterfv", GetErrorState(), texture, pname,
5155 static_cast<GLint>(params[0]));
5158 void GLES2DecoderImpl::DoTexParameteriv(
5159 GLenum target, GLenum pname, const GLint* params) {
5160 TextureRef* texture = GetTextureInfoForTarget(target);
5161 if (!texture) {
5162 LOCAL_SET_GL_ERROR(
5163 GL_INVALID_VALUE, "glTexParameteriv", "unknown texture");
5164 return;
5167 texture_manager()->SetParameter(
5168 "glTexParameteriv", GetErrorState(), texture, pname, *params);
5171 bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
5172 if (!state_.current_program.get()) {
5173 // The program does not exist.
5174 LOCAL_SET_GL_ERROR(
5175 GL_INVALID_OPERATION, function_name, "no program in use");
5176 return false;
5178 if (!state_.current_program->InUse()) {
5179 LOCAL_SET_GL_ERROR(
5180 GL_INVALID_OPERATION, function_name, "program not linked");
5181 return false;
5183 return true;
5186 bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
5187 GLint location, const char* function_name) {
5188 if (!CheckCurrentProgram(function_name)) {
5189 return false;
5191 return location != -1;
5194 namespace {
5196 static const GLenum valid_int_vec1_types_list[] = {
5197 GL_INT,
5198 GL_BOOL,
5199 GL_SAMPLER_2D,
5200 GL_SAMPLER_2D_RECT_ARB,
5201 GL_SAMPLER_CUBE,
5202 GL_SAMPLER_EXTERNAL_OES,
5205 static const GLenum valid_int_vec2_types_list[] = {
5206 GL_INT_VEC2,
5207 GL_BOOL_VEC2,
5210 static const GLenum valid_int_vec3_types_list[] = {
5211 GL_INT_VEC3,
5212 GL_BOOL_VEC3,
5215 static const GLenum valid_int_vec4_types_list[] = {
5216 GL_INT_VEC4,
5217 GL_BOOL_VEC4,
5220 static const GLenum valid_float_vec1_types_list[] = {
5221 GL_FLOAT,
5222 GL_BOOL,
5225 static const GLenum valid_float_vec2_types_list[] = {
5226 GL_FLOAT_VEC2,
5227 GL_BOOL_VEC2,
5230 static const GLenum valid_float_vec3_types_list[] = {
5231 GL_FLOAT_VEC3,
5232 GL_BOOL_VEC3,
5235 static const GLenum valid_float_vec4_types_list[] = {
5236 GL_FLOAT_VEC4,
5237 GL_BOOL_VEC4,
5240 static const GLenum valid_float_mat2_types_list[] = {
5241 GL_FLOAT_MAT2,
5244 static const GLenum valid_float_mat3_types_list[] = {
5245 GL_FLOAT_MAT3,
5248 static const GLenum valid_float_mat4_types_list[] = {
5249 GL_FLOAT_MAT4,
5252 static const GLES2DecoderImpl::BaseUniformInfo valid_int_vec1_base_info = {
5253 valid_int_vec1_types_list,
5254 arraysize(valid_int_vec1_types_list),
5257 static const GLES2DecoderImpl::BaseUniformInfo valid_int_vec2_base_info = {
5258 valid_int_vec2_types_list,
5259 arraysize(valid_int_vec2_types_list),
5262 static const GLES2DecoderImpl::BaseUniformInfo valid_int_vec3_base_info = {
5263 valid_int_vec3_types_list,
5264 arraysize(valid_int_vec3_types_list),
5267 static const GLES2DecoderImpl::BaseUniformInfo valid_int_vec4_base_info = {
5268 valid_int_vec4_types_list,
5269 arraysize(valid_int_vec4_types_list),
5272 static const GLES2DecoderImpl::BaseUniformInfo valid_float_vec1_base_info = {
5273 valid_float_vec1_types_list,
5274 arraysize(valid_float_vec1_types_list),
5277 static const GLES2DecoderImpl::BaseUniformInfo valid_float_vec2_base_info = {
5278 valid_float_vec2_types_list,
5279 arraysize(valid_float_vec2_types_list),
5282 static const GLES2DecoderImpl::BaseUniformInfo valid_float_vec3_base_info = {
5283 valid_float_vec3_types_list,
5284 arraysize(valid_float_vec3_types_list),
5287 static const GLES2DecoderImpl::BaseUniformInfo valid_float_vec4_base_info = {
5288 valid_float_vec4_types_list,
5289 arraysize(valid_float_vec4_types_list),
5292 static const GLES2DecoderImpl::BaseUniformInfo valid_float_mat2_base_info = {
5293 valid_float_mat2_types_list,
5294 arraysize(valid_float_mat2_types_list),
5297 static const GLES2DecoderImpl::BaseUniformInfo valid_float_mat3_base_info = {
5298 valid_float_mat3_types_list,
5299 arraysize(valid_float_mat3_types_list),
5302 static const GLES2DecoderImpl::BaseUniformInfo valid_float_mat4_base_info = {
5303 valid_float_mat4_types_list,
5304 arraysize(valid_float_mat4_types_list),
5307 } // anonymous namespace.
5309 bool GLES2DecoderImpl::PrepForSetUniformByLocation(
5310 GLint fake_location, const char* function_name,
5311 const GLES2DecoderImpl::BaseUniformInfo& base_info,
5312 GLint* real_location, GLenum* type, GLsizei* count) {
5313 DCHECK(type);
5314 DCHECK(count);
5315 DCHECK(real_location);
5317 if (!CheckCurrentProgramForUniform(fake_location, function_name)) {
5318 return false;
5320 GLint array_index = -1;
5321 const Program::UniformInfo* info =
5322 state_.current_program->GetUniformInfoByFakeLocation(
5323 fake_location, real_location, &array_index);
5324 if (!info) {
5325 LOCAL_SET_GL_ERROR(
5326 GL_INVALID_OPERATION, function_name, "unknown location");
5327 return false;
5329 bool okay = false;
5330 for (size_t ii = 0; ii < base_info.num_valid_types; ++ii) {
5331 if (base_info.valid_types[ii] == info->type) {
5332 okay = true;
5333 break;
5336 if (!okay) {
5337 LOCAL_SET_GL_ERROR(
5338 GL_INVALID_OPERATION, function_name,
5339 "wrong uniform function for type");
5340 return false;
5342 if (*count > 1 && !info->is_array) {
5343 LOCAL_SET_GL_ERROR(
5344 GL_INVALID_OPERATION, function_name, "count > 1 for non-array");
5345 return false;
5347 *count = std::min(info->size - array_index, *count);
5348 if (*count <= 0) {
5349 return false;
5351 *type = info->type;
5352 return true;
5355 void GLES2DecoderImpl::DoUniform1i(GLint fake_location, GLint v0) {
5356 GLenum type = 0;
5357 GLsizei count = 1;
5358 GLint real_location = -1;
5359 if (!PrepForSetUniformByLocation(
5360 fake_location, "glUniform1iv", valid_int_vec1_base_info,
5361 &real_location, &type, &count)) {
5362 return;
5364 if (!state_.current_program->SetSamplers(
5365 state_.texture_units.size(), fake_location, 1, &v0)) {
5366 LOCAL_SET_GL_ERROR(
5367 GL_INVALID_VALUE, "glUniform1i", "texture unit out of range");
5368 return;
5370 glUniform1i(real_location, v0);
5373 void GLES2DecoderImpl::DoUniform1iv(
5374 GLint fake_location, GLsizei count, const GLint *value) {
5375 GLenum type = 0;
5376 GLint real_location = -1;
5377 if (!PrepForSetUniformByLocation(
5378 fake_location, "glUniform1iv", valid_int_vec1_base_info,
5379 &real_location, &type, &count)) {
5380 return;
5382 if (type == GL_SAMPLER_2D || type == GL_SAMPLER_2D_RECT_ARB ||
5383 type == GL_SAMPLER_CUBE || type == GL_SAMPLER_EXTERNAL_OES) {
5384 if (!state_.current_program->SetSamplers(
5385 state_.texture_units.size(), fake_location, count, value)) {
5386 LOCAL_SET_GL_ERROR(
5387 GL_INVALID_VALUE, "glUniform1iv", "texture unit out of range");
5388 return;
5391 glUniform1iv(real_location, count, value);
5394 void GLES2DecoderImpl::DoUniform1fv(
5395 GLint fake_location, GLsizei count, const GLfloat* value) {
5396 GLenum type = 0;
5397 GLint real_location = -1;
5398 if (!PrepForSetUniformByLocation(
5399 fake_location, "glUniform1fv", valid_float_vec1_base_info,
5400 &real_location, &type, &count)) {
5401 return;
5403 if (type == GL_BOOL) {
5404 scoped_ptr<GLint[]> temp(new GLint[count]);
5405 for (GLsizei ii = 0; ii < count; ++ii) {
5406 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
5408 DoUniform1iv(real_location, count, temp.get());
5409 } else {
5410 glUniform1fv(real_location, count, value);
5414 void GLES2DecoderImpl::DoUniform2fv(
5415 GLint fake_location, GLsizei count, const GLfloat* value) {
5416 GLenum type = 0;
5417 GLint real_location = -1;
5418 if (!PrepForSetUniformByLocation(
5419 fake_location, "glUniform2fv", valid_float_vec2_base_info,
5420 &real_location, &type, &count)) {
5421 return;
5423 if (type == GL_BOOL_VEC2) {
5424 GLsizei num_values = count * 2;
5425 scoped_ptr<GLint[]> temp(new GLint[num_values]);
5426 for (GLsizei ii = 0; ii < num_values; ++ii) {
5427 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
5429 glUniform2iv(real_location, count, temp.get());
5430 } else {
5431 glUniform2fv(real_location, count, value);
5435 void GLES2DecoderImpl::DoUniform3fv(
5436 GLint fake_location, GLsizei count, const GLfloat* value) {
5437 GLenum type = 0;
5438 GLint real_location = -1;
5439 if (!PrepForSetUniformByLocation(
5440 fake_location, "glUniform3fv", valid_float_vec3_base_info,
5441 &real_location, &type, &count)) {
5442 return;
5444 if (type == GL_BOOL_VEC3) {
5445 GLsizei num_values = count * 3;
5446 scoped_ptr<GLint[]> temp(new GLint[num_values]);
5447 for (GLsizei ii = 0; ii < num_values; ++ii) {
5448 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
5450 glUniform3iv(real_location, count, temp.get());
5451 } else {
5452 glUniform3fv(real_location, count, value);
5456 void GLES2DecoderImpl::DoUniform4fv(
5457 GLint fake_location, GLsizei count, const GLfloat* value) {
5458 GLenum type = 0;
5459 GLint real_location = -1;
5460 if (!PrepForSetUniformByLocation(
5461 fake_location, "glUniform4fv", valid_float_vec4_base_info,
5462 &real_location, &type, &count)) {
5463 return;
5465 if (type == GL_BOOL_VEC4) {
5466 GLsizei num_values = count * 4;
5467 scoped_ptr<GLint[]> temp(new GLint[num_values]);
5468 for (GLsizei ii = 0; ii < num_values; ++ii) {
5469 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
5471 glUniform4iv(real_location, count, temp.get());
5472 } else {
5473 glUniform4fv(real_location, count, value);
5477 void GLES2DecoderImpl::DoUniform2iv(
5478 GLint fake_location, GLsizei count, const GLint* value) {
5479 GLenum type = 0;
5480 GLint real_location = -1;
5481 if (!PrepForSetUniformByLocation(
5482 fake_location, "glUniform2iv", valid_int_vec2_base_info,
5483 &real_location, &type, &count)) {
5484 return;
5486 glUniform2iv(real_location, count, value);
5489 void GLES2DecoderImpl::DoUniform3iv(
5490 GLint fake_location, GLsizei count, const GLint* value) {
5491 GLenum type = 0;
5492 GLint real_location = -1;
5493 if (!PrepForSetUniformByLocation(
5494 fake_location, "glUniform3iv", valid_int_vec3_base_info,
5495 &real_location, &type, &count)) {
5496 return;
5498 glUniform3iv(real_location, count, value);
5501 void GLES2DecoderImpl::DoUniform4iv(
5502 GLint fake_location, GLsizei count, const GLint* value) {
5503 GLenum type = 0;
5504 GLint real_location = -1;
5505 if (!PrepForSetUniformByLocation(
5506 fake_location, "glUniform4iv", valid_int_vec4_base_info,
5507 &real_location, &type, &count)) {
5508 return;
5510 glUniform4iv(real_location, count, value);
5513 void GLES2DecoderImpl::DoUniformMatrix2fv(
5514 GLint fake_location, GLsizei count, GLboolean transpose,
5515 const GLfloat* value) {
5516 GLenum type = 0;
5517 GLint real_location = -1;
5518 if (!PrepForSetUniformByLocation(
5519 fake_location, "glUniformMatrix2fv", valid_float_mat2_base_info,
5520 &real_location, &type, &count)) {
5521 return;
5523 glUniformMatrix2fv(real_location, count, transpose, value);
5526 void GLES2DecoderImpl::DoUniformMatrix3fv(
5527 GLint fake_location, GLsizei count, GLboolean transpose,
5528 const GLfloat* value) {
5529 GLenum type = 0;
5530 GLint real_location = -1;
5531 if (!PrepForSetUniformByLocation(
5532 fake_location, "glUniformMatrix3fv", valid_float_mat3_base_info,
5533 &real_location, &type, &count)) {
5534 return;
5536 glUniformMatrix3fv(real_location, count, transpose, value);
5539 void GLES2DecoderImpl::DoUniformMatrix4fv(
5540 GLint fake_location, GLsizei count, GLboolean transpose,
5541 const GLfloat* value) {
5542 GLenum type = 0;
5543 GLint real_location = -1;
5544 if (!PrepForSetUniformByLocation(
5545 fake_location, "glUniformMatrix4fv", valid_float_mat4_base_info,
5546 &real_location, &type, &count)) {
5547 return;
5549 glUniformMatrix4fv(real_location, count, transpose, value);
5552 void GLES2DecoderImpl::DoUseProgram(GLuint program_id) {
5553 GLuint service_id = 0;
5554 Program* program = NULL;
5555 if (program_id) {
5556 program = GetProgramInfoNotShader(program_id, "glUseProgram");
5557 if (!program) {
5558 return;
5560 if (!program->IsValid()) {
5561 // Program was not linked successfully. (ie, glLinkProgram)
5562 LOCAL_SET_GL_ERROR(
5563 GL_INVALID_OPERATION, "glUseProgram", "program not linked");
5564 return;
5566 service_id = program->service_id();
5568 if (state_.current_program.get()) {
5569 program_manager()->UnuseProgram(shader_manager(),
5570 state_.current_program.get());
5572 state_.current_program = program;
5573 LogClientServiceMapping("glUseProgram", program_id, service_id);
5574 glUseProgram(service_id);
5575 if (state_.current_program.get()) {
5576 program_manager()->UseProgram(state_.current_program.get());
5580 void GLES2DecoderImpl::RenderWarning(
5581 const char* filename, int line, const std::string& msg) {
5582 logger_.LogMessage(filename, line, std::string("RENDER WARNING: ") + msg);
5585 void GLES2DecoderImpl::PerformanceWarning(
5586 const char* filename, int line, const std::string& msg) {
5587 logger_.LogMessage(filename, line,
5588 std::string("PERFORMANCE WARNING: ") + msg);
5591 void GLES2DecoderImpl::ForceCompileShaderIfPending(Shader* shader) {
5592 if (shader->compilation_status() ==
5593 Shader::PENDING_DEFERRED_COMPILE) {
5594 ShaderTranslator* translator = NULL;
5595 if (use_shader_translator_) {
5596 translator = shader->shader_type() == GL_VERTEX_SHADER ?
5597 vertex_translator_.get() : fragment_translator_.get();
5599 // We know there will be no errors, because we only defer compilation on
5600 // shaders that were previously compiled successfully.
5601 program_manager()->ForceCompileShader(shader->deferred_compilation_source(),
5602 shader,
5603 translator,
5604 feature_info_.get());
5608 bool GLES2DecoderImpl::SetBlackTextureForNonRenderableTextures() {
5609 DCHECK(state_.current_program.get());
5610 // Only check if there are some unrenderable textures.
5611 if (!texture_manager()->HaveUnrenderableTextures()) {
5612 return false;
5615 bool textures_set = false;
5616 const Program::SamplerIndices& sampler_indices =
5617 state_.current_program->sampler_indices();
5618 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
5619 const Program::UniformInfo* uniform_info =
5620 state_.current_program->GetUniformInfo(sampler_indices[ii]);
5621 DCHECK(uniform_info);
5622 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
5623 GLuint texture_unit_index = uniform_info->texture_units[jj];
5624 if (texture_unit_index < state_.texture_units.size()) {
5625 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
5626 TextureRef* texture =
5627 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
5628 if (!texture || !texture_manager()->CanRender(texture)) {
5629 textures_set = true;
5630 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
5631 glBindTexture(
5632 GetBindTargetForSamplerType(uniform_info->type),
5633 texture_manager()->black_texture_id(uniform_info->type));
5634 LOCAL_RENDER_WARNING(
5635 std::string("texture bound to texture unit ") +
5636 base::IntToString(texture_unit_index) +
5637 " is not renderable. It maybe non-power-of-2 and have"
5638 " incompatible texture filtering or is not"
5639 " 'texture complete'");
5642 // else: should this be an error?
5645 return textures_set;
5648 void GLES2DecoderImpl::RestoreStateForNonRenderableTextures() {
5649 DCHECK(state_.current_program.get());
5650 const Program::SamplerIndices& sampler_indices =
5651 state_.current_program->sampler_indices();
5652 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
5653 const Program::UniformInfo* uniform_info =
5654 state_.current_program->GetUniformInfo(sampler_indices[ii]);
5655 DCHECK(uniform_info);
5656 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
5657 GLuint texture_unit_index = uniform_info->texture_units[jj];
5658 if (texture_unit_index < state_.texture_units.size()) {
5659 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
5660 TextureRef* texture_ref =
5661 uniform_info->type == GL_SAMPLER_2D
5662 ? texture_unit.bound_texture_2d.get()
5663 : texture_unit.bound_texture_cube_map.get();
5664 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
5665 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
5666 // Get the texture_ref info that was previously bound here.
5667 texture_ref = texture_unit.bind_target == GL_TEXTURE_2D
5668 ? texture_unit.bound_texture_2d.get()
5669 : texture_unit.bound_texture_cube_map.get();
5670 glBindTexture(texture_unit.bind_target,
5671 texture_ref ? texture_ref->service_id() : 0);
5676 // Set the active texture back to whatever the user had it as.
5677 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
5680 bool GLES2DecoderImpl::ClearUnclearedTextures() {
5681 // Only check if there are some uncleared textures.
5682 if (!texture_manager()->HaveUnsafeTextures()) {
5683 return true;
5686 // 1: Check all textures we are about to render with.
5687 if (state_.current_program.get()) {
5688 const Program::SamplerIndices& sampler_indices =
5689 state_.current_program->sampler_indices();
5690 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
5691 const Program::UniformInfo* uniform_info =
5692 state_.current_program->GetUniformInfo(sampler_indices[ii]);
5693 DCHECK(uniform_info);
5694 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
5695 GLuint texture_unit_index = uniform_info->texture_units[jj];
5696 if (texture_unit_index < state_.texture_units.size()) {
5697 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
5698 TextureRef* texture_ref =
5699 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
5700 if (texture_ref && !texture_ref->texture()->SafeToRenderFrom()) {
5701 if (!texture_manager()->ClearRenderableLevels(this, texture_ref)) {
5702 return false;
5709 return true;
5712 bool GLES2DecoderImpl::IsDrawValid(
5713 const char* function_name, GLuint max_vertex_accessed, GLsizei primcount) {
5714 // NOTE: We specifically do not check current_program->IsValid() because
5715 // it could never be invalid since glUseProgram would have failed. While
5716 // glLinkProgram could later mark the program as invalid the previous
5717 // valid program will still function if it is still the current program.
5718 if (!state_.current_program.get()) {
5719 // The program does not exist.
5720 // But GL says no ERROR.
5721 LOCAL_RENDER_WARNING("Drawing with no current shader program.");
5722 return false;
5725 return state_.vertex_attrib_manager
5726 ->ValidateBindings(function_name,
5727 this,
5728 feature_info_.get(),
5729 state_.current_program.get(),
5730 max_vertex_accessed,
5731 primcount);
5734 bool GLES2DecoderImpl::SimulateAttrib0(
5735 const char* function_name, GLuint max_vertex_accessed, bool* simulated) {
5736 DCHECK(simulated);
5737 *simulated = false;
5739 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
5740 return true;
5742 const VertexAttrib* attrib =
5743 state_.vertex_attrib_manager->GetVertexAttrib(0);
5744 // If it's enabled or it's not used then we don't need to do anything.
5745 bool attrib_0_used =
5746 state_.current_program->GetAttribInfoByLocation(0) != NULL;
5747 if (attrib->enabled() && attrib_0_used) {
5748 return true;
5751 // Make a buffer with a single repeated vec4 value enough to
5752 // simulate the constant value that is supposed to be here.
5753 // This is required to emulate GLES2 on GL.
5754 GLuint num_vertices = max_vertex_accessed + 1;
5755 uint32 size_needed = 0;
5757 if (num_vertices == 0 ||
5758 !SafeMultiplyUint32(num_vertices, sizeof(Vec4), &size_needed) ||
5759 size_needed > 0x7FFFFFFFU) {
5760 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
5761 return false;
5764 LOCAL_PERFORMANCE_WARNING(
5765 "Attribute 0 is disabled. This has signficant performance penalty");
5767 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
5768 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
5770 bool new_buffer = static_cast<GLsizei>(size_needed) > attrib_0_size_;
5771 if (new_buffer) {
5772 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
5773 GLenum error = glGetError();
5774 if (error != GL_NO_ERROR) {
5775 LOCAL_SET_GL_ERROR(
5776 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
5777 return false;
5781 const Vec4& value = state_.attrib_values[0];
5782 if (new_buffer ||
5783 (attrib_0_used &&
5784 (!attrib_0_buffer_matches_value_ ||
5785 (value.v[0] != attrib_0_value_.v[0] ||
5786 value.v[1] != attrib_0_value_.v[1] ||
5787 value.v[2] != attrib_0_value_.v[2] ||
5788 value.v[3] != attrib_0_value_.v[3])))) {
5789 std::vector<Vec4> temp(num_vertices, value);
5790 glBufferSubData(GL_ARRAY_BUFFER, 0, size_needed, &temp[0].v[0]);
5791 attrib_0_buffer_matches_value_ = true;
5792 attrib_0_value_ = value;
5793 attrib_0_size_ = size_needed;
5796 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
5798 if (attrib->divisor())
5799 glVertexAttribDivisorANGLE(0, 0);
5801 *simulated = true;
5802 return true;
5805 void GLES2DecoderImpl::RestoreStateForAttrib(GLuint attrib_index) {
5806 const VertexAttrib* attrib =
5807 state_.vertex_attrib_manager->GetVertexAttrib(attrib_index);
5808 const void* ptr = reinterpret_cast<const void*>(attrib->offset());
5809 Buffer* buffer = attrib->buffer();
5810 glBindBuffer(GL_ARRAY_BUFFER, buffer ? buffer->service_id() : 0);
5811 glVertexAttribPointer(
5812 attrib_index, attrib->size(), attrib->type(), attrib->normalized(),
5813 attrib->gl_stride(), ptr);
5814 if (attrib->divisor())
5815 glVertexAttribDivisorANGLE(attrib_index, attrib->divisor());
5816 glBindBuffer(
5817 GL_ARRAY_BUFFER,
5818 state_.bound_array_buffer.get() ? state_.bound_array_buffer->service_id()
5819 : 0);
5821 // Never touch vertex attribute 0's state (in particular, never
5822 // disable it) when running on desktop GL because it will never be
5823 // re-enabled.
5824 if (attrib_index != 0 ||
5825 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
5826 if (attrib->enabled()) {
5827 glEnableVertexAttribArray(attrib_index);
5828 } else {
5829 glDisableVertexAttribArray(attrib_index);
5834 bool GLES2DecoderImpl::SimulateFixedAttribs(
5835 const char* function_name,
5836 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount) {
5837 DCHECK(simulated);
5838 *simulated = false;
5839 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
5840 return true;
5842 if (!state_.vertex_attrib_manager->HaveFixedAttribs()) {
5843 return true;
5846 LOCAL_PERFORMANCE_WARNING(
5847 "GL_FIXED attributes have a signficant performance penalty");
5849 // NOTE: we could be smart and try to check if a buffer is used
5850 // twice in 2 different attribs, find the overlapping parts and therefore
5851 // duplicate the minimum amount of data but this whole code path is not meant
5852 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
5853 // tests so we just add to the buffer attrib used.
5855 GLuint elements_needed = 0;
5856 const VertexAttribManager::VertexAttribList& enabled_attribs =
5857 state_.vertex_attrib_manager->GetEnabledVertexAttribs();
5858 for (VertexAttribManager::VertexAttribList::const_iterator it =
5859 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
5860 const VertexAttrib* attrib = *it;
5861 const Program::VertexAttrib* attrib_info =
5862 state_.current_program->GetAttribInfoByLocation(attrib->index());
5863 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
5864 max_vertex_accessed);
5865 GLuint num_vertices = max_accessed + 1;
5866 if (num_vertices == 0) {
5867 LOCAL_SET_GL_ERROR(
5868 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
5869 return false;
5871 if (attrib_info &&
5872 attrib->CanAccess(max_accessed) &&
5873 attrib->type() == GL_FIXED) {
5874 uint32 elements_used = 0;
5875 if (!SafeMultiplyUint32(num_vertices, attrib->size(), &elements_used) ||
5876 !SafeAddUint32(elements_needed, elements_used, &elements_needed)) {
5877 LOCAL_SET_GL_ERROR(
5878 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
5879 return false;
5884 const uint32 kSizeOfFloat = sizeof(float); // NOLINT
5885 uint32 size_needed = 0;
5886 if (!SafeMultiplyUint32(elements_needed, kSizeOfFloat, &size_needed) ||
5887 size_needed > 0x7FFFFFFFU) {
5888 LOCAL_SET_GL_ERROR(
5889 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
5890 return false;
5893 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
5895 glBindBuffer(GL_ARRAY_BUFFER, fixed_attrib_buffer_id_);
5896 if (static_cast<GLsizei>(size_needed) > fixed_attrib_buffer_size_) {
5897 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
5898 GLenum error = glGetError();
5899 if (error != GL_NO_ERROR) {
5900 LOCAL_SET_GL_ERROR(
5901 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
5902 return false;
5906 // Copy the elements and convert to float
5907 GLintptr offset = 0;
5908 for (VertexAttribManager::VertexAttribList::const_iterator it =
5909 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
5910 const VertexAttrib* attrib = *it;
5911 const Program::VertexAttrib* attrib_info =
5912 state_.current_program->GetAttribInfoByLocation(attrib->index());
5913 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
5914 max_vertex_accessed);
5915 GLuint num_vertices = max_accessed + 1;
5916 if (num_vertices == 0) {
5917 LOCAL_SET_GL_ERROR(
5918 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
5919 return false;
5921 if (attrib_info &&
5922 attrib->CanAccess(max_accessed) &&
5923 attrib->type() == GL_FIXED) {
5924 int num_elements = attrib->size() * kSizeOfFloat;
5925 int size = num_elements * num_vertices;
5926 scoped_ptr<float[]> data(new float[size]);
5927 const int32* src = reinterpret_cast<const int32 *>(
5928 attrib->buffer()->GetRange(attrib->offset(), size));
5929 const int32* end = src + num_elements;
5930 float* dst = data.get();
5931 while (src != end) {
5932 *dst++ = static_cast<float>(*src++) / 65536.0f;
5934 glBufferSubData(GL_ARRAY_BUFFER, offset, size, data.get());
5935 glVertexAttribPointer(
5936 attrib->index(), attrib->size(), GL_FLOAT, false, 0,
5937 reinterpret_cast<GLvoid*>(offset));
5938 offset += size;
5941 *simulated = true;
5942 return true;
5945 void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
5946 // There's no need to call glVertexAttribPointer because we shadow all the
5947 // settings and passing GL_FIXED to it will not work.
5948 glBindBuffer(
5949 GL_ARRAY_BUFFER,
5950 state_.bound_array_buffer.get() ? state_.bound_array_buffer->service_id()
5951 : 0);
5954 error::Error GLES2DecoderImpl::DoDrawArrays(
5955 const char* function_name,
5956 bool instanced,
5957 GLenum mode,
5958 GLint first,
5959 GLsizei count,
5960 GLsizei primcount) {
5961 if (ShouldDeferDraws())
5962 return error::kDeferCommandUntilLater;
5963 if (!validators_->draw_mode.IsValid(mode)) {
5964 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
5965 return error::kNoError;
5967 if (count < 0) {
5968 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
5969 return error::kNoError;
5971 if (primcount < 0) {
5972 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
5973 return error::kNoError;
5975 if (!CheckBoundFramebuffersValid(function_name)) {
5976 return error::kNoError;
5978 // We have to check this here because the prototype for glDrawArrays
5979 // is GLint not GLsizei.
5980 if (first < 0) {
5981 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "first < 0");
5982 return error::kNoError;
5985 if (count == 0 || (instanced && primcount == 0)) {
5986 LOCAL_RENDER_WARNING("Render count or primcount is 0.");
5987 return error::kNoError;
5990 GLuint max_vertex_accessed = first + count - 1;
5991 if (IsDrawValid(function_name, max_vertex_accessed, primcount)) {
5992 if (!ClearUnclearedTextures()) {
5993 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
5994 return error::kNoError;
5996 bool simulated_attrib_0 = false;
5997 if (!SimulateAttrib0(
5998 function_name, max_vertex_accessed, &simulated_attrib_0)) {
5999 return error::kNoError;
6001 bool simulated_fixed_attribs = false;
6002 if (SimulateFixedAttribs(
6003 function_name, max_vertex_accessed, &simulated_fixed_attribs,
6004 primcount)) {
6005 bool textures_set = SetBlackTextureForNonRenderableTextures();
6006 ApplyDirtyState();
6007 if (!instanced) {
6008 glDrawArrays(mode, first, count);
6009 } else {
6010 glDrawArraysInstancedANGLE(mode, first, count, primcount);
6012 ProcessPendingQueries();
6013 if (textures_set) {
6014 RestoreStateForNonRenderableTextures();
6016 if (simulated_fixed_attribs) {
6017 RestoreStateForSimulatedFixedAttribs();
6020 if (simulated_attrib_0) {
6021 RestoreStateForAttrib(0);
6024 return error::kNoError;
6027 error::Error GLES2DecoderImpl::HandleDrawArrays(
6028 uint32 immediate_data_size, const cmds::DrawArrays& c) {
6029 return DoDrawArrays("glDrawArrays",
6030 false,
6031 static_cast<GLenum>(c.mode),
6032 static_cast<GLint>(c.first),
6033 static_cast<GLsizei>(c.count),
6037 error::Error GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
6038 uint32 immediate_data_size, const cmds::DrawArraysInstancedANGLE& c) {
6039 if (!features().angle_instanced_arrays) {
6040 LOCAL_SET_GL_ERROR(
6041 GL_INVALID_OPERATION,
6042 "glDrawArraysInstancedANGLE", "function not available");
6043 return error::kNoError;
6045 return DoDrawArrays("glDrawArraysIntancedANGLE",
6046 true,
6047 static_cast<GLenum>(c.mode),
6048 static_cast<GLint>(c.first),
6049 static_cast<GLsizei>(c.count),
6050 static_cast<GLsizei>(c.primcount));
6053 error::Error GLES2DecoderImpl::DoDrawElements(
6054 const char* function_name,
6055 bool instanced,
6056 GLenum mode,
6057 GLsizei count,
6058 GLenum type,
6059 int32 offset,
6060 GLsizei primcount) {
6061 if (ShouldDeferDraws())
6062 return error::kDeferCommandUntilLater;
6063 if (!state_.vertex_attrib_manager->element_array_buffer()) {
6064 LOCAL_SET_GL_ERROR(
6065 GL_INVALID_OPERATION, function_name, "No element array buffer bound");
6066 return error::kNoError;
6069 if (count < 0) {
6070 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
6071 return error::kNoError;
6073 if (offset < 0) {
6074 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "offset < 0");
6075 return error::kNoError;
6077 if (!validators_->draw_mode.IsValid(mode)) {
6078 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
6079 return error::kNoError;
6081 if (!validators_->index_type.IsValid(type)) {
6082 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, type, "type");
6083 return error::kNoError;
6085 if (primcount < 0) {
6086 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
6087 return error::kNoError;
6090 if (!CheckBoundFramebuffersValid(function_name)) {
6091 return error::kNoError;
6094 if (count == 0 || (instanced && primcount == 0)) {
6095 return error::kNoError;
6098 GLuint max_vertex_accessed;
6099 Buffer* element_array_buffer =
6100 state_.vertex_attrib_manager->element_array_buffer();
6102 if (!element_array_buffer->GetMaxValueForRange(
6103 offset, count, type, &max_vertex_accessed)) {
6104 LOCAL_SET_GL_ERROR(
6105 GL_INVALID_OPERATION, function_name, "range out of bounds for buffer");
6106 return error::kNoError;
6109 if (IsDrawValid(function_name, max_vertex_accessed, primcount)) {
6110 if (!ClearUnclearedTextures()) {
6111 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
6112 return error::kNoError;
6114 bool simulated_attrib_0 = false;
6115 if (!SimulateAttrib0(
6116 function_name, max_vertex_accessed, &simulated_attrib_0)) {
6117 return error::kNoError;
6119 bool simulated_fixed_attribs = false;
6120 if (SimulateFixedAttribs(
6121 function_name, max_vertex_accessed, &simulated_fixed_attribs,
6122 primcount)) {
6123 bool textures_set = SetBlackTextureForNonRenderableTextures();
6124 ApplyDirtyState();
6125 // TODO(gman): Refactor to hide these details in BufferManager or
6126 // VertexAttribManager.
6127 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
6128 bool used_client_side_array = false;
6129 if (element_array_buffer->IsClientSideArray()) {
6130 used_client_side_array = true;
6131 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
6132 indices = element_array_buffer->GetRange(offset, 0);
6135 if (!instanced) {
6136 glDrawElements(mode, count, type, indices);
6137 } else {
6138 glDrawElementsInstancedANGLE(mode, count, type, indices, primcount);
6141 if (used_client_side_array) {
6142 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
6143 element_array_buffer->service_id());
6146 ProcessPendingQueries();
6147 if (textures_set) {
6148 RestoreStateForNonRenderableTextures();
6150 if (simulated_fixed_attribs) {
6151 RestoreStateForSimulatedFixedAttribs();
6154 if (simulated_attrib_0) {
6155 RestoreStateForAttrib(0);
6158 return error::kNoError;
6161 error::Error GLES2DecoderImpl::HandleDrawElements(
6162 uint32 immediate_data_size, const cmds::DrawElements& c) {
6163 return DoDrawElements("glDrawElements",
6164 false,
6165 static_cast<GLenum>(c.mode),
6166 static_cast<GLsizei>(c.count),
6167 static_cast<GLenum>(c.type),
6168 static_cast<int32>(c.index_offset),
6172 error::Error GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
6173 uint32 immediate_data_size, const cmds::DrawElementsInstancedANGLE& c) {
6174 if (!features().angle_instanced_arrays) {
6175 LOCAL_SET_GL_ERROR(
6176 GL_INVALID_OPERATION,
6177 "glDrawElementsInstancedANGLE", "function not available");
6178 return error::kNoError;
6180 return DoDrawElements("glDrawElementsInstancedANGLE",
6181 true,
6182 static_cast<GLenum>(c.mode),
6183 static_cast<GLsizei>(c.count),
6184 static_cast<GLenum>(c.type),
6185 static_cast<int32>(c.index_offset),
6186 static_cast<GLsizei>(c.primcount));
6189 GLuint GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
6190 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
6191 GLuint max_vertex_accessed = 0;
6192 Buffer* buffer = GetBuffer(buffer_id);
6193 if (!buffer) {
6194 // TODO(gman): Should this be a GL error or a command buffer error?
6195 LOCAL_SET_GL_ERROR(
6196 GL_INVALID_VALUE, "GetMaxValueInBufferCHROMIUM", "unknown buffer");
6197 } else {
6198 if (!buffer->GetMaxValueForRange(
6199 offset, count, type, &max_vertex_accessed)) {
6200 // TODO(gman): Should this be a GL error or a command buffer error?
6201 LOCAL_SET_GL_ERROR(
6202 GL_INVALID_OPERATION,
6203 "GetMaxValueInBufferCHROMIUM", "range out of bounds for buffer");
6206 return max_vertex_accessed;
6209 // Calls glShaderSource for the various versions of the ShaderSource command.
6210 // Assumes that data / data_size points to a piece of memory that is in range
6211 // of whatever context it came from (shared memory, immediate memory, bucket
6212 // memory.)
6213 error::Error GLES2DecoderImpl::ShaderSourceHelper(
6214 GLuint client_id, const char* data, uint32 data_size) {
6215 std::string str(data, data + data_size);
6216 Shader* shader = GetShaderInfoNotProgram(client_id, "glShaderSource");
6217 if (!shader) {
6218 return error::kNoError;
6220 // Note: We don't actually call glShaderSource here. We wait until
6221 // the call to glCompileShader.
6222 shader->UpdateSource(str.c_str());
6223 return error::kNoError;
6226 error::Error GLES2DecoderImpl::HandleShaderSource(
6227 uint32 immediate_data_size, const cmds::ShaderSource& c) {
6228 uint32 data_size = c.data_size;
6229 const char* data = GetSharedMemoryAs<const char*>(
6230 c.data_shm_id, c.data_shm_offset, data_size);
6231 if (!data) {
6232 return error::kOutOfBounds;
6234 return ShaderSourceHelper(c.shader, data, data_size);
6237 error::Error GLES2DecoderImpl::HandleShaderSourceImmediate(
6238 uint32 immediate_data_size, const cmds::ShaderSourceImmediate& c) {
6239 uint32 data_size = c.data_size;
6240 const char* data = GetImmediateDataAs<const char*>(
6241 c, data_size, immediate_data_size);
6242 if (!data) {
6243 return error::kOutOfBounds;
6245 return ShaderSourceHelper(c.shader, data, data_size);
6248 error::Error GLES2DecoderImpl::HandleShaderSourceBucket(
6249 uint32 immediate_data_size, const cmds::ShaderSourceBucket& c) {
6250 Bucket* bucket = GetBucket(c.data_bucket_id);
6251 if (!bucket || bucket->size() == 0) {
6252 return error::kInvalidArguments;
6254 return ShaderSourceHelper(
6255 c.shader, bucket->GetDataAs<const char*>(0, bucket->size() - 1),
6256 bucket->size() - 1);
6259 void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
6260 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
6261 Shader* shader = GetShaderInfoNotProgram(client_id, "glCompileShader");
6262 if (!shader) {
6263 return;
6265 ShaderTranslator* translator = NULL;
6266 if (use_shader_translator_) {
6267 translator = shader->shader_type() == GL_VERTEX_SHADER ?
6268 vertex_translator_.get() : fragment_translator_.get();
6271 program_manager()->DoCompileShader(shader, translator, feature_info_.get());
6274 void GLES2DecoderImpl::DoGetShaderiv(
6275 GLuint shader_id, GLenum pname, GLint* params) {
6276 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderiv");
6277 if (!shader) {
6278 return;
6280 switch (pname) {
6281 case GL_SHADER_SOURCE_LENGTH:
6282 *params = shader->source() ? shader->source()->size() + 1 : 0;
6283 return;
6284 case GL_COMPILE_STATUS:
6285 *params = compile_shader_always_succeeds_ ? true : shader->IsValid();
6286 return;
6287 case GL_INFO_LOG_LENGTH:
6288 *params = shader->log_info() ? shader->log_info()->size() + 1 : 0;
6289 return;
6290 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
6291 ForceCompileShaderIfPending(shader);
6292 *params = shader->translated_source() ?
6293 shader->translated_source()->size() + 1 : 0;
6294 return;
6295 default:
6296 break;
6298 glGetShaderiv(shader->service_id(), pname, params);
6301 error::Error GLES2DecoderImpl::HandleGetShaderSource(
6302 uint32 immediate_data_size, const cmds::GetShaderSource& c) {
6303 GLuint shader_id = c.shader;
6304 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6305 Bucket* bucket = CreateBucket(bucket_id);
6306 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderSource");
6307 if (!shader || !shader->source()) {
6308 bucket->SetSize(0);
6309 return error::kNoError;
6311 bucket->SetFromString(shader->source()->c_str());
6312 return error::kNoError;
6315 error::Error GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
6316 uint32 immediate_data_size,
6317 const cmds::GetTranslatedShaderSourceANGLE& c) {
6318 GLuint shader_id = c.shader;
6319 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6320 Bucket* bucket = CreateBucket(bucket_id);
6321 Shader* shader = GetShaderInfoNotProgram(
6322 shader_id, "glTranslatedGetShaderSourceANGLE");
6323 if (!shader) {
6324 bucket->SetSize(0);
6325 return error::kNoError;
6327 ForceCompileShaderIfPending(shader);
6329 bucket->SetFromString(shader->translated_source() ?
6330 shader->translated_source()->c_str() : NULL);
6331 return error::kNoError;
6334 error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
6335 uint32 immediate_data_size, const cmds::GetProgramInfoLog& c) {
6336 GLuint program_id = c.program;
6337 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6338 Bucket* bucket = CreateBucket(bucket_id);
6339 Program* program = GetProgramInfoNotShader(
6340 program_id, "glGetProgramInfoLog");
6341 if (!program || !program->log_info()) {
6342 bucket->SetFromString("");
6343 return error::kNoError;
6345 bucket->SetFromString(program->log_info()->c_str());
6346 return error::kNoError;
6349 error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
6350 uint32 immediate_data_size, const cmds::GetShaderInfoLog& c) {
6351 GLuint shader_id = c.shader;
6352 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6353 Bucket* bucket = CreateBucket(bucket_id);
6354 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderInfoLog");
6355 if (!shader || !shader->log_info()) {
6356 bucket->SetFromString("");
6357 return error::kNoError;
6359 bucket->SetFromString(shader->log_info()->c_str());
6360 return error::kNoError;
6363 bool GLES2DecoderImpl::DoIsEnabled(GLenum cap) {
6364 return state_.GetEnabled(cap);
6367 bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
6368 const Buffer* buffer = GetBuffer(client_id);
6369 return buffer && buffer->IsValid() && !buffer->IsDeleted();
6372 bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
6373 const Framebuffer* framebuffer =
6374 GetFramebuffer(client_id);
6375 return framebuffer && framebuffer->IsValid() && !framebuffer->IsDeleted();
6378 bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
6379 // IsProgram is true for programs as soon as they are created, until they are
6380 // deleted and no longer in use.
6381 const Program* program = GetProgram(client_id);
6382 return program != NULL && !program->IsDeleted();
6385 bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
6386 const Renderbuffer* renderbuffer =
6387 GetRenderbuffer(client_id);
6388 return renderbuffer && renderbuffer->IsValid() && !renderbuffer->IsDeleted();
6391 bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
6392 // IsShader is true for shaders as soon as they are created, until they
6393 // are deleted and not attached to any programs.
6394 const Shader* shader = GetShader(client_id);
6395 return shader != NULL && !shader->IsDeleted();
6398 bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
6399 const TextureRef* texture_ref = GetTexture(client_id);
6400 return texture_ref && texture_ref->texture()->IsValid();
6403 void GLES2DecoderImpl::DoAttachShader(
6404 GLuint program_client_id, GLint shader_client_id) {
6405 Program* program = GetProgramInfoNotShader(
6406 program_client_id, "glAttachShader");
6407 if (!program) {
6408 return;
6410 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glAttachShader");
6411 if (!shader) {
6412 return;
6414 if (!program->AttachShader(shader_manager(), shader)) {
6415 LOCAL_SET_GL_ERROR(
6416 GL_INVALID_OPERATION,
6417 "glAttachShader",
6418 "can not attach more than one shader of the same type.");
6419 return;
6421 glAttachShader(program->service_id(), shader->service_id());
6424 void GLES2DecoderImpl::DoDetachShader(
6425 GLuint program_client_id, GLint shader_client_id) {
6426 Program* program = GetProgramInfoNotShader(
6427 program_client_id, "glDetachShader");
6428 if (!program) {
6429 return;
6431 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glDetachShader");
6432 if (!shader) {
6433 return;
6435 if (!program->DetachShader(shader_manager(), shader)) {
6436 LOCAL_SET_GL_ERROR(
6437 GL_INVALID_OPERATION,
6438 "glDetachShader", "shader not attached to program");
6439 return;
6441 glDetachShader(program->service_id(), shader->service_id());
6444 void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
6445 Program* program = GetProgramInfoNotShader(
6446 program_client_id, "glValidateProgram");
6447 if (!program) {
6448 return;
6450 program->Validate();
6453 void GLES2DecoderImpl::GetVertexAttribHelper(
6454 const VertexAttrib* attrib, GLenum pname, GLint* params) {
6455 switch (pname) {
6456 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
6457 Buffer* buffer = attrib->buffer();
6458 if (buffer && !buffer->IsDeleted()) {
6459 GLuint client_id;
6460 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
6461 *params = client_id;
6463 break;
6465 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
6466 *params = attrib->enabled();
6467 break;
6468 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
6469 *params = attrib->size();
6470 break;
6471 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
6472 *params = attrib->gl_stride();
6473 break;
6474 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
6475 *params = attrib->type();
6476 break;
6477 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
6478 *params = attrib->normalized();
6479 break;
6480 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE:
6481 *params = attrib->divisor();
6482 break;
6483 default:
6484 NOTREACHED();
6485 break;
6489 void GLES2DecoderImpl::DoGetVertexAttribfv(
6490 GLuint index, GLenum pname, GLfloat* params) {
6491 VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(index);
6492 if (!attrib) {
6493 LOCAL_SET_GL_ERROR(
6494 GL_INVALID_VALUE, "glGetVertexAttribfv", "index out of range");
6495 return;
6497 switch (pname) {
6498 case GL_CURRENT_VERTEX_ATTRIB: {
6499 const Vec4& value = state_.attrib_values[index];
6500 params[0] = value.v[0];
6501 params[1] = value.v[1];
6502 params[2] = value.v[2];
6503 params[3] = value.v[3];
6504 break;
6506 default: {
6507 GLint value = 0;
6508 GetVertexAttribHelper(attrib, pname, &value);
6509 *params = static_cast<GLfloat>(value);
6510 break;
6515 void GLES2DecoderImpl::DoGetVertexAttribiv(
6516 GLuint index, GLenum pname, GLint* params) {
6517 VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(index);
6518 if (!attrib) {
6519 LOCAL_SET_GL_ERROR(
6520 GL_INVALID_VALUE, "glGetVertexAttribiv", "index out of range");
6521 return;
6523 switch (pname) {
6524 case GL_CURRENT_VERTEX_ATTRIB: {
6525 const Vec4& value = state_.attrib_values[index];
6526 params[0] = static_cast<GLint>(value.v[0]);
6527 params[1] = static_cast<GLint>(value.v[1]);
6528 params[2] = static_cast<GLint>(value.v[2]);
6529 params[3] = static_cast<GLint>(value.v[3]);
6530 break;
6532 default:
6533 GetVertexAttribHelper(attrib, pname, params);
6534 break;
6538 bool GLES2DecoderImpl::SetVertexAttribValue(
6539 const char* function_name, GLuint index, const GLfloat* value) {
6540 if (index >= state_.attrib_values.size()) {
6541 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "index out of range");
6542 return false;
6544 Vec4& v = state_.attrib_values[index];
6545 v.v[0] = value[0];
6546 v.v[1] = value[1];
6547 v.v[2] = value[2];
6548 v.v[3] = value[3];
6549 return true;
6552 void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
6553 GLfloat v[4] = { v0, 0.0f, 0.0f, 1.0f, };
6554 if (SetVertexAttribValue("glVertexAttrib1f", index, v)) {
6555 glVertexAttrib1f(index, v0);
6559 void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
6560 GLfloat v[4] = { v0, v1, 0.0f, 1.0f, };
6561 if (SetVertexAttribValue("glVertexAttrib2f", index, v)) {
6562 glVertexAttrib2f(index, v0, v1);
6566 void GLES2DecoderImpl::DoVertexAttrib3f(
6567 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
6568 GLfloat v[4] = { v0, v1, v2, 1.0f, };
6569 if (SetVertexAttribValue("glVertexAttrib3f", index, v)) {
6570 glVertexAttrib3f(index, v0, v1, v2);
6574 void GLES2DecoderImpl::DoVertexAttrib4f(
6575 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
6576 GLfloat v[4] = { v0, v1, v2, v3, };
6577 if (SetVertexAttribValue("glVertexAttrib4f", index, v)) {
6578 glVertexAttrib4f(index, v0, v1, v2, v3);
6582 void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
6583 GLfloat t[4] = { v[0], 0.0f, 0.0f, 1.0f, };
6584 if (SetVertexAttribValue("glVertexAttrib1fv", index, t)) {
6585 glVertexAttrib1fv(index, v);
6589 void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
6590 GLfloat t[4] = { v[0], v[1], 0.0f, 1.0f, };
6591 if (SetVertexAttribValue("glVertexAttrib2fv", index, t)) {
6592 glVertexAttrib2fv(index, v);
6596 void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
6597 GLfloat t[4] = { v[0], v[1], v[2], 1.0f, };
6598 if (SetVertexAttribValue("glVertexAttrib3fv", index, t)) {
6599 glVertexAttrib3fv(index, v);
6603 void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
6604 if (SetVertexAttribValue("glVertexAttrib4fv", index, v)) {
6605 glVertexAttrib4fv(index, v);
6609 error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
6610 uint32 immediate_data_size, const cmds::VertexAttribPointer& c) {
6612 if (!state_.bound_array_buffer.get() ||
6613 state_.bound_array_buffer->IsDeleted()) {
6614 if (state_.vertex_attrib_manager.get() ==
6615 default_vertex_attrib_manager_.get()) {
6616 LOCAL_SET_GL_ERROR(
6617 GL_INVALID_VALUE, "glVertexAttribPointer", "no array buffer bound");
6618 return error::kNoError;
6619 } else if (c.offset != 0) {
6620 LOCAL_SET_GL_ERROR(
6621 GL_INVALID_VALUE,
6622 "glVertexAttribPointer", "client side arrays are not allowed");
6623 return error::kNoError;
6627 GLuint indx = c.indx;
6628 GLint size = c.size;
6629 GLenum type = c.type;
6630 GLboolean normalized = c.normalized;
6631 GLsizei stride = c.stride;
6632 GLsizei offset = c.offset;
6633 const void* ptr = reinterpret_cast<const void*>(offset);
6634 if (!validators_->vertex_attrib_type.IsValid(type)) {
6635 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribPointer", type, "type");
6636 return error::kNoError;
6638 if (!validators_->vertex_attrib_size.IsValid(size)) {
6639 LOCAL_SET_GL_ERROR(
6640 GL_INVALID_VALUE, "glVertexAttribPointer", "size GL_INVALID_VALUE");
6641 return error::kNoError;
6643 if (indx >= group_->max_vertex_attribs()) {
6644 LOCAL_SET_GL_ERROR(
6645 GL_INVALID_VALUE, "glVertexAttribPointer", "index out of range");
6646 return error::kNoError;
6648 if (stride < 0) {
6649 LOCAL_SET_GL_ERROR(
6650 GL_INVALID_VALUE, "glVertexAttribPointer", "stride < 0");
6651 return error::kNoError;
6653 if (stride > 255) {
6654 LOCAL_SET_GL_ERROR(
6655 GL_INVALID_VALUE, "glVertexAttribPointer", "stride > 255");
6656 return error::kNoError;
6658 if (offset < 0) {
6659 LOCAL_SET_GL_ERROR(
6660 GL_INVALID_VALUE, "glVertexAttribPointer", "offset < 0");
6661 return error::kNoError;
6663 GLsizei component_size =
6664 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
6665 if (offset % component_size > 0) {
6666 LOCAL_SET_GL_ERROR(
6667 GL_INVALID_OPERATION,
6668 "glVertexAttribPointer", "offset not valid for type");
6669 return error::kNoError;
6671 if (stride % component_size > 0) {
6672 LOCAL_SET_GL_ERROR(
6673 GL_INVALID_OPERATION,
6674 "glVertexAttribPointer", "stride not valid for type");
6675 return error::kNoError;
6677 state_.vertex_attrib_manager
6678 ->SetAttribInfo(indx,
6679 state_.bound_array_buffer.get(),
6680 size,
6681 type,
6682 normalized,
6683 stride,
6684 stride != 0 ? stride : component_size * size,
6685 offset);
6686 if (type != GL_FIXED) {
6687 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
6689 return error::kNoError;
6692 void GLES2DecoderImpl::DoViewport(GLint x, GLint y, GLsizei width,
6693 GLsizei height) {
6694 state_.viewport_x = x;
6695 state_.viewport_y = y;
6696 state_.viewport_width = std::min(width, viewport_max_width_);
6697 state_.viewport_height = std::min(height, viewport_max_height_);
6698 glViewport(x, y, width, height);
6701 error::Error GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
6702 uint32 immediate_data_size, const cmds::VertexAttribDivisorANGLE& c) {
6703 if (!features().angle_instanced_arrays) {
6704 LOCAL_SET_GL_ERROR(
6705 GL_INVALID_OPERATION,
6706 "glVertexAttribDivisorANGLE", "function not available");
6708 GLuint index = c.index;
6709 GLuint divisor = c.divisor;
6710 if (index >= group_->max_vertex_attribs()) {
6711 LOCAL_SET_GL_ERROR(
6712 GL_INVALID_VALUE,
6713 "glVertexAttribDivisorANGLE", "index out of range");
6714 return error::kNoError;
6717 state_.vertex_attrib_manager->SetDivisor(
6718 index,
6719 divisor);
6720 glVertexAttribDivisorANGLE(index, divisor);
6721 return error::kNoError;
6724 void GLES2DecoderImpl::FinishReadPixels(
6725 const cmds::ReadPixels& c,
6726 GLuint buffer) {
6727 TRACE_EVENT0("gpu", "GLES2DecoderImpl::FinishReadPixels");
6728 GLsizei width = c.width;
6729 GLsizei height = c.height;
6730 GLenum format = c.format;
6731 GLenum type = c.type;
6732 typedef cmds::ReadPixels::Result Result;
6733 uint32 pixels_size;
6734 Result* result = NULL;
6735 if (c.result_shm_id != 0) {
6736 result = GetSharedMemoryAs<Result*>(
6737 c.result_shm_id, c.result_shm_offset, sizeof(*result));
6738 if (!result) {
6739 if (buffer != 0) {
6740 glDeleteBuffersARB(1, &buffer);
6742 return;
6745 GLES2Util::ComputeImageDataSizes(
6746 width, height, format, type, state_.pack_alignment, &pixels_size,
6747 NULL, NULL);
6748 void* pixels = GetSharedMemoryAs<void*>(
6749 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
6750 if (!pixels) {
6751 if (buffer != 0) {
6752 glDeleteBuffersARB(1, &buffer);
6754 return;
6757 if (buffer != 0) {
6758 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
6759 void* data = glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
6760 memcpy(pixels, data, pixels_size);
6761 // GL_PIXEL_PACK_BUFFER_ARB is currently unused, so we don't
6762 // have to restore the state.
6763 glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB);
6764 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
6765 glDeleteBuffersARB(1, &buffer);
6768 if (result != NULL) {
6769 *result = true;
6772 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
6773 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
6774 if ((channels_exist & 0x0008) == 0 &&
6775 workarounds().clear_alpha_in_readpixels) {
6776 // Set the alpha to 255 because some drivers are buggy in this regard.
6777 uint32 temp_size;
6779 uint32 unpadded_row_size;
6780 uint32 padded_row_size;
6781 if (!GLES2Util::ComputeImageDataSizes(
6782 width, 2, format, type, state_.pack_alignment, &temp_size,
6783 &unpadded_row_size, &padded_row_size)) {
6784 return;
6786 // NOTE: Assumes the type is GL_UNSIGNED_BYTE which was true at the time
6787 // of this implementation.
6788 if (type != GL_UNSIGNED_BYTE) {
6789 return;
6791 switch (format) {
6792 case GL_RGBA:
6793 case GL_BGRA_EXT:
6794 case GL_ALPHA: {
6795 int offset = (format == GL_ALPHA) ? 0 : 3;
6796 int step = (format == GL_ALPHA) ? 1 : 4;
6797 uint8* dst = static_cast<uint8*>(pixels) + offset;
6798 for (GLint yy = 0; yy < height; ++yy) {
6799 uint8* end = dst + unpadded_row_size;
6800 for (uint8* d = dst; d < end; d += step) {
6801 *d = 255;
6803 dst += padded_row_size;
6805 break;
6807 default:
6808 break;
6814 error::Error GLES2DecoderImpl::HandleReadPixels(
6815 uint32 immediate_data_size, const cmds::ReadPixels& c) {
6816 if (ShouldDeferReads())
6817 return error::kDeferCommandUntilLater;
6818 GLint x = c.x;
6819 GLint y = c.y;
6820 GLsizei width = c.width;
6821 GLsizei height = c.height;
6822 GLenum format = c.format;
6823 GLenum type = c.type;
6824 GLboolean async = c.async;
6825 if (width < 0 || height < 0) {
6826 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glReadPixels", "dimensions < 0");
6827 return error::kNoError;
6829 typedef cmds::ReadPixels::Result Result;
6830 uint32 pixels_size;
6831 if (!GLES2Util::ComputeImageDataSizes(
6832 width, height, format, type, state_.pack_alignment, &pixels_size,
6833 NULL, NULL)) {
6834 return error::kOutOfBounds;
6836 void* pixels = GetSharedMemoryAs<void*>(
6837 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
6838 if (!pixels) {
6839 return error::kOutOfBounds;
6841 Result* result = NULL;
6842 if (c.result_shm_id != 0) {
6843 result = GetSharedMemoryAs<Result*>(
6844 c.result_shm_id, c.result_shm_offset, sizeof(*result));
6845 if (!result) {
6846 return error::kOutOfBounds;
6850 if (!validators_->read_pixel_format.IsValid(format)) {
6851 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", format, "format");
6852 return error::kNoError;
6854 if (!validators_->pixel_type.IsValid(type)) {
6855 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", type, "type");
6856 return error::kNoError;
6858 if (width == 0 || height == 0) {
6859 return error::kNoError;
6862 // Get the size of the current fbo or backbuffer.
6863 gfx::Size max_size = GetBoundReadFrameBufferSize();
6865 int32 max_x;
6866 int32 max_y;
6867 if (!SafeAddInt32(x, width, &max_x) || !SafeAddInt32(y, height, &max_y)) {
6868 LOCAL_SET_GL_ERROR(
6869 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
6870 return error::kNoError;
6873 if (!CheckBoundFramebuffersValid("glReadPixels")) {
6874 return error::kNoError;
6877 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixel");
6879 ScopedResolvedFrameBufferBinder binder(this, false, true);
6881 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
6882 // The user requested an out of range area. Get the results 1 line
6883 // at a time.
6884 uint32 temp_size;
6885 uint32 unpadded_row_size;
6886 uint32 padded_row_size;
6887 if (!GLES2Util::ComputeImageDataSizes(
6888 width, 2, format, type, state_.pack_alignment, &temp_size,
6889 &unpadded_row_size, &padded_row_size)) {
6890 LOCAL_SET_GL_ERROR(
6891 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
6892 return error::kNoError;
6895 GLint dest_x_offset = std::max(-x, 0);
6896 uint32 dest_row_offset;
6897 if (!GLES2Util::ComputeImageDataSizes(
6898 dest_x_offset, 1, format, type, state_.pack_alignment, &dest_row_offset,
6899 NULL, NULL)) {
6900 LOCAL_SET_GL_ERROR(
6901 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
6902 return error::kNoError;
6905 // Copy each row into the larger dest rect.
6906 int8* dst = static_cast<int8*>(pixels);
6907 GLint read_x = std::max(0, x);
6908 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
6909 GLint read_width = read_end_x - read_x;
6910 for (GLint yy = 0; yy < height; ++yy) {
6911 GLint ry = y + yy;
6913 // Clear the row.
6914 memset(dst, 0, unpadded_row_size);
6916 // If the row is in range, copy it.
6917 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
6918 glReadPixels(
6919 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
6921 dst += padded_row_size;
6923 } else {
6924 if (async && features().use_async_readpixels) {
6925 GLuint buffer;
6926 glGenBuffersARB(1, &buffer);
6927 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
6928 glBufferData(GL_PIXEL_PACK_BUFFER_ARB, pixels_size, NULL, GL_STREAM_READ);
6929 GLenum error = glGetError();
6930 if (error == GL_NO_ERROR) {
6931 glReadPixels(x, y, width, height, format, type, 0);
6932 pending_readpixel_fences_.push(linked_ptr<FenceCallback>(
6933 new FenceCallback()));
6934 WaitForReadPixels(base::Bind(
6935 &GLES2DecoderImpl::FinishReadPixels,
6936 base::internal::SupportsWeakPtrBase::StaticAsWeakPtr
6937 <GLES2DecoderImpl>(this),
6938 c, buffer));
6939 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
6940 return error::kNoError;
6943 glReadPixels(x, y, width, height, format, type, pixels);
6945 GLenum error = LOCAL_PEEK_GL_ERROR("glReadPixels");
6946 if (error == GL_NO_ERROR) {
6947 if (result != NULL) {
6948 *result = true;
6950 FinishReadPixels(c, 0);
6953 return error::kNoError;
6956 error::Error GLES2DecoderImpl::HandlePixelStorei(
6957 uint32 immediate_data_size, const cmds::PixelStorei& c) {
6958 GLenum pname = c.pname;
6959 GLenum param = c.param;
6960 if (!validators_->pixel_store.IsValid(pname)) {
6961 LOCAL_SET_GL_ERROR_INVALID_ENUM("glPixelStorei", pname, "pname");
6962 return error::kNoError;
6964 switch (pname) {
6965 case GL_PACK_ALIGNMENT:
6966 case GL_UNPACK_ALIGNMENT:
6967 if (!validators_->pixel_store_alignment.IsValid(param)) {
6968 LOCAL_SET_GL_ERROR(
6969 GL_INVALID_VALUE, "glPixelStore", "param GL_INVALID_VALUE");
6970 return error::kNoError;
6972 break;
6973 case GL_UNPACK_FLIP_Y_CHROMIUM:
6974 unpack_flip_y_ = (param != 0);
6975 return error::kNoError;
6976 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
6977 unpack_premultiply_alpha_ = (param != 0);
6978 return error::kNoError;
6979 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM:
6980 unpack_unpremultiply_alpha_ = (param != 0);
6981 return error::kNoError;
6982 default:
6983 break;
6985 glPixelStorei(pname, param);
6986 switch (pname) {
6987 case GL_PACK_ALIGNMENT:
6988 state_.pack_alignment = param;
6989 break;
6990 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
6991 state_.pack_reverse_row_order = (param != 0);
6992 break;
6993 case GL_UNPACK_ALIGNMENT:
6994 state_.unpack_alignment = param;
6995 break;
6996 default:
6997 // Validation should have prevented us from getting here.
6998 NOTREACHED();
6999 break;
7001 return error::kNoError;
7004 error::Error GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
7005 uint32 immediate_data_size, const cmds::PostSubBufferCHROMIUM& c) {
7006 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
7007 if (!surface_->HasExtension("GL_CHROMIUM_post_sub_buffer")) {
7008 LOCAL_SET_GL_ERROR(
7009 GL_INVALID_OPERATION,
7010 "glPostSubBufferCHROMIUM", "command not supported by surface");
7011 return error::kNoError;
7013 if (surface_->PostSubBuffer(c.x, c.y, c.width, c.height)) {
7014 return error::kNoError;
7015 } else {
7016 LOG(ERROR) << "Context lost because PostSubBuffer failed.";
7017 return error::kLostContext;
7021 error::Error GLES2DecoderImpl::GetAttribLocationHelper(
7022 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
7023 const std::string& name_str) {
7024 if (!StringIsValidForGLES(name_str.c_str())) {
7025 LOCAL_SET_GL_ERROR(
7026 GL_INVALID_VALUE, "glGetAttribLocation", "Invalid character");
7027 return error::kNoError;
7029 Program* program = GetProgramInfoNotShader(
7030 client_id, "glGetAttribLocation");
7031 if (!program) {
7032 return error::kNoError;
7034 if (!program->IsValid()) {
7035 LOCAL_SET_GL_ERROR(
7036 GL_INVALID_OPERATION, "glGetAttribLocation", "program not linked");
7037 return error::kNoError;
7039 GLint* location = GetSharedMemoryAs<GLint*>(
7040 location_shm_id, location_shm_offset, sizeof(GLint));
7041 if (!location) {
7042 return error::kOutOfBounds;
7044 // Require the client to init this incase the context is lost and we are no
7045 // longer executing commands.
7046 if (*location != -1) {
7047 return error::kGenericError;
7049 *location = program->GetAttribLocation(name_str);
7050 return error::kNoError;
7053 error::Error GLES2DecoderImpl::HandleGetAttribLocation(
7054 uint32 immediate_data_size, const cmds::GetAttribLocation& c) {
7055 uint32 name_size = c.data_size;
7056 const char* name = GetSharedMemoryAs<const char*>(
7057 c.name_shm_id, c.name_shm_offset, name_size);
7058 if (!name) {
7059 return error::kOutOfBounds;
7061 String name_str(name, name_size);
7062 return GetAttribLocationHelper(
7063 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7066 error::Error GLES2DecoderImpl::HandleGetAttribLocationImmediate(
7067 uint32 immediate_data_size, const cmds::GetAttribLocationImmediate& c) {
7068 uint32 name_size = c.data_size;
7069 const char* name = GetImmediateDataAs<const char*>(
7070 c, name_size, immediate_data_size);
7071 if (!name) {
7072 return error::kOutOfBounds;
7074 String name_str(name, name_size);
7075 return GetAttribLocationHelper(
7076 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7079 error::Error GLES2DecoderImpl::HandleGetAttribLocationBucket(
7080 uint32 immediate_data_size, const cmds::GetAttribLocationBucket& c) {
7081 Bucket* bucket = GetBucket(c.name_bucket_id);
7082 if (!bucket) {
7083 return error::kInvalidArguments;
7085 std::string name_str;
7086 if (!bucket->GetAsString(&name_str)) {
7087 return error::kInvalidArguments;
7089 return GetAttribLocationHelper(
7090 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7093 error::Error GLES2DecoderImpl::GetUniformLocationHelper(
7094 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
7095 const std::string& name_str) {
7096 if (!StringIsValidForGLES(name_str.c_str())) {
7097 LOCAL_SET_GL_ERROR(
7098 GL_INVALID_VALUE, "glGetUniformLocation", "Invalid character");
7099 return error::kNoError;
7101 Program* program = GetProgramInfoNotShader(
7102 client_id, "glUniformLocation");
7103 if (!program) {
7104 return error::kNoError;
7106 if (!program->IsValid()) {
7107 LOCAL_SET_GL_ERROR(
7108 GL_INVALID_OPERATION, "glGetUniformLocation", "program not linked");
7109 return error::kNoError;
7111 GLint* location = GetSharedMemoryAs<GLint*>(
7112 location_shm_id, location_shm_offset, sizeof(GLint));
7113 if (!location) {
7114 return error::kOutOfBounds;
7116 // Require the client to init this incase the context is lost an we are no
7117 // longer executing commands.
7118 if (*location != -1) {
7119 return error::kGenericError;
7121 *location = program->GetUniformFakeLocation(name_str);
7122 return error::kNoError;
7125 error::Error GLES2DecoderImpl::HandleGetUniformLocation(
7126 uint32 immediate_data_size, const cmds::GetUniformLocation& c) {
7127 uint32 name_size = c.data_size;
7128 const char* name = GetSharedMemoryAs<const char*>(
7129 c.name_shm_id, c.name_shm_offset, name_size);
7130 if (!name) {
7131 return error::kOutOfBounds;
7133 String name_str(name, name_size);
7134 return GetUniformLocationHelper(
7135 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7138 error::Error GLES2DecoderImpl::HandleGetUniformLocationImmediate(
7139 uint32 immediate_data_size, const cmds::GetUniformLocationImmediate& c) {
7140 uint32 name_size = c.data_size;
7141 const char* name = GetImmediateDataAs<const char*>(
7142 c, name_size, immediate_data_size);
7143 if (!name) {
7144 return error::kOutOfBounds;
7146 String name_str(name, name_size);
7147 return GetUniformLocationHelper(
7148 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7151 error::Error GLES2DecoderImpl::HandleGetUniformLocationBucket(
7152 uint32 immediate_data_size, const cmds::GetUniformLocationBucket& c) {
7153 Bucket* bucket = GetBucket(c.name_bucket_id);
7154 if (!bucket) {
7155 return error::kInvalidArguments;
7157 std::string name_str;
7158 if (!bucket->GetAsString(&name_str)) {
7159 return error::kInvalidArguments;
7161 return GetUniformLocationHelper(
7162 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7165 error::Error GLES2DecoderImpl::HandleGetString(
7166 uint32 immediate_data_size, const cmds::GetString& c) {
7167 GLenum name = static_cast<GLenum>(c.name);
7168 if (!validators_->string_type.IsValid(name)) {
7169 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetString", name, "name");
7170 return error::kNoError;
7172 const char* gl_str = reinterpret_cast<const char*>(glGetString(name));
7173 const char* str = NULL;
7174 std::string extensions;
7175 switch (name) {
7176 case GL_VERSION:
7177 str = "OpenGL ES 2.0 Chromium";
7178 break;
7179 case GL_SHADING_LANGUAGE_VERSION:
7180 str = "OpenGL ES GLSL ES 1.0 Chromium";
7181 break;
7182 case GL_RENDERER:
7183 str = "Chromium";
7184 break;
7185 case GL_VENDOR:
7186 str = "Chromium";
7187 break;
7188 case GL_EXTENSIONS:
7190 // For WebGL contexts, strip out the OES derivatives and
7191 // EXT frag depth extensions if they have not been enabled.
7192 if (force_webgl_glsl_validation_) {
7193 extensions = feature_info_->extensions();
7194 if (!derivatives_explicitly_enabled_) {
7195 size_t offset = extensions.find(kOESDerivativeExtension);
7196 if (std::string::npos != offset) {
7197 extensions.replace(offset, arraysize(kOESDerivativeExtension),
7198 std::string());
7201 if (!frag_depth_explicitly_enabled_) {
7202 size_t offset = extensions.find(kEXTFragDepthExtension);
7203 if (std::string::npos != offset) {
7204 extensions.replace(offset, arraysize(kEXTFragDepthExtension),
7205 std::string());
7208 if (!draw_buffers_explicitly_enabled_) {
7209 size_t offset = extensions.find(kEXTDrawBuffersExtension);
7210 if (std::string::npos != offset) {
7211 extensions.replace(offset, arraysize(kEXTDrawBuffersExtension),
7212 std::string());
7215 } else {
7216 extensions = feature_info_->extensions().c_str();
7218 std::string surface_extensions = surface_->GetExtensions();
7219 if (!surface_extensions.empty())
7220 extensions += " " + surface_extensions;
7221 str = extensions.c_str();
7223 break;
7224 default:
7225 str = gl_str;
7226 break;
7228 Bucket* bucket = CreateBucket(c.bucket_id);
7229 bucket->SetFromString(str);
7230 return error::kNoError;
7233 void GLES2DecoderImpl::DoBufferData(
7234 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage) {
7235 if (!validators_->buffer_target.IsValid(target)) {
7236 LOCAL_SET_GL_ERROR_INVALID_ENUM("glBufferData", target, "target");
7237 return;
7239 if (!validators_->buffer_usage.IsValid(usage)) {
7240 LOCAL_SET_GL_ERROR_INVALID_ENUM("glBufferData", usage, "usage");
7241 return;
7243 if (size < 0) {
7244 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glBufferData", "size < 0");
7245 return;
7247 Buffer* buffer = GetBufferInfoForTarget(target);
7248 if (!buffer) {
7249 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glBufferData", "unknown buffer");
7250 return;
7253 if (!EnsureGPUMemoryAvailable(size)) {
7254 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glBufferData", "out of memory");
7255 return;
7258 buffer_manager()->DoBufferData(GetErrorState(), buffer, size, usage, data);
7261 error::Error GLES2DecoderImpl::HandleBufferData(
7262 uint32 immediate_data_size, const cmds::BufferData& c) {
7263 GLenum target = static_cast<GLenum>(c.target);
7264 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
7265 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
7266 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
7267 GLenum usage = static_cast<GLenum>(c.usage);
7268 const void* data = NULL;
7269 if (data_shm_id != 0 || data_shm_offset != 0) {
7270 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
7271 if (!data) {
7272 return error::kOutOfBounds;
7275 DoBufferData(target, size, data, usage);
7276 return error::kNoError;
7279 error::Error GLES2DecoderImpl::HandleBufferDataImmediate(
7280 uint32 immediate_data_size, const cmds::BufferDataImmediate& c) {
7281 GLenum target = static_cast<GLenum>(c.target);
7282 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
7283 const void* data = GetImmediateDataAs<const void*>(
7284 c, size, immediate_data_size);
7285 if (!data) {
7286 return error::kOutOfBounds;
7288 GLenum usage = static_cast<GLenum>(c.usage);
7289 DoBufferData(target, size, data, usage);
7290 return error::kNoError;
7293 void GLES2DecoderImpl::DoBufferSubData(
7294 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
7295 Buffer* buffer = GetBufferInfoForTarget(target);
7296 if (!buffer) {
7297 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glBufferSubData", "unknown buffer");
7298 return;
7301 buffer_manager()->DoBufferSubData(GetErrorState(), buffer, offset, size,
7302 data);
7305 bool GLES2DecoderImpl::ClearLevel(
7306 unsigned service_id,
7307 unsigned bind_target,
7308 unsigned target,
7309 int level,
7310 unsigned format,
7311 unsigned type,
7312 int width,
7313 int height,
7314 bool is_texture_immutable) {
7315 uint32 channels = GLES2Util::GetChannelsForFormat(format);
7316 if (IsAngle() && (channels & GLES2Util::kDepth) != 0) {
7317 // It's a depth format and ANGLE doesn't allow texImage2D or texSubImage2D
7318 // on depth formats.
7319 GLuint fb = 0;
7320 glGenFramebuffersEXT(1, &fb);
7321 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb);
7323 bool have_stencil = (channels & GLES2Util::kStencil) != 0;
7324 GLenum attachment = have_stencil ? GL_DEPTH_STENCIL_ATTACHMENT :
7325 GL_DEPTH_ATTACHMENT;
7327 glFramebufferTexture2DEXT(
7328 GL_DRAW_FRAMEBUFFER_EXT, attachment, target, service_id, level);
7329 // ANGLE promises a depth only attachment ok.
7330 if (glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT) !=
7331 GL_FRAMEBUFFER_COMPLETE) {
7332 return false;
7334 glClearStencil(0);
7335 glStencilMask(-1);
7336 glClearDepth(1.0f);
7337 glDepthMask(true);
7338 glDisable(GL_SCISSOR_TEST);
7339 glClear(GL_DEPTH_BUFFER_BIT | (have_stencil ? GL_STENCIL_BUFFER_BIT : 0));
7341 RestoreClearState();
7343 glDeleteFramebuffersEXT(1, &fb);
7344 Framebuffer* framebuffer =
7345 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
7346 GLuint fb_service_id =
7347 framebuffer ? framebuffer->service_id() : GetBackbufferServiceId();
7348 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb_service_id);
7349 return true;
7352 static const uint32 kMaxZeroSize = 1024 * 1024 * 4;
7354 uint32 size;
7355 uint32 padded_row_size;
7356 if (!GLES2Util::ComputeImageDataSizes(
7357 width, height, format, type, state_.unpack_alignment, &size,
7358 NULL, &padded_row_size)) {
7359 return false;
7362 TRACE_EVENT1("gpu", "GLES2DecoderImpl::ClearLevel", "size", size);
7364 int tile_height;
7366 if (size > kMaxZeroSize) {
7367 if (kMaxZeroSize < padded_row_size) {
7368 // That'd be an awfully large texture.
7369 return false;
7371 // We should never have a large total size with a zero row size.
7372 DCHECK_GT(padded_row_size, 0U);
7373 tile_height = kMaxZeroSize / padded_row_size;
7374 if (!GLES2Util::ComputeImageDataSizes(
7375 width, tile_height, format, type, state_.unpack_alignment, &size,
7376 NULL, NULL)) {
7377 return false;
7379 } else {
7380 tile_height = height;
7383 // Assumes the size has already been checked.
7384 scoped_ptr<char[]> zero(new char[size]);
7385 memset(zero.get(), 0, size);
7386 glBindTexture(bind_target, service_id);
7388 GLint y = 0;
7389 while (y < height) {
7390 GLint h = y + tile_height > height ? height - y : tile_height;
7391 if (is_texture_immutable || h != height) {
7392 glTexSubImage2D(target, level, 0, y, width, h, format, type, zero.get());
7393 } else {
7394 glTexImage2D(
7395 target, level, format, width, h, 0, format, type, zero.get());
7397 y += tile_height;
7399 TextureRef* texture = GetTextureInfoForTarget(bind_target);
7400 glBindTexture(bind_target, texture ? texture->service_id() : 0);
7401 return true;
7404 namespace {
7406 const int kS3TCBlockWidth = 4;
7407 const int kS3TCBlockHeight = 4;
7408 const int kS3TCDXT1BlockSize = 8;
7409 const int kS3TCDXT3AndDXT5BlockSize = 16;
7410 const int kETC1BlockWidth = 4;
7411 const int kETC1BlockHeight = 4;
7412 const int kETC1BlockSize = 8;
7414 bool IsValidDXTSize(GLint level, GLsizei size) {
7415 return (size == 1) ||
7416 (size == 2) || !(size % kS3TCBlockWidth);
7419 } // anonymous namespace.
7421 bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
7422 const char* function_name,
7423 GLsizei width, GLsizei height, GLenum format, size_t size) {
7424 unsigned int bytes_required = 0;
7426 switch (format) {
7427 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
7428 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: {
7429 int num_blocks_across =
7430 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
7431 int num_blocks_down =
7432 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
7433 int num_blocks = num_blocks_across * num_blocks_down;
7434 bytes_required = num_blocks * kS3TCDXT1BlockSize;
7435 break;
7437 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
7438 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
7439 int num_blocks_across =
7440 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
7441 int num_blocks_down =
7442 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
7443 int num_blocks = num_blocks_across * num_blocks_down;
7444 bytes_required = num_blocks * kS3TCDXT3AndDXT5BlockSize;
7445 break;
7447 case GL_ETC1_RGB8_OES: {
7448 int num_blocks_across =
7449 (width + kETC1BlockWidth - 1) / kETC1BlockWidth;
7450 int num_blocks_down =
7451 (height + kETC1BlockHeight - 1) / kETC1BlockHeight;
7452 int num_blocks = num_blocks_across * num_blocks_down;
7453 bytes_required = num_blocks * kETC1BlockSize;
7454 break;
7456 default:
7457 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, format, "format");
7458 return false;
7461 if (size != bytes_required) {
7462 LOCAL_SET_GL_ERROR(
7463 GL_INVALID_VALUE, function_name, "size is not correct for dimensions");
7464 return false;
7467 return true;
7470 bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
7471 const char* function_name,
7472 GLint level, GLsizei width, GLsizei height, GLenum format) {
7473 switch (format) {
7474 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
7475 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
7476 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
7477 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
7478 if (!IsValidDXTSize(level, width) || !IsValidDXTSize(level, height)) {
7479 LOCAL_SET_GL_ERROR(
7480 GL_INVALID_OPERATION, function_name,
7481 "width or height invalid for level");
7482 return false;
7484 return true;
7486 case GL_ETC1_RGB8_OES:
7487 if (width <= 0 || height <= 0) {
7488 LOCAL_SET_GL_ERROR(
7489 GL_INVALID_OPERATION, function_name,
7490 "width or height invalid for level");
7491 return false;
7493 return true;
7494 default:
7495 return false;
7499 bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
7500 const char* function_name,
7501 GLenum target, GLint level, GLint xoffset, GLint yoffset,
7502 GLsizei width, GLsizei height, GLenum format,
7503 Texture* texture) {
7504 if (xoffset < 0 || yoffset < 0) {
7505 LOCAL_SET_GL_ERROR(
7506 GL_INVALID_VALUE, function_name, "xoffset or yoffset < 0");
7507 return false;
7510 switch (format) {
7511 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
7512 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
7513 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
7514 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
7515 const int kBlockWidth = 4;
7516 const int kBlockHeight = 4;
7517 if ((xoffset % kBlockWidth) || (yoffset % kBlockHeight)) {
7518 LOCAL_SET_GL_ERROR(
7519 GL_INVALID_OPERATION, function_name,
7520 "xoffset or yoffset not multiple of 4");
7521 return false;
7523 GLsizei tex_width = 0;
7524 GLsizei tex_height = 0;
7525 if (!texture->GetLevelSize(target, level, &tex_width, &tex_height) ||
7526 width - xoffset > tex_width ||
7527 height - yoffset > tex_height) {
7528 LOCAL_SET_GL_ERROR(
7529 GL_INVALID_OPERATION, function_name, "dimensions out of range");
7530 return false;
7532 return ValidateCompressedTexDimensions(
7533 function_name, level, width, height, format);
7535 case GL_ETC1_RGB8_OES: {
7536 LOCAL_SET_GL_ERROR(
7537 GL_INVALID_OPERATION, function_name,
7538 "TexsubImage2d not supported for ECT1_RGB8_OES textures");
7539 return false;
7541 default:
7542 return false;
7546 error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
7547 GLenum target,
7548 GLint level,
7549 GLenum internal_format,
7550 GLsizei width,
7551 GLsizei height,
7552 GLint border,
7553 GLsizei image_size,
7554 const void* data) {
7555 // TODO(gman): Validate image_size is correct for width, height and format.
7556 if (!validators_->texture_target.IsValid(target)) {
7557 LOCAL_SET_GL_ERROR_INVALID_ENUM(
7558 "glCompressedTexImage2D", target, "target");
7559 return error::kNoError;
7561 if (!validators_->compressed_texture_format.IsValid(
7562 internal_format)) {
7563 LOCAL_SET_GL_ERROR_INVALID_ENUM(
7564 "glCompressedTexImage2D", internal_format, "internal_format");
7565 return error::kNoError;
7567 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
7568 border != 0) {
7569 LOCAL_SET_GL_ERROR(
7570 GL_INVALID_VALUE,
7571 "glCompressedTexImage2D", "dimensions out of range");
7572 return error::kNoError;
7574 TextureRef* texture_ref = GetTextureInfoForTarget(target);
7575 if (!texture_ref) {
7576 LOCAL_SET_GL_ERROR(
7577 GL_INVALID_VALUE,
7578 "glCompressedTexImage2D", "unknown texture target");
7579 return error::kNoError;
7581 Texture* texture = texture_ref->texture();
7582 if (texture->IsImmutable()) {
7583 LOCAL_SET_GL_ERROR(
7584 GL_INVALID_OPERATION,
7585 "glCompressedTexImage2D", "texture is immutable");
7586 return error::kNoError;
7589 if (!ValidateCompressedTexDimensions(
7590 "glCompressedTexImage2D", level, width, height, internal_format) ||
7591 !ValidateCompressedTexFuncData(
7592 "glCompressedTexImage2D", width, height, internal_format, image_size)) {
7593 return error::kNoError;
7596 if (!EnsureGPUMemoryAvailable(image_size)) {
7597 LOCAL_SET_GL_ERROR(
7598 GL_OUT_OF_MEMORY, "glCompressedTexImage2D", "out of memory");
7599 return error::kNoError;
7602 if (texture->IsAttachedToFramebuffer()) {
7603 clear_state_dirty_ = true;
7606 scoped_ptr<int8[]> zero;
7607 if (!data) {
7608 zero.reset(new int8[image_size]);
7609 memset(zero.get(), 0, image_size);
7610 data = zero.get();
7612 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage2D");
7613 glCompressedTexImage2D(
7614 target, level, internal_format, width, height, border, image_size, data);
7615 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedTexImage2D");
7616 if (error == GL_NO_ERROR) {
7617 texture_manager()->SetLevelInfo(
7618 texture_ref, target, level, internal_format,
7619 width, height, 1, border, 0, 0, true);
7621 return error::kNoError;
7624 error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
7625 uint32 immediate_data_size, const cmds::CompressedTexImage2D& c) {
7626 GLenum target = static_cast<GLenum>(c.target);
7627 GLint level = static_cast<GLint>(c.level);
7628 GLenum internal_format = static_cast<GLenum>(c.internalformat);
7629 GLsizei width = static_cast<GLsizei>(c.width);
7630 GLsizei height = static_cast<GLsizei>(c.height);
7631 GLint border = static_cast<GLint>(c.border);
7632 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
7633 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
7634 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
7635 const void* data = NULL;
7636 if (data_shm_id != 0 || data_shm_offset != 0) {
7637 data = GetSharedMemoryAs<const void*>(
7638 data_shm_id, data_shm_offset, image_size);
7639 if (!data) {
7640 return error::kOutOfBounds;
7643 return DoCompressedTexImage2D(
7644 target, level, internal_format, width, height, border, image_size, data);
7647 error::Error GLES2DecoderImpl::HandleCompressedTexImage2DImmediate(
7648 uint32 immediate_data_size, const cmds::CompressedTexImage2DImmediate& c) {
7649 GLenum target = static_cast<GLenum>(c.target);
7650 GLint level = static_cast<GLint>(c.level);
7651 GLenum internal_format = static_cast<GLenum>(c.internalformat);
7652 GLsizei width = static_cast<GLsizei>(c.width);
7653 GLsizei height = static_cast<GLsizei>(c.height);
7654 GLint border = static_cast<GLint>(c.border);
7655 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
7656 const void* data = GetImmediateDataAs<const void*>(
7657 c, image_size, immediate_data_size);
7658 if (!data) {
7659 return error::kOutOfBounds;
7661 return DoCompressedTexImage2D(
7662 target, level, internal_format, width, height, border, image_size, data);
7665 error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
7666 uint32 immediate_data_size, const cmds::CompressedTexImage2DBucket& c) {
7667 GLenum target = static_cast<GLenum>(c.target);
7668 GLint level = static_cast<GLint>(c.level);
7669 GLenum internal_format = static_cast<GLenum>(c.internalformat);
7670 GLsizei width = static_cast<GLsizei>(c.width);
7671 GLsizei height = static_cast<GLsizei>(c.height);
7672 GLint border = static_cast<GLint>(c.border);
7673 Bucket* bucket = GetBucket(c.bucket_id);
7674 if (!bucket) {
7675 return error::kInvalidArguments;
7677 uint32 data_size = bucket->size();
7678 GLsizei imageSize = data_size;
7679 const void* data = bucket->GetData(0, data_size);
7680 if (!data) {
7681 return error::kInvalidArguments;
7683 return DoCompressedTexImage2D(
7684 target, level, internal_format, width, height, border,
7685 imageSize, data);
7688 error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
7689 uint32 immediate_data_size,
7690 const cmds::CompressedTexSubImage2DBucket& c) {
7691 GLenum target = static_cast<GLenum>(c.target);
7692 GLint level = static_cast<GLint>(c.level);
7693 GLint xoffset = static_cast<GLint>(c.xoffset);
7694 GLint yoffset = static_cast<GLint>(c.yoffset);
7695 GLsizei width = static_cast<GLsizei>(c.width);
7696 GLsizei height = static_cast<GLsizei>(c.height);
7697 GLenum format = static_cast<GLenum>(c.format);
7698 Bucket* bucket = GetBucket(c.bucket_id);
7699 if (!bucket) {
7700 return error::kInvalidArguments;
7702 uint32 data_size = bucket->size();
7703 GLsizei imageSize = data_size;
7704 const void* data = bucket->GetData(0, data_size);
7705 if (!data) {
7706 return error::kInvalidArguments;
7708 if (!validators_->texture_target.IsValid(target)) {
7709 LOCAL_SET_GL_ERROR(
7710 GL_INVALID_ENUM, "glCompressedTexSubImage2D", "target");
7711 return error::kNoError;
7713 if (!validators_->compressed_texture_format.IsValid(format)) {
7714 LOCAL_SET_GL_ERROR_INVALID_ENUM(
7715 "glCompressedTexSubImage2D", format, "format");
7716 return error::kNoError;
7718 if (width < 0) {
7719 LOCAL_SET_GL_ERROR(
7720 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "width < 0");
7721 return error::kNoError;
7723 if (height < 0) {
7724 LOCAL_SET_GL_ERROR(
7725 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "height < 0");
7726 return error::kNoError;
7728 if (imageSize < 0) {
7729 LOCAL_SET_GL_ERROR(
7730 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "imageSize < 0");
7731 return error::kNoError;
7733 DoCompressedTexSubImage2D(
7734 target, level, xoffset, yoffset, width, height, format, imageSize, data);
7735 return error::kNoError;
7738 bool GLES2DecoderImpl::ValidateTextureParameters(
7739 const char* function_name,
7740 GLenum target, GLenum format, GLenum type, GLint level) {
7741 if (!feature_info_->GetTextureFormatValidator(format).IsValid(type)) {
7742 LOCAL_SET_GL_ERROR(
7743 GL_INVALID_OPERATION, function_name,
7744 (std::string("invalid type ") +
7745 GLES2Util::GetStringEnum(type) + " for format " +
7746 GLES2Util::GetStringEnum(format)).c_str());
7747 return false;
7750 uint32 channels = GLES2Util::GetChannelsForFormat(format);
7751 if ((channels & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0 && level) {
7752 LOCAL_SET_GL_ERROR(
7753 GL_INVALID_OPERATION, function_name,
7754 (std::string("invalid type ") +
7755 GLES2Util::GetStringEnum(type) + " for format " +
7756 GLES2Util::GetStringEnum(format)).c_str());
7757 return false;
7759 return true;
7762 bool GLES2DecoderImpl::ValidateTexImage2D(
7763 const char* function_name,
7764 GLenum target,
7765 GLint level,
7766 GLenum internal_format,
7767 GLsizei width,
7768 GLsizei height,
7769 GLint border,
7770 GLenum format,
7771 GLenum type,
7772 const void* pixels,
7773 uint32 pixels_size) {
7774 if (!validators_->texture_target.IsValid(target)) {
7775 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
7776 return false;
7778 if (!validators_->texture_format.IsValid(internal_format)) {
7779 LOCAL_SET_GL_ERROR_INVALID_ENUM(
7780 function_name, internal_format, "internal_format");
7781 return false;
7783 if (!validators_->texture_format.IsValid(format)) {
7784 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, format, "format");
7785 return false;
7787 if (!validators_->pixel_type.IsValid(type)) {
7788 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, type, "type");
7789 return false;
7791 if (format != internal_format) {
7792 LOCAL_SET_GL_ERROR(
7793 GL_INVALID_OPERATION, function_name, "format != internalFormat");
7794 return false;
7796 if (!ValidateTextureParameters(function_name, target, format, type, level)) {
7797 return false;
7799 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
7800 border != 0) {
7801 LOCAL_SET_GL_ERROR(
7802 GL_INVALID_VALUE, function_name, "dimensions out of range");
7803 return false;
7805 if ((GLES2Util::GetChannelsForFormat(format) &
7806 (GLES2Util::kDepth | GLES2Util::kStencil)) != 0 && pixels) {
7807 LOCAL_SET_GL_ERROR(
7808 GL_INVALID_OPERATION,
7809 function_name, "can not supply data for depth or stencil textures");
7810 return false;
7812 TextureRef* texture_ref = GetTextureInfoForTarget(target);
7813 if (!texture_ref) {
7814 LOCAL_SET_GL_ERROR(
7815 GL_INVALID_OPERATION, function_name, "unknown texture for target");
7816 return false;
7818 if (texture_ref->texture()->IsImmutable()) {
7819 LOCAL_SET_GL_ERROR(
7820 GL_INVALID_OPERATION, function_name, "texture is immutable");
7821 return false;
7823 return true;
7826 void GLES2DecoderImpl::DoTexImage2D(
7827 GLenum target,
7828 GLint level,
7829 GLenum internal_format,
7830 GLsizei width,
7831 GLsizei height,
7832 GLint border,
7833 GLenum format,
7834 GLenum type,
7835 const void* pixels,
7836 uint32 pixels_size) {
7837 if (!ValidateTexImage2D("glTexImage2D", target, level, internal_format,
7838 width, height, border, format, type, pixels, pixels_size)) {
7839 return;
7842 if (!EnsureGPUMemoryAvailable(pixels_size)) {
7843 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glTexImage2D", "out of memory");
7844 return;
7847 TextureRef* texture_ref = GetTextureInfoForTarget(target);
7848 Texture* texture = texture_ref->texture();
7849 GLsizei tex_width = 0;
7850 GLsizei tex_height = 0;
7851 GLenum tex_type = 0;
7852 GLenum tex_format = 0;
7853 bool level_is_same =
7854 texture->GetLevelSize(target, level, &tex_width, &tex_height) &&
7855 texture->GetLevelType(target, level, &tex_type, &tex_format) &&
7856 width == tex_width && height == tex_height &&
7857 type == tex_type && format == tex_format;
7859 if (level_is_same && !pixels) {
7860 // Just set the level texture but mark the texture as uncleared.
7861 texture_manager()->SetLevelInfo(
7862 texture_ref,
7863 target, level, internal_format, width, height, 1, border, format, type,
7864 false);
7865 tex_image_2d_failed_ = false;
7866 return;
7869 if (texture->IsAttachedToFramebuffer()) {
7870 clear_state_dirty_ = true;
7873 if (!teximage2d_faster_than_texsubimage2d_ && level_is_same && pixels) {
7875 ScopedTextureUploadTimer timer(this);
7876 glTexSubImage2D(target, level, 0, 0, width, height, format, type, pixels);
7878 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
7879 tex_image_2d_failed_ = false;
7880 return;
7883 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexImage2D");
7885 ScopedTextureUploadTimer timer(this);
7886 glTexImage2D(
7887 target, level, internal_format, width, height, border, format, type,
7888 pixels);
7890 GLenum error = LOCAL_PEEK_GL_ERROR("glTexImage2D");
7891 if (error == GL_NO_ERROR) {
7892 texture_manager()->SetLevelInfo(
7893 texture_ref,
7894 target, level, internal_format, width, height, 1, border, format, type,
7895 pixels != NULL);
7896 tex_image_2d_failed_ = false;
7898 return;
7901 error::Error GLES2DecoderImpl::HandleTexImage2D(
7902 uint32 immediate_data_size, const cmds::TexImage2D& c) {
7903 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexImage2D");
7904 tex_image_2d_failed_ = true;
7905 GLenum target = static_cast<GLenum>(c.target);
7906 GLint level = static_cast<GLint>(c.level);
7907 GLint internal_format = static_cast<GLint>(c.internalformat);
7908 GLsizei width = static_cast<GLsizei>(c.width);
7909 GLsizei height = static_cast<GLsizei>(c.height);
7910 GLint border = static_cast<GLint>(c.border);
7911 GLenum format = static_cast<GLenum>(c.format);
7912 GLenum type = static_cast<GLenum>(c.type);
7913 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
7914 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
7915 uint32 pixels_size;
7916 if (!GLES2Util::ComputeImageDataSizes(
7917 width, height, format, type, state_.unpack_alignment, &pixels_size, NULL,
7918 NULL)) {
7919 return error::kOutOfBounds;
7921 const void* pixels = NULL;
7922 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
7923 pixels = GetSharedMemoryAs<const void*>(
7924 pixels_shm_id, pixels_shm_offset, pixels_size);
7925 if (!pixels) {
7926 return error::kOutOfBounds;
7930 DoTexImage2D(
7931 target, level, internal_format, width, height, border, format, type,
7932 pixels, pixels_size);
7933 return error::kNoError;
7936 error::Error GLES2DecoderImpl::HandleTexImage2DImmediate(
7937 uint32 immediate_data_size, const cmds::TexImage2DImmediate& c) {
7938 GLenum target = static_cast<GLenum>(c.target);
7939 GLint level = static_cast<GLint>(c.level);
7940 GLint internal_format = static_cast<GLint>(c.internalformat);
7941 GLsizei width = static_cast<GLsizei>(c.width);
7942 GLsizei height = static_cast<GLsizei>(c.height);
7943 GLint border = static_cast<GLint>(c.border);
7944 GLenum format = static_cast<GLenum>(c.format);
7945 GLenum type = static_cast<GLenum>(c.type);
7946 uint32 size;
7947 if (!GLES2Util::ComputeImageDataSizes(
7948 width, height, format, type, state_.unpack_alignment, &size,
7949 NULL, NULL)) {
7950 return error::kOutOfBounds;
7952 const void* pixels = GetImmediateDataAs<const void*>(
7953 c, size, immediate_data_size);
7954 if (!pixels) {
7955 return error::kOutOfBounds;
7957 DoTexImage2D(
7958 target, level, internal_format, width, height, border, format, type,
7959 pixels, size);
7960 return error::kNoError;
7963 void GLES2DecoderImpl::DoCompressedTexSubImage2D(
7964 GLenum target,
7965 GLint level,
7966 GLint xoffset,
7967 GLint yoffset,
7968 GLsizei width,
7969 GLsizei height,
7970 GLenum format,
7971 GLsizei image_size,
7972 const void * data) {
7973 TextureRef* texture_ref = GetTextureInfoForTarget(target);
7974 if (!texture_ref) {
7975 LOCAL_SET_GL_ERROR(
7976 GL_INVALID_OPERATION,
7977 "glCompressedTexSubImage2D", "unknown texture for target");
7978 return;
7980 Texture* texture = texture_ref->texture();
7981 GLenum type = 0;
7982 GLenum internal_format = 0;
7983 if (!texture->GetLevelType(target, level, &type, &internal_format)) {
7984 LOCAL_SET_GL_ERROR(
7985 GL_INVALID_OPERATION,
7986 "glCompressedTexSubImage2D", "level does not exist.");
7987 return;
7989 if (internal_format != format) {
7990 LOCAL_SET_GL_ERROR(
7991 GL_INVALID_OPERATION,
7992 "glCompressedTexSubImage2D", "format does not match internal format.");
7993 return;
7995 if (!texture->ValidForTexture(
7996 target, level, xoffset, yoffset, width, height, format, type)) {
7997 LOCAL_SET_GL_ERROR(
7998 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "bad dimensions.");
7999 return;
8002 if (!ValidateCompressedTexFuncData(
8003 "glCompressedTexSubImage2D", width, height, format, image_size) ||
8004 !ValidateCompressedTexSubDimensions(
8005 "glCompressedTexSubImage2D",
8006 target, level, xoffset, yoffset, width, height, format, texture)) {
8007 return;
8011 // Note: There is no need to deal with texture cleared tracking here
8012 // because the validation above means you can only get here if the level
8013 // is already a matching compressed format and in that case
8014 // CompressedTexImage2D already cleared the texture.
8015 glCompressedTexSubImage2D(
8016 target, level, xoffset, yoffset, width, height, format, image_size, data);
8019 static void Clip(
8020 GLint start, GLint range, GLint sourceRange,
8021 GLint* out_start, GLint* out_range) {
8022 DCHECK(out_start);
8023 DCHECK(out_range);
8024 if (start < 0) {
8025 range += start;
8026 start = 0;
8028 GLint end = start + range;
8029 if (end > sourceRange) {
8030 range -= end - sourceRange;
8032 *out_start = start;
8033 *out_range = range;
8036 void GLES2DecoderImpl::DoCopyTexImage2D(
8037 GLenum target,
8038 GLint level,
8039 GLenum internal_format,
8040 GLint x,
8041 GLint y,
8042 GLsizei width,
8043 GLsizei height,
8044 GLint border) {
8045 DCHECK(!ShouldDeferReads());
8046 TextureRef* texture_ref = GetTextureInfoForTarget(target);
8047 if (!texture_ref) {
8048 LOCAL_SET_GL_ERROR(
8049 GL_INVALID_OPERATION,
8050 "glCopyTexImage2D", "unknown texture for target");
8051 return;
8053 Texture* texture = texture_ref->texture();
8054 if (texture->IsImmutable()) {
8055 LOCAL_SET_GL_ERROR(
8056 GL_INVALID_OPERATION, "glCopyTexImage2D", "texture is immutable");
8058 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
8059 border != 0) {
8060 LOCAL_SET_GL_ERROR(
8061 GL_INVALID_VALUE, "glCopyTexImage2D", "dimensions out of range");
8062 return;
8064 if (!ValidateTextureParameters(
8065 "glCopyTexImage2D", target, internal_format, GL_UNSIGNED_BYTE, level)) {
8066 return;
8069 // Check we have compatible formats.
8070 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
8071 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
8072 uint32 channels_needed = GLES2Util::GetChannelsForFormat(internal_format);
8074 if ((channels_needed & channels_exist) != channels_needed) {
8075 LOCAL_SET_GL_ERROR(
8076 GL_INVALID_OPERATION, "glCopyTexImage2D", "incompatible format");
8077 return;
8080 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
8081 LOCAL_SET_GL_ERROR(
8082 GL_INVALID_OPERATION,
8083 "glCopyTexImage2D", "can not be used with depth or stencil textures");
8084 return;
8087 uint32 estimated_size = 0;
8088 if (!GLES2Util::ComputeImageDataSizes(
8089 width, height, internal_format, GL_UNSIGNED_BYTE, state_.unpack_alignment,
8090 &estimated_size, NULL, NULL)) {
8091 LOCAL_SET_GL_ERROR(
8092 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too large");
8093 return;
8096 if (!EnsureGPUMemoryAvailable(estimated_size)) {
8097 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexImage2D", "out of memory");
8098 return;
8101 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
8102 return;
8105 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTexImage2D");
8106 ScopedResolvedFrameBufferBinder binder(this, false, true);
8107 gfx::Size size = GetBoundReadFrameBufferSize();
8109 if (texture->IsAttachedToFramebuffer()) {
8110 clear_state_dirty_ = true;
8113 // Clip to size to source dimensions
8114 GLint copyX = 0;
8115 GLint copyY = 0;
8116 GLint copyWidth = 0;
8117 GLint copyHeight = 0;
8118 Clip(x, width, size.width(), &copyX, &copyWidth);
8119 Clip(y, height, size.height(), &copyY, &copyHeight);
8121 if (copyX != x ||
8122 copyY != y ||
8123 copyWidth != width ||
8124 copyHeight != height) {
8125 // some part was clipped so clear the texture.
8126 if (!ClearLevel(
8127 texture->service_id(), texture->target(),
8128 target, level, internal_format, GL_UNSIGNED_BYTE, width, height,
8129 texture->IsImmutable())) {
8130 LOCAL_SET_GL_ERROR(
8131 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too big");
8132 return;
8134 if (copyHeight > 0 && copyWidth > 0) {
8135 GLint dx = copyX - x;
8136 GLint dy = copyY - y;
8137 GLint destX = dx;
8138 GLint destY = dy;
8139 glCopyTexSubImage2D(target, level,
8140 destX, destY, copyX, copyY,
8141 copyWidth, copyHeight);
8143 } else {
8144 glCopyTexImage2D(target, level, internal_format,
8145 copyX, copyY, copyWidth, copyHeight, border);
8147 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTexImage2D");
8148 if (error == GL_NO_ERROR) {
8149 texture_manager()->SetLevelInfo(
8150 texture_ref, target, level, internal_format, width, height, 1,
8151 border, internal_format, GL_UNSIGNED_BYTE, true);
8155 void GLES2DecoderImpl::DoCopyTexSubImage2D(
8156 GLenum target,
8157 GLint level,
8158 GLint xoffset,
8159 GLint yoffset,
8160 GLint x,
8161 GLint y,
8162 GLsizei width,
8163 GLsizei height) {
8164 DCHECK(!ShouldDeferReads());
8165 TextureRef* texture_ref = GetTextureInfoForTarget(target);
8166 if (!texture_ref) {
8167 LOCAL_SET_GL_ERROR(
8168 GL_INVALID_OPERATION,
8169 "glCopyTexSubImage2D", "unknown texture for target");
8170 return;
8172 Texture* texture = texture_ref->texture();
8173 GLenum type = 0;
8174 GLenum format = 0;
8175 if (!texture->GetLevelType(target, level, &type, &format) ||
8176 !texture->ValidForTexture(
8177 target, level, xoffset, yoffset, width, height, format, type)) {
8178 LOCAL_SET_GL_ERROR(
8179 GL_INVALID_VALUE, "glCopyTexSubImage2D", "bad dimensions.");
8180 return;
8182 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
8183 LOCAL_SET_GL_ERROR(
8184 GL_INVALID_OPERATION,
8185 "glCopyTexSubImage2D", "async upload pending for texture");
8186 return;
8189 // Check we have compatible formats.
8190 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
8191 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
8192 uint32 channels_needed = GLES2Util::GetChannelsForFormat(format);
8194 if (!channels_needed ||
8195 (channels_needed & channels_exist) != channels_needed) {
8196 LOCAL_SET_GL_ERROR(
8197 GL_INVALID_OPERATION, "glCopyTexSubImage2D", "incompatible format");
8198 return;
8201 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
8202 LOCAL_SET_GL_ERROR(
8203 GL_INVALID_OPERATION,
8204 "glCopySubImage2D", "can not be used with depth or stencil textures");
8205 return;
8208 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
8209 return;
8212 ScopedResolvedFrameBufferBinder binder(this, false, true);
8213 gfx::Size size = GetBoundReadFrameBufferSize();
8214 GLint copyX = 0;
8215 GLint copyY = 0;
8216 GLint copyWidth = 0;
8217 GLint copyHeight = 0;
8218 Clip(x, width, size.width(), &copyX, &copyWidth);
8219 Clip(y, height, size.height(), &copyY, &copyHeight);
8221 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, level)) {
8222 LOCAL_SET_GL_ERROR(
8223 GL_OUT_OF_MEMORY, "glCopyTexSubImage2D", "dimensions too big");
8224 return;
8227 if (copyX != x ||
8228 copyY != y ||
8229 copyWidth != width ||
8230 copyHeight != height) {
8231 // some part was clipped so clear the sub rect.
8232 uint32 pixels_size = 0;
8233 if (!GLES2Util::ComputeImageDataSizes(
8234 width, height, format, type, state_.unpack_alignment, &pixels_size,
8235 NULL, NULL)) {
8236 LOCAL_SET_GL_ERROR(
8237 GL_INVALID_VALUE, "glCopyTexSubImage2D", "dimensions too large");
8238 return;
8240 scoped_ptr<char[]> zero(new char[pixels_size]);
8241 memset(zero.get(), 0, pixels_size);
8242 glTexSubImage2D(
8243 target, level, xoffset, yoffset, width, height,
8244 format, type, zero.get());
8247 if (copyHeight > 0 && copyWidth > 0) {
8248 GLint dx = copyX - x;
8249 GLint dy = copyY - y;
8250 GLint destX = xoffset + dx;
8251 GLint destY = yoffset + dy;
8252 glCopyTexSubImage2D(target, level,
8253 destX, destY, copyX, copyY,
8254 copyWidth, copyHeight);
8258 bool GLES2DecoderImpl::ValidateTexSubImage2D(
8259 error::Error* error,
8260 const char* function_name,
8261 GLenum target,
8262 GLint level,
8263 GLint xoffset,
8264 GLint yoffset,
8265 GLsizei width,
8266 GLsizei height,
8267 GLenum format,
8268 GLenum type,
8269 const void * data) {
8270 (*error) = error::kNoError;
8271 if (!validators_->texture_target.IsValid(target)) {
8272 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
8273 return false;
8275 if (width < 0) {
8276 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "width < 0");
8277 return false;
8279 if (height < 0) {
8280 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "height < 0");
8281 return false;
8283 if (!validators_->texture_format.IsValid(format)) {
8284 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, format, "format");
8285 return false;
8287 if (!validators_->pixel_type.IsValid(type)) {
8288 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, type, "type");
8289 return false;
8291 TextureRef* texture_ref = GetTextureInfoForTarget(target);
8292 if (!texture_ref) {
8293 LOCAL_SET_GL_ERROR(
8294 GL_INVALID_OPERATION,
8295 function_name, "unknown texture for target");
8296 return false;
8298 Texture* texture = texture_ref->texture();
8299 GLenum current_type = 0;
8300 GLenum internal_format = 0;
8301 if (!texture->GetLevelType(target, level, &current_type, &internal_format)) {
8302 LOCAL_SET_GL_ERROR(
8303 GL_INVALID_OPERATION, function_name, "level does not exist.");
8304 return false;
8306 if (format != internal_format) {
8307 LOCAL_SET_GL_ERROR(
8308 GL_INVALID_OPERATION,
8309 function_name, "format does not match internal format.");
8310 return false;
8312 if (type != current_type) {
8313 LOCAL_SET_GL_ERROR(
8314 GL_INVALID_OPERATION,
8315 function_name, "type does not match type of texture.");
8316 return false;
8318 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
8319 LOCAL_SET_GL_ERROR(
8320 GL_INVALID_OPERATION,
8321 function_name, "async upload pending for texture");
8322 return false;
8324 if (!texture->ValidForTexture(
8325 target, level, xoffset, yoffset, width, height, format, type)) {
8326 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "bad dimensions.");
8327 return false;
8329 if ((GLES2Util::GetChannelsForFormat(format) &
8330 (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
8331 LOCAL_SET_GL_ERROR(
8332 GL_INVALID_OPERATION,
8333 function_name, "can not supply data for depth or stencil textures");
8334 return false;
8336 if (data == NULL) {
8337 (*error) = error::kOutOfBounds;
8338 return false;
8340 return true;
8343 error::Error GLES2DecoderImpl::DoTexSubImage2D(
8344 GLenum target,
8345 GLint level,
8346 GLint xoffset,
8347 GLint yoffset,
8348 GLsizei width,
8349 GLsizei height,
8350 GLenum format,
8351 GLenum type,
8352 const void * data) {
8353 error::Error error = error::kNoError;
8354 if (!ValidateTexSubImage2D(&error, "glTexSubImage2D", target, level,
8355 xoffset, yoffset, width, height, format, type, data)) {
8356 return error;
8358 TextureRef* texture_ref = GetTextureInfoForTarget(target);
8359 Texture* texture = texture_ref->texture();
8360 GLsizei tex_width = 0;
8361 GLsizei tex_height = 0;
8362 bool ok = texture->GetLevelSize(target, level, &tex_width, &tex_height);
8363 DCHECK(ok);
8364 if (xoffset != 0 || yoffset != 0 ||
8365 width != tex_width || height != tex_height) {
8366 if (!texture_manager()->ClearTextureLevel(this, texture_ref,
8367 target, level)) {
8368 LOCAL_SET_GL_ERROR(
8369 GL_OUT_OF_MEMORY, "glTexSubImage2D", "dimensions too big");
8370 return error::kNoError;
8372 ScopedTextureUploadTimer timer(this);
8373 glTexSubImage2D(
8374 target, level, xoffset, yoffset, width, height, format, type, data);
8375 return error::kNoError;
8378 if (teximage2d_faster_than_texsubimage2d_ && !texture->IsImmutable()) {
8379 ScopedTextureUploadTimer timer(this);
8380 // NOTE: In OpenGL ES 2.0 border is always zero and format is always the
8381 // same as internal_foramt. If that changes we'll need to look them up.
8382 glTexImage2D(
8383 target, level, format, width, height, 0, format, type, data);
8384 } else {
8385 ScopedTextureUploadTimer timer(this);
8386 glTexSubImage2D(
8387 target, level, xoffset, yoffset, width, height, format, type, data);
8389 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
8390 return error::kNoError;
8393 error::Error GLES2DecoderImpl::HandleTexSubImage2D(
8394 uint32 immediate_data_size, const cmds::TexSubImage2D& c) {
8395 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexSubImage2D");
8396 GLboolean internal = static_cast<GLboolean>(c.internal);
8397 if (internal == GL_TRUE && tex_image_2d_failed_)
8398 return error::kNoError;
8400 GLenum target = static_cast<GLenum>(c.target);
8401 GLint level = static_cast<GLint>(c.level);
8402 GLint xoffset = static_cast<GLint>(c.xoffset);
8403 GLint yoffset = static_cast<GLint>(c.yoffset);
8404 GLsizei width = static_cast<GLsizei>(c.width);
8405 GLsizei height = static_cast<GLsizei>(c.height);
8406 GLenum format = static_cast<GLenum>(c.format);
8407 GLenum type = static_cast<GLenum>(c.type);
8408 uint32 data_size;
8409 if (!GLES2Util::ComputeImageDataSizes(
8410 width, height, format, type, state_.unpack_alignment, &data_size,
8411 NULL, NULL)) {
8412 return error::kOutOfBounds;
8414 const void* pixels = GetSharedMemoryAs<const void*>(
8415 c.pixels_shm_id, c.pixels_shm_offset, data_size);
8416 return DoTexSubImage2D(
8417 target, level, xoffset, yoffset, width, height, format, type, pixels);
8420 error::Error GLES2DecoderImpl::HandleTexSubImage2DImmediate(
8421 uint32 immediate_data_size, const cmds::TexSubImage2DImmediate& c) {
8422 GLboolean internal = static_cast<GLboolean>(c.internal);
8423 if (internal == GL_TRUE && tex_image_2d_failed_)
8424 return error::kNoError;
8426 GLenum target = static_cast<GLenum>(c.target);
8427 GLint level = static_cast<GLint>(c.level);
8428 GLint xoffset = static_cast<GLint>(c.xoffset);
8429 GLint yoffset = static_cast<GLint>(c.yoffset);
8430 GLsizei width = static_cast<GLsizei>(c.width);
8431 GLsizei height = static_cast<GLsizei>(c.height);
8432 GLenum format = static_cast<GLenum>(c.format);
8433 GLenum type = static_cast<GLenum>(c.type);
8434 uint32 data_size;
8435 if (!GLES2Util::ComputeImageDataSizes(
8436 width, height, format, type, state_.unpack_alignment, &data_size,
8437 NULL, NULL)) {
8438 return error::kOutOfBounds;
8440 const void* pixels = GetImmediateDataAs<const void*>(
8441 c, data_size, immediate_data_size);
8442 return DoTexSubImage2D(
8443 target, level, xoffset, yoffset, width, height, format, type, pixels);
8446 error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
8447 uint32 immediate_data_size, const cmds::GetVertexAttribPointerv& c) {
8448 GLuint index = static_cast<GLuint>(c.index);
8449 GLenum pname = static_cast<GLenum>(c.pname);
8450 typedef cmds::GetVertexAttribPointerv::Result Result;
8451 Result* result = GetSharedMemoryAs<Result*>(
8452 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
8453 if (!result) {
8454 return error::kOutOfBounds;
8456 // Check that the client initialized the result.
8457 if (result->size != 0) {
8458 return error::kInvalidArguments;
8460 if (!validators_->vertex_pointer.IsValid(pname)) {
8461 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8462 "glGetVertexAttribPointerv", pname, "pname");
8463 return error::kNoError;
8465 if (index >= group_->max_vertex_attribs()) {
8466 LOCAL_SET_GL_ERROR(
8467 GL_INVALID_VALUE, "glGetVertexAttribPointerv", "index out of range.");
8468 return error::kNoError;
8470 result->SetNumResults(1);
8471 *result->GetData() =
8472 state_.vertex_attrib_manager->GetVertexAttrib(index)->offset();
8473 return error::kNoError;
8476 bool GLES2DecoderImpl::GetUniformSetup(
8477 GLuint program_id, GLint fake_location,
8478 uint32 shm_id, uint32 shm_offset,
8479 error::Error* error, GLint* real_location,
8480 GLuint* service_id, void** result_pointer, GLenum* result_type) {
8481 DCHECK(error);
8482 DCHECK(service_id);
8483 DCHECK(result_pointer);
8484 DCHECK(result_type);
8485 DCHECK(real_location);
8486 *error = error::kNoError;
8487 // Make sure we have enough room for the result on failure.
8488 SizedResult<GLint>* result;
8489 result = GetSharedMemoryAs<SizedResult<GLint>*>(
8490 shm_id, shm_offset, SizedResult<GLint>::ComputeSize(0));
8491 if (!result) {
8492 *error = error::kOutOfBounds;
8493 return false;
8495 *result_pointer = result;
8496 // Set the result size to 0 so the client does not have to check for success.
8497 result->SetNumResults(0);
8498 Program* program = GetProgramInfoNotShader(program_id, "glGetUniform");
8499 if (!program) {
8500 return false;
8502 if (!program->IsValid()) {
8503 // Program was not linked successfully. (ie, glLinkProgram)
8504 LOCAL_SET_GL_ERROR(
8505 GL_INVALID_OPERATION, "glGetUniform", "program not linked");
8506 return false;
8508 *service_id = program->service_id();
8509 GLint array_index = -1;
8510 const Program::UniformInfo* uniform_info =
8511 program->GetUniformInfoByFakeLocation(
8512 fake_location, real_location, &array_index);
8513 if (!uniform_info) {
8514 // No such location.
8515 LOCAL_SET_GL_ERROR(
8516 GL_INVALID_OPERATION, "glGetUniform", "unknown location");
8517 return false;
8519 GLenum type = uniform_info->type;
8520 GLsizei size = GLES2Util::GetGLDataTypeSizeForUniforms(type);
8521 if (size == 0) {
8522 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glGetUniform", "unknown type");
8523 return false;
8525 result = GetSharedMemoryAs<SizedResult<GLint>*>(
8526 shm_id, shm_offset, SizedResult<GLint>::ComputeSizeFromBytes(size));
8527 if (!result) {
8528 *error = error::kOutOfBounds;
8529 return false;
8531 result->size = size;
8532 *result_type = type;
8533 return true;
8536 error::Error GLES2DecoderImpl::HandleGetUniformiv(
8537 uint32 immediate_data_size, const cmds::GetUniformiv& c) {
8538 GLuint program = c.program;
8539 GLint fake_location = c.location;
8540 GLuint service_id;
8541 GLenum result_type;
8542 GLint real_location = -1;
8543 Error error;
8544 void* result;
8545 if (GetUniformSetup(
8546 program, fake_location, c.params_shm_id, c.params_shm_offset,
8547 &error, &real_location, &service_id, &result, &result_type)) {
8548 glGetUniformiv(
8549 service_id, real_location,
8550 static_cast<cmds::GetUniformiv::Result*>(result)->GetData());
8552 return error;
8555 error::Error GLES2DecoderImpl::HandleGetUniformfv(
8556 uint32 immediate_data_size, const cmds::GetUniformfv& c) {
8557 GLuint program = c.program;
8558 GLint fake_location = c.location;
8559 GLuint service_id;
8560 GLint real_location = -1;
8561 Error error;
8562 typedef cmds::GetUniformfv::Result Result;
8563 Result* result;
8564 GLenum result_type;
8565 if (GetUniformSetup(
8566 program, fake_location, c.params_shm_id, c.params_shm_offset,
8567 &error, &real_location, &service_id,
8568 reinterpret_cast<void**>(&result), &result_type)) {
8569 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
8570 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
8571 GLsizei num_values = result->GetNumResults();
8572 scoped_ptr<GLint[]> temp(new GLint[num_values]);
8573 glGetUniformiv(service_id, real_location, temp.get());
8574 GLfloat* dst = result->GetData();
8575 for (GLsizei ii = 0; ii < num_values; ++ii) {
8576 dst[ii] = (temp[ii] != 0);
8578 } else {
8579 glGetUniformfv(service_id, real_location, result->GetData());
8582 return error;
8585 error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
8586 uint32 immediate_data_size, const cmds::GetShaderPrecisionFormat& c) {
8587 GLenum shader_type = static_cast<GLenum>(c.shadertype);
8588 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
8589 typedef cmds::GetShaderPrecisionFormat::Result Result;
8590 Result* result = GetSharedMemoryAs<Result*>(
8591 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8592 if (!result) {
8593 return error::kOutOfBounds;
8595 // Check that the client initialized the result.
8596 if (result->success != 0) {
8597 return error::kInvalidArguments;
8599 if (!validators_->shader_type.IsValid(shader_type)) {
8600 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8601 "glGetShaderPrecisionFormat", shader_type, "shader_type");
8602 return error::kNoError;
8604 if (!validators_->shader_precision.IsValid(precision_type)) {
8605 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8606 "glGetShaderPrecisionFormat", precision_type, "precision_type");
8607 return error::kNoError;
8610 result->success = 1; // true
8612 GLint range[2] = { 0, 0 };
8613 GLint precision = 0;
8614 GetShaderPrecisionFormatImpl(shader_type, precision_type, range, &precision);
8616 result->min_range = range[0];
8617 result->max_range = range[1];
8618 result->precision = precision;
8620 return error::kNoError;
8623 error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
8624 uint32 immediate_data_size, const cmds::GetAttachedShaders& c) {
8625 uint32 result_size = c.result_size;
8626 GLuint program_id = static_cast<GLuint>(c.program);
8627 Program* program = GetProgramInfoNotShader(
8628 program_id, "glGetAttachedShaders");
8629 if (!program) {
8630 return error::kNoError;
8632 typedef cmds::GetAttachedShaders::Result Result;
8633 uint32 max_count = Result::ComputeMaxResults(result_size);
8634 Result* result = GetSharedMemoryAs<Result*>(
8635 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
8636 if (!result) {
8637 return error::kOutOfBounds;
8639 // Check that the client initialized the result.
8640 if (result->size != 0) {
8641 return error::kInvalidArguments;
8643 GLsizei count = 0;
8644 glGetAttachedShaders(
8645 program->service_id(), max_count, &count, result->GetData());
8646 for (GLsizei ii = 0; ii < count; ++ii) {
8647 if (!shader_manager()->GetClientId(result->GetData()[ii],
8648 &result->GetData()[ii])) {
8649 NOTREACHED();
8650 return error::kGenericError;
8653 result->SetNumResults(count);
8654 return error::kNoError;
8657 error::Error GLES2DecoderImpl::HandleGetActiveUniform(
8658 uint32 immediate_data_size, const cmds::GetActiveUniform& c) {
8659 GLuint program_id = c.program;
8660 GLuint index = c.index;
8661 uint32 name_bucket_id = c.name_bucket_id;
8662 typedef cmds::GetActiveUniform::Result Result;
8663 Result* result = GetSharedMemoryAs<Result*>(
8664 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8665 if (!result) {
8666 return error::kOutOfBounds;
8668 // Check that the client initialized the result.
8669 if (result->success != 0) {
8670 return error::kInvalidArguments;
8672 Program* program = GetProgramInfoNotShader(
8673 program_id, "glGetActiveUniform");
8674 if (!program) {
8675 return error::kNoError;
8677 const Program::UniformInfo* uniform_info =
8678 program->GetUniformInfo(index);
8679 if (!uniform_info) {
8680 LOCAL_SET_GL_ERROR(
8681 GL_INVALID_VALUE, "glGetActiveUniform", "index out of range");
8682 return error::kNoError;
8684 result->success = 1; // true.
8685 result->size = uniform_info->size;
8686 result->type = uniform_info->type;
8687 Bucket* bucket = CreateBucket(name_bucket_id);
8688 bucket->SetFromString(uniform_info->name.c_str());
8689 return error::kNoError;
8692 error::Error GLES2DecoderImpl::HandleGetActiveAttrib(
8693 uint32 immediate_data_size, const cmds::GetActiveAttrib& c) {
8694 GLuint program_id = c.program;
8695 GLuint index = c.index;
8696 uint32 name_bucket_id = c.name_bucket_id;
8697 typedef cmds::GetActiveAttrib::Result Result;
8698 Result* result = GetSharedMemoryAs<Result*>(
8699 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8700 if (!result) {
8701 return error::kOutOfBounds;
8703 // Check that the client initialized the result.
8704 if (result->success != 0) {
8705 return error::kInvalidArguments;
8707 Program* program = GetProgramInfoNotShader(
8708 program_id, "glGetActiveAttrib");
8709 if (!program) {
8710 return error::kNoError;
8712 const Program::VertexAttrib* attrib_info =
8713 program->GetAttribInfo(index);
8714 if (!attrib_info) {
8715 LOCAL_SET_GL_ERROR(
8716 GL_INVALID_VALUE, "glGetActiveAttrib", "index out of range");
8717 return error::kNoError;
8719 result->success = 1; // true.
8720 result->size = attrib_info->size;
8721 result->type = attrib_info->type;
8722 Bucket* bucket = CreateBucket(name_bucket_id);
8723 bucket->SetFromString(attrib_info->name.c_str());
8724 return error::kNoError;
8727 error::Error GLES2DecoderImpl::HandleShaderBinary(
8728 uint32 immediate_data_size, const cmds::ShaderBinary& c) {
8729 #if 1 // No binary shader support.
8730 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glShaderBinary", "not supported");
8731 return error::kNoError;
8732 #else
8733 GLsizei n = static_cast<GLsizei>(c.n);
8734 if (n < 0) {
8735 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "n < 0");
8736 return error::kNoError;
8738 GLsizei length = static_cast<GLsizei>(c.length);
8739 if (length < 0) {
8740 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "length < 0");
8741 return error::kNoError;
8743 uint32 data_size;
8744 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
8745 return error::kOutOfBounds;
8747 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
8748 c.shaders_shm_id, c.shaders_shm_offset, data_size);
8749 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
8750 const void* binary = GetSharedMemoryAs<const void*>(
8751 c.binary_shm_id, c.binary_shm_offset, length);
8752 if (shaders == NULL || binary == NULL) {
8753 return error::kOutOfBounds;
8755 scoped_array<GLuint> service_ids(new GLuint[n]);
8756 for (GLsizei ii = 0; ii < n; ++ii) {
8757 Shader* shader = GetShader(shaders[ii]);
8758 if (!shader) {
8759 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "unknown shader");
8760 return error::kNoError;
8762 service_ids[ii] = shader->service_id();
8764 // TODO(gman): call glShaderBinary
8765 return error::kNoError;
8766 #endif
8769 void GLES2DecoderImpl::DoSwapBuffers() {
8770 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
8772 int this_frame_number = frame_number_++;
8773 // TRACE_EVENT for gpu tests:
8774 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffersLatency",
8775 TRACE_EVENT_SCOPE_THREAD,
8776 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
8777 "width", (is_offscreen ? offscreen_size_.width() :
8778 surface_->GetSize().width()));
8779 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoSwapBuffers",
8780 "offscreen", is_offscreen,
8781 "frame", this_frame_number);
8782 // If offscreen then don't actually SwapBuffers to the display. Just copy
8783 // the rendered frame to another frame buffer.
8784 if (is_offscreen) {
8785 TRACE_EVENT2("gpu", "Offscreen",
8786 "width", offscreen_size_.width(), "height", offscreen_size_.height());
8787 if (offscreen_size_ != offscreen_saved_color_texture_->size()) {
8788 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
8789 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
8790 // fix this.
8791 if (workarounds().needs_offscreen_buffer_workaround) {
8792 offscreen_saved_frame_buffer_->Create();
8793 glFinish();
8796 // Allocate the offscreen saved color texture.
8797 DCHECK(offscreen_saved_color_format_);
8798 offscreen_saved_color_texture_->AllocateStorage(
8799 offscreen_size_, offscreen_saved_color_format_, false);
8801 offscreen_saved_frame_buffer_->AttachRenderTexture(
8802 offscreen_saved_color_texture_.get());
8803 if (offscreen_size_.width() != 0 && offscreen_size_.height() != 0) {
8804 if (offscreen_saved_frame_buffer_->CheckStatus() !=
8805 GL_FRAMEBUFFER_COMPLETE) {
8806 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
8807 << "because offscreen saved FBO was incomplete.";
8808 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB);
8809 return;
8812 // Clear the offscreen color texture.
8813 // TODO(piman): Is this still necessary?
8815 ScopedFrameBufferBinder binder(this,
8816 offscreen_saved_frame_buffer_->id());
8817 glClearColor(0, 0, 0, 0);
8818 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
8819 glDisable(GL_SCISSOR_TEST);
8820 glClear(GL_COLOR_BUFFER_BIT);
8821 RestoreClearState();
8825 UpdateParentTextureInfo();
8828 if (offscreen_size_.width() == 0 || offscreen_size_.height() == 0)
8829 return;
8830 ScopedGLErrorSuppressor suppressor(
8831 "GLES2DecoderImpl::DoSwapBuffers", this);
8833 if (IsOffscreenBufferMultisampled()) {
8834 // For multisampled buffers, resolve the frame buffer.
8835 ScopedResolvedFrameBufferBinder binder(this, true, false);
8836 } else {
8837 ScopedFrameBufferBinder binder(this,
8838 offscreen_target_frame_buffer_->id());
8840 if (offscreen_target_buffer_preserved_) {
8841 // Copy the target frame buffer to the saved offscreen texture.
8842 offscreen_saved_color_texture_->Copy(
8843 offscreen_saved_color_texture_->size(),
8844 offscreen_saved_color_format_);
8845 } else {
8846 // Flip the textures in the parent context via the texture manager.
8847 if (!!offscreen_saved_color_texture_info_.get())
8848 offscreen_saved_color_texture_info_->texture()->
8849 SetServiceId(offscreen_target_color_texture_->id());
8851 offscreen_saved_color_texture_.swap(offscreen_target_color_texture_);
8852 offscreen_target_frame_buffer_->AttachRenderTexture(
8853 offscreen_target_color_texture_.get());
8856 // Ensure the side effects of the copy are visible to the parent
8857 // context. There is no need to do this for ANGLE because it uses a
8858 // single D3D device for all contexts.
8859 if (!IsAngle())
8860 glFlush();
8862 } else {
8863 TRACE_EVENT2("gpu", "Onscreen",
8864 "width", surface_->GetSize().width(),
8865 "height", surface_->GetSize().height());
8866 if (!surface_->SwapBuffers()) {
8867 LOG(ERROR) << "Context lost because SwapBuffers failed.";
8868 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB);
8873 error::Error GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
8874 uint32 immediate_data_size, const cmds::EnableFeatureCHROMIUM& c) {
8875 Bucket* bucket = GetBucket(c.bucket_id);
8876 if (!bucket || bucket->size() == 0) {
8877 return error::kInvalidArguments;
8879 typedef cmds::EnableFeatureCHROMIUM::Result Result;
8880 Result* result = GetSharedMemoryAs<Result*>(
8881 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8882 if (!result) {
8883 return error::kOutOfBounds;
8885 // Check that the client initialized the result.
8886 if (*result != 0) {
8887 return error::kInvalidArguments;
8889 std::string feature_str;
8890 if (!bucket->GetAsString(&feature_str)) {
8891 return error::kInvalidArguments;
8894 // TODO(gman): make this some kind of table to function pointer thingy.
8895 if (feature_str.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
8896 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
8897 } else if (feature_str.compare("pepper3d_support_fixed_attribs") == 0) {
8898 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
8899 // TODO(gman): decide how to remove the need for this const_cast.
8900 // I could make validators_ non const but that seems bad as this is the only
8901 // place it is needed. I could make some special friend class of validators
8902 // just to allow this to set them. That seems silly. I could refactor this
8903 // code to use the extension mechanism or the initialization attributes to
8904 // turn this feature on. Given that the only real point of this is to make
8905 // the conformance tests pass and given that there is lots of real work that
8906 // needs to be done it seems like refactoring for one to one of those
8907 // methods is a very low priority.
8908 const_cast<Validators*>(validators_)->vertex_attrib_type.AddValue(GL_FIXED);
8909 } else if (feature_str.compare("webgl_enable_glsl_webgl_validation") == 0) {
8910 force_webgl_glsl_validation_ = true;
8911 InitializeShaderTranslator();
8912 } else {
8913 return error::kNoError;
8916 *result = 1; // true.
8917 return error::kNoError;
8920 error::Error GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
8921 uint32 immediate_data_size,
8922 const cmds::GetRequestableExtensionsCHROMIUM& c) {
8923 Bucket* bucket = CreateBucket(c.bucket_id);
8924 scoped_refptr<FeatureInfo> info(new FeatureInfo());
8925 info->Initialize(disallowed_features_, NULL);
8926 bucket->SetFromString(info->extensions().c_str());
8927 return error::kNoError;
8930 error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
8931 uint32 immediate_data_size, const cmds::RequestExtensionCHROMIUM& c) {
8932 Bucket* bucket = GetBucket(c.bucket_id);
8933 if (!bucket || bucket->size() == 0) {
8934 return error::kInvalidArguments;
8936 std::string feature_str;
8937 if (!bucket->GetAsString(&feature_str)) {
8938 return error::kInvalidArguments;
8941 bool desire_webgl_glsl_validation =
8942 feature_str.find("GL_CHROMIUM_webglsl") != std::string::npos;
8943 bool desire_standard_derivatives = false;
8944 bool desire_frag_depth = false;
8945 bool desire_draw_buffers = false;
8946 if (force_webgl_glsl_validation_) {
8947 desire_standard_derivatives =
8948 feature_str.find("GL_OES_standard_derivatives") != std::string::npos;
8949 desire_frag_depth =
8950 feature_str.find("GL_EXT_frag_depth") != std::string::npos;
8951 desire_draw_buffers =
8952 feature_str.find("GL_EXT_draw_buffers") != std::string::npos;
8955 if (desire_webgl_glsl_validation != force_webgl_glsl_validation_ ||
8956 desire_standard_derivatives != derivatives_explicitly_enabled_ ||
8957 desire_frag_depth != frag_depth_explicitly_enabled_ ||
8958 desire_draw_buffers != draw_buffers_explicitly_enabled_) {
8959 force_webgl_glsl_validation_ |= desire_webgl_glsl_validation;
8960 derivatives_explicitly_enabled_ |= desire_standard_derivatives;
8961 frag_depth_explicitly_enabled_ |= desire_frag_depth;
8962 draw_buffers_explicitly_enabled_ |= desire_draw_buffers;
8963 InitializeShaderTranslator();
8966 UpdateCapabilities();
8968 return error::kNoError;
8971 error::Error GLES2DecoderImpl::HandleGetMultipleIntegervCHROMIUM(
8972 uint32 immediate_data_size, const cmds::GetMultipleIntegervCHROMIUM& c) {
8973 GLuint count = c.count;
8974 uint32 pnames_size;
8975 if (!SafeMultiplyUint32(count, sizeof(GLenum), &pnames_size)) {
8976 return error::kOutOfBounds;
8978 const GLenum* pnames = GetSharedMemoryAs<const GLenum*>(
8979 c.pnames_shm_id, c.pnames_shm_offset, pnames_size);
8980 if (pnames == NULL) {
8981 return error::kOutOfBounds;
8984 // We have to copy them since we use them twice so the client
8985 // can't change them between the time we validate them and the time we use
8986 // them.
8987 scoped_ptr<GLenum[]> enums(new GLenum[count]);
8988 memcpy(enums.get(), pnames, pnames_size);
8990 // Count up the space needed for the result.
8991 uint32 num_results = 0;
8992 for (GLuint ii = 0; ii < count; ++ii) {
8993 uint32 num = util_.GLGetNumValuesReturned(enums[ii]);
8994 if (num == 0) {
8995 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8996 "glGetMulitpleCHROMIUM", enums[ii], "pname");
8997 return error::kNoError;
8999 // Num will never be more than 4.
9000 DCHECK_LE(num, 4u);
9001 if (!SafeAddUint32(num_results, num, &num_results)) {
9002 return error::kOutOfBounds;
9006 uint32 result_size = 0;
9007 if (!SafeMultiplyUint32(num_results, sizeof(GLint), &result_size)) {
9008 return error::kOutOfBounds;
9011 if (result_size != static_cast<uint32>(c.size)) {
9012 LOCAL_SET_GL_ERROR(
9013 GL_INVALID_VALUE,
9014 "glGetMulitpleCHROMIUM", "bad size GL_INVALID_VALUE");
9015 return error::kNoError;
9018 GLint* results = GetSharedMemoryAs<GLint*>(
9019 c.results_shm_id, c.results_shm_offset, result_size);
9020 if (results == NULL) {
9021 return error::kOutOfBounds;
9024 // Check the results have been cleared in case the context was lost.
9025 for (uint32 ii = 0; ii < num_results; ++ii) {
9026 if (results[ii]) {
9027 return error::kInvalidArguments;
9031 // Get each result.
9032 GLint* start = results;
9033 for (GLuint ii = 0; ii < count; ++ii) {
9034 GLsizei num_written = 0;
9035 if (!state_.GetStateAsGLint(enums[ii], results, &num_written) &&
9036 !GetHelper(enums[ii], results, &num_written)) {
9037 DoGetIntegerv(enums[ii], results);
9039 results += num_written;
9042 // Just to verify. Should this be a DCHECK?
9043 if (static_cast<uint32>(results - start) != num_results) {
9044 return error::kOutOfBounds;
9047 return error::kNoError;
9050 error::Error GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
9051 uint32 immediate_data_size, const cmds::GetProgramInfoCHROMIUM& c) {
9052 GLuint program_id = static_cast<GLuint>(c.program);
9053 uint32 bucket_id = c.bucket_id;
9054 Bucket* bucket = CreateBucket(bucket_id);
9055 bucket->SetSize(sizeof(ProgramInfoHeader)); // in case we fail.
9056 Program* program = NULL;
9057 program = GetProgram(program_id);
9058 if (!program || !program->IsValid()) {
9059 return error::kNoError;
9061 program->GetProgramInfo(program_manager(), bucket);
9062 return error::kNoError;
9065 error::ContextLostReason GLES2DecoderImpl::GetContextLostReason() {
9066 switch (reset_status_) {
9067 case GL_NO_ERROR:
9068 // TODO(kbr): improve the precision of the error code in this case.
9069 // Consider delegating to context for error code if MakeCurrent fails.
9070 return error::kUnknown;
9071 case GL_GUILTY_CONTEXT_RESET_ARB:
9072 return error::kGuilty;
9073 case GL_INNOCENT_CONTEXT_RESET_ARB:
9074 return error::kInnocent;
9075 case GL_UNKNOWN_CONTEXT_RESET_ARB:
9076 return error::kUnknown;
9079 NOTREACHED();
9080 return error::kUnknown;
9083 bool GLES2DecoderImpl::WasContextLost() {
9084 if (reset_status_ != GL_NO_ERROR) {
9085 return true;
9087 if (context_->WasAllocatedUsingRobustnessExtension()) {
9088 GLenum status = GL_NO_ERROR;
9089 if (has_robustness_extension_)
9090 status = glGetGraphicsResetStatusARB();
9091 if (status != GL_NO_ERROR) {
9092 // The graphics card was reset. Signal a lost context to the application.
9093 reset_status_ = status;
9094 reset_by_robustness_extension_ = true;
9095 LOG(ERROR) << (surface_->IsOffscreen() ? "Offscreen" : "Onscreen")
9096 << " context lost via ARB/EXT_robustness. Reset status = "
9097 << GLES2Util::GetStringEnum(status);
9098 return true;
9101 return false;
9104 bool GLES2DecoderImpl::WasContextLostByRobustnessExtension() {
9105 return WasContextLost() && reset_by_robustness_extension_;
9108 void GLES2DecoderImpl::LoseContext(uint32 reset_status) {
9109 // Only loses the context once.
9110 if (reset_status_ != GL_NO_ERROR) {
9111 return;
9114 // Marks this context as lost.
9115 reset_status_ = reset_status;
9116 current_decoder_error_ = error::kLostContext;
9119 error::Error GLES2DecoderImpl::HandleLoseContextCHROMIUM(
9120 uint32 immediate_data_size, const cmds::LoseContextCHROMIUM& c) {
9121 GLenum current = static_cast<GLenum>(c.current);
9122 GLenum other = static_cast<GLenum>(c.other);
9123 if (!validators_->reset_status.IsValid(current)) {
9124 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9125 "glLoseContextCHROMIUM", current, "current");
9127 if (!validators_->reset_status.IsValid(other)) {
9128 LOCAL_SET_GL_ERROR_INVALID_ENUM("glLoseContextCHROMIUM", other, "other");
9130 group_->LoseContexts(other);
9131 reset_status_ = current;
9132 current_decoder_error_ = error::kLostContext;
9133 return error::kLostContext;
9136 error::Error GLES2DecoderImpl::HandleInsertSyncPointCHROMIUM(
9137 uint32 immediate_data_size, const cmds::InsertSyncPointCHROMIUM& c) {
9138 return error::kUnknownCommand;
9141 error::Error GLES2DecoderImpl::HandleWaitSyncPointCHROMIUM(
9142 uint32 immediate_data_size, const cmds::WaitSyncPointCHROMIUM& c) {
9143 if (wait_sync_point_callback_.is_null())
9144 return error::kNoError;
9146 return wait_sync_point_callback_.Run(c.sync_point) ?
9147 error::kNoError : error::kDeferCommandUntilLater;
9150 bool GLES2DecoderImpl::GenQueriesEXTHelper(
9151 GLsizei n, const GLuint* client_ids) {
9152 for (GLsizei ii = 0; ii < n; ++ii) {
9153 if (query_manager_->GetQuery(client_ids[ii])) {
9154 return false;
9157 // NOTE: We don't generate Query objects here. Only in BeginQueryEXT
9158 return true;
9161 void GLES2DecoderImpl::DeleteQueriesEXTHelper(
9162 GLsizei n, const GLuint* client_ids) {
9163 for (GLsizei ii = 0; ii < n; ++ii) {
9164 QueryManager::Query* query = query_manager_->GetQuery(client_ids[ii]);
9165 if (query && !query->IsDeleted()) {
9166 if (query == state_.current_query.get()) {
9167 state_.current_query = NULL;
9169 query->Destroy(true);
9170 query_manager_->RemoveQuery(client_ids[ii]);
9175 bool GLES2DecoderImpl::ProcessPendingQueries() {
9176 if (query_manager_.get() == NULL) {
9177 return false;
9179 if (!query_manager_->ProcessPendingQueries()) {
9180 current_decoder_error_ = error::kOutOfBounds;
9182 return query_manager_->HavePendingQueries();
9185 // Note that if there are no pending readpixels right now,
9186 // this function will call the callback immediately.
9187 void GLES2DecoderImpl::WaitForReadPixels(base::Closure callback) {
9188 if (features().use_async_readpixels && !pending_readpixel_fences_.empty()) {
9189 pending_readpixel_fences_.back()->callbacks.push_back(callback);
9190 } else {
9191 callback.Run();
9195 void GLES2DecoderImpl::ProcessPendingReadPixels() {
9196 while (!pending_readpixel_fences_.empty() &&
9197 pending_readpixel_fences_.front()->fence->HasCompleted()) {
9198 std::vector<base::Closure> callbacks =
9199 pending_readpixel_fences_.front()->callbacks;
9200 pending_readpixel_fences_.pop();
9201 for (size_t i = 0; i < callbacks.size(); i++) {
9202 callbacks[i].Run();
9207 bool GLES2DecoderImpl::HasMoreIdleWork() {
9208 return !pending_readpixel_fences_.empty() ||
9209 async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers();
9212 void GLES2DecoderImpl::PerformIdleWork() {
9213 ProcessPendingReadPixels();
9214 if (!async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers())
9215 return;
9216 async_pixel_transfer_manager_->ProcessMorePendingTransfers();
9217 ProcessFinishedAsyncTransfers();
9220 error::Error GLES2DecoderImpl::HandleBeginQueryEXT(
9221 uint32 immediate_data_size, const cmds::BeginQueryEXT& c) {
9222 GLenum target = static_cast<GLenum>(c.target);
9223 GLuint client_id = static_cast<GLuint>(c.id);
9224 int32 sync_shm_id = static_cast<int32>(c.sync_data_shm_id);
9225 uint32 sync_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
9227 switch (target) {
9228 case GL_COMMANDS_ISSUED_CHROMIUM:
9229 case GL_LATENCY_QUERY_CHROMIUM:
9230 case GL_ASYNC_PIXEL_TRANSFERS_COMPLETED_CHROMIUM:
9231 case GL_ASYNC_READ_PIXELS_COMPLETED_CHROMIUM:
9232 case GL_GET_ERROR_QUERY_CHROMIUM:
9233 break;
9234 default:
9235 if (!features().occlusion_query_boolean) {
9236 LOCAL_SET_GL_ERROR(
9237 GL_INVALID_OPERATION, "glBeginQueryEXT",
9238 "not enabled for occlusion queries");
9239 return error::kNoError;
9241 break;
9244 // TODO(hubbe): Make it possible to have one query per type running at the
9245 // same time.
9246 if (state_.current_query.get()) {
9247 LOCAL_SET_GL_ERROR(
9248 GL_INVALID_OPERATION, "glBeginQueryEXT", "query already in progress");
9249 return error::kNoError;
9252 if (client_id == 0) {
9253 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glBeginQueryEXT", "id is 0");
9254 return error::kNoError;
9257 QueryManager::Query* query = query_manager_->GetQuery(client_id);
9258 if (!query) {
9259 // TODO(gman): Decide if we need this check.
9261 // Checks id was made by glGenQueries
9263 // From the POV of OpenGL ES 2.0 you need to call glGenQueriesEXT
9264 // for all Query ids but from the POV of the command buffer service maybe
9265 // you don't.
9267 // The client can enforce this. I don't think the service cares.
9269 // IdAllocatorInterface* id_allocator =
9270 // group_->GetIdAllocator(id_namespaces::kQueries);
9271 // if (!id_allocator->InUse(client_id)) {
9272 // LOCAL_SET_GL_ERROR(
9273 // GL_INVALID_OPERATION,
9274 // "glBeginQueryEXT", "id not made by glGenQueriesEXT");
9275 // return error::kNoError;
9276 // }
9277 query = query_manager_->CreateQuery(
9278 target, client_id, sync_shm_id, sync_shm_offset);
9281 if (query->target() != target) {
9282 LOCAL_SET_GL_ERROR(
9283 GL_INVALID_OPERATION, "glBeginQueryEXT", "target does not match");
9284 return error::kNoError;
9285 } else if (query->shm_id() != sync_shm_id ||
9286 query->shm_offset() != sync_shm_offset) {
9287 DLOG(ERROR) << "Shared memory used by query not the same as before";
9288 return error::kInvalidArguments;
9291 if (!query_manager_->BeginQuery(query)) {
9292 return error::kOutOfBounds;
9295 state_.current_query = query;
9296 return error::kNoError;
9299 error::Error GLES2DecoderImpl::HandleEndQueryEXT(
9300 uint32 immediate_data_size, const cmds::EndQueryEXT& c) {
9301 GLenum target = static_cast<GLenum>(c.target);
9302 uint32 submit_count = static_cast<GLuint>(c.submit_count);
9304 if (!state_.current_query.get()) {
9305 LOCAL_SET_GL_ERROR(
9306 GL_INVALID_OPERATION, "glEndQueryEXT", "No active query");
9307 return error::kNoError;
9309 if (state_.current_query->target() != target) {
9310 LOCAL_SET_GL_ERROR(
9311 GL_INVALID_OPERATION,
9312 "glEndQueryEXT", "target does not match active query");
9313 return error::kNoError;
9316 if (!query_manager_->EndQuery(state_.current_query.get(), submit_count)) {
9317 return error::kOutOfBounds;
9320 query_manager_->ProcessPendingTransferQueries();
9322 state_.current_query = NULL;
9323 return error::kNoError;
9326 bool GLES2DecoderImpl::GenVertexArraysOESHelper(
9327 GLsizei n, const GLuint* client_ids) {
9328 for (GLsizei ii = 0; ii < n; ++ii) {
9329 if (GetVertexAttribManager(client_ids[ii])) {
9330 return false;
9334 if (!features().native_vertex_array_object) {
9335 // Emulated VAO
9336 for (GLsizei ii = 0; ii < n; ++ii) {
9337 CreateVertexAttribManager(client_ids[ii], 0);
9339 } else {
9340 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
9342 glGenVertexArraysOES(n, service_ids.get());
9343 for (GLsizei ii = 0; ii < n; ++ii) {
9344 CreateVertexAttribManager(client_ids[ii], service_ids[ii]);
9348 return true;
9351 void GLES2DecoderImpl::DeleteVertexArraysOESHelper(
9352 GLsizei n, const GLuint* client_ids) {
9353 for (GLsizei ii = 0; ii < n; ++ii) {
9354 VertexAttribManager* vao =
9355 GetVertexAttribManager(client_ids[ii]);
9356 if (vao && !vao->IsDeleted()) {
9357 if (state_.vertex_attrib_manager.get() == vao) {
9358 state_.vertex_attrib_manager = default_vertex_attrib_manager_;
9360 RemoveVertexAttribManager(client_ids[ii]);
9365 void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id) {
9366 VertexAttribManager* vao = NULL;
9367 GLuint service_id = 0;
9368 if (client_id != 0) {
9369 vao = GetVertexAttribManager(client_id);
9370 if (!vao) {
9371 // Unlike most Bind* methods, the spec explicitly states that VertexArray
9372 // only allows names that have been previously generated. As such, we do
9373 // not generate new names here.
9374 LOCAL_SET_GL_ERROR(
9375 GL_INVALID_OPERATION,
9376 "glBindVertexArrayOES", "bad vertex array id.");
9377 current_decoder_error_ = error::kNoError;
9378 return;
9379 } else {
9380 service_id = vao->service_id();
9382 } else {
9383 vao = default_vertex_attrib_manager_.get();
9386 // Only set the VAO state if it's changed
9387 if (state_.vertex_attrib_manager.get() != vao) {
9388 state_.vertex_attrib_manager = vao;
9389 if (!features().native_vertex_array_object) {
9390 EmulateVertexArrayState();
9391 } else {
9392 glBindVertexArrayOES(service_id);
9397 // Used when OES_vertex_array_object isn't natively supported
9398 void GLES2DecoderImpl::EmulateVertexArrayState() {
9399 // Setup the Vertex attribute state
9400 for (uint32 vv = 0; vv < group_->max_vertex_attribs(); ++vv) {
9401 RestoreStateForAttrib(vv);
9404 // Setup the element buffer
9405 Buffer* element_array_buffer =
9406 state_.vertex_attrib_manager->element_array_buffer();
9407 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
9408 element_array_buffer ? element_array_buffer->service_id() : 0);
9411 bool GLES2DecoderImpl::DoIsVertexArrayOES(GLuint client_id) {
9412 const VertexAttribManager* vao =
9413 GetVertexAttribManager(client_id);
9414 return vao && vao->IsValid() && !vao->IsDeleted();
9417 error::Error GLES2DecoderImpl::HandleCreateStreamTextureCHROMIUM(
9418 uint32 immediate_data_size,
9419 const cmds::CreateStreamTextureCHROMIUM& c) {
9420 if (!features().chromium_stream_texture) {
9421 LOCAL_SET_GL_ERROR(
9422 GL_INVALID_OPERATION,
9423 "glOpenStreamTextureCHROMIUM", "not supported.");
9424 return error::kNoError;
9427 uint32 client_id = c.client_id;
9428 typedef cmds::CreateStreamTextureCHROMIUM::Result Result;
9429 Result* result = GetSharedMemoryAs<Result*>(
9430 c.result_shm_id, c.result_shm_offset, sizeof(*result));
9432 if (!result)
9433 return error::kOutOfBounds;
9434 *result = GL_ZERO;
9435 TextureRef* texture_ref = texture_manager()->GetTexture(client_id);
9436 if (!texture_ref) {
9437 LOCAL_SET_GL_ERROR(
9438 GL_INVALID_VALUE,
9439 "glCreateStreamTextureCHROMIUM", "bad texture id.");
9440 return error::kNoError;
9443 Texture* texture = texture_ref->texture();
9444 if (texture->IsStreamTexture()) {
9445 LOCAL_SET_GL_ERROR(
9446 GL_INVALID_OPERATION,
9447 "glCreateStreamTextureCHROMIUM", "is already a stream texture.");
9448 return error::kNoError;
9451 if (texture->target() && texture->target() != GL_TEXTURE_EXTERNAL_OES) {
9452 LOCAL_SET_GL_ERROR(
9453 GL_INVALID_OPERATION,
9454 "glCreateStreamTextureCHROMIUM",
9455 "is already bound to incompatible target.");
9456 return error::kNoError;
9459 if (!stream_texture_manager())
9460 return error::kInvalidArguments;
9462 GLuint object_id = stream_texture_manager()->CreateStreamTexture(
9463 texture->service_id(), client_id);
9465 if (object_id) {
9466 texture_manager()->SetStreamTexture(texture_ref, true);
9467 } else {
9468 LOCAL_SET_GL_ERROR(
9469 GL_OUT_OF_MEMORY,
9470 "glCreateStreamTextureCHROMIUM", "failed to create platform texture.");
9473 *result = object_id;
9474 return error::kNoError;
9477 error::Error GLES2DecoderImpl::HandleDestroyStreamTextureCHROMIUM(
9478 uint32 immediate_data_size,
9479 const cmds::DestroyStreamTextureCHROMIUM& c) {
9480 GLuint client_id = c.texture;
9481 TextureRef* texture_ref = texture_manager()->GetTexture(client_id);
9482 if (texture_ref && texture_manager()->IsStreamTextureOwner(texture_ref)) {
9483 if (!stream_texture_manager())
9484 return error::kInvalidArguments;
9486 stream_texture_manager()->DestroyStreamTexture(texture_ref->service_id());
9487 texture_manager()->SetStreamTexture(texture_ref, false);
9488 } else {
9489 LOCAL_SET_GL_ERROR(
9490 GL_INVALID_VALUE,
9491 "glDestroyStreamTextureCHROMIUM", "bad texture id.");
9494 return error::kNoError;
9497 #if defined(OS_MACOSX)
9498 void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id) {
9499 TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.find(
9500 texture_id);
9501 if (it != texture_to_io_surface_map_.end()) {
9502 // Found a previous IOSurface bound to this texture; release it.
9503 CFTypeRef surface = it->second;
9504 CFRelease(surface);
9505 texture_to_io_surface_map_.erase(it);
9508 #endif
9510 void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
9511 GLenum target, GLsizei width, GLsizei height,
9512 GLuint io_surface_id, GLuint plane) {
9513 #if defined(OS_MACOSX)
9514 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) {
9515 LOCAL_SET_GL_ERROR(
9516 GL_INVALID_OPERATION,
9517 "glTexImageIOSurface2DCHROMIUM", "only supported on desktop GL.");
9518 return;
9521 IOSurfaceSupport* surface_support = IOSurfaceSupport::Initialize();
9522 if (!surface_support) {
9523 LOCAL_SET_GL_ERROR(
9524 GL_INVALID_OPERATION,
9525 "glTexImageIOSurface2DCHROMIUM", "only supported on 10.6.");
9526 return;
9529 if (target != GL_TEXTURE_RECTANGLE_ARB) {
9530 // This might be supported in the future, and if we could require
9531 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
9532 // could delete a lot of code. For now, perform strict validation so we
9533 // know what's going on.
9534 LOCAL_SET_GL_ERROR(
9535 GL_INVALID_OPERATION,
9536 "glTexImageIOSurface2DCHROMIUM",
9537 "requires TEXTURE_RECTANGLE_ARB target");
9538 return;
9541 // Default target might be conceptually valid, but disallow it to avoid
9542 // accidents.
9543 TextureRef* texture_ref = GetTextureInfoForTargetUnlessDefault(target);
9544 if (!texture_ref) {
9545 LOCAL_SET_GL_ERROR(
9546 GL_INVALID_OPERATION,
9547 "glTexImageIOSurface2DCHROMIUM", "no rectangle texture bound");
9548 return;
9551 // Look up the new IOSurface. Note that because of asynchrony
9552 // between processes this might fail; during live resizing the
9553 // plugin process might allocate and release an IOSurface before
9554 // this process gets a chance to look it up. Hold on to any old
9555 // IOSurface in this case.
9556 CFTypeRef surface = surface_support->IOSurfaceLookup(io_surface_id);
9557 if (!surface) {
9558 LOCAL_SET_GL_ERROR(
9559 GL_INVALID_OPERATION,
9560 "glTexImageIOSurface2DCHROMIUM", "no IOSurface with the given ID");
9561 return;
9564 // Release any IOSurface previously bound to this texture.
9565 ReleaseIOSurfaceForTexture(texture_ref->service_id());
9567 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
9568 texture_to_io_surface_map_.insert(
9569 std::make_pair(texture_ref->service_id(), surface));
9571 CGLContextObj context =
9572 static_cast<CGLContextObj>(context_->GetHandle());
9574 CGLError err = surface_support->CGLTexImageIOSurface2D(
9575 context,
9576 target,
9577 GL_RGBA,
9578 width,
9579 height,
9580 GL_BGRA,
9581 GL_UNSIGNED_INT_8_8_8_8_REV,
9582 surface,
9583 plane);
9585 if (err != kCGLNoError) {
9586 LOCAL_SET_GL_ERROR(
9587 GL_INVALID_OPERATION,
9588 "glTexImageIOSurface2DCHROMIUM", "error in CGLTexImageIOSurface2D");
9589 return;
9592 texture_manager()->SetLevelInfo(
9593 texture_ref, target, 0, GL_RGBA, width, height, 1, 0,
9594 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, true);
9596 #else
9597 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
9598 "glTexImageIOSurface2DCHROMIUM", "not supported.");
9599 #endif
9602 static GLenum ExtractFormatFromStorageFormat(GLenum internalformat) {
9603 switch (internalformat) {
9604 case GL_RGB565:
9605 return GL_RGB;
9606 case GL_RGBA4:
9607 return GL_RGBA;
9608 case GL_RGB5_A1:
9609 return GL_RGBA;
9610 case GL_RGB8_OES:
9611 return GL_RGB;
9612 case GL_RGBA8_OES:
9613 return GL_RGBA;
9614 case GL_LUMINANCE8_ALPHA8_EXT:
9615 return GL_LUMINANCE_ALPHA;
9616 case GL_LUMINANCE8_EXT:
9617 return GL_LUMINANCE;
9618 case GL_ALPHA8_EXT:
9619 return GL_ALPHA;
9620 case GL_RGBA32F_EXT:
9621 return GL_RGBA;
9622 case GL_RGB32F_EXT:
9623 return GL_RGB;
9624 case GL_ALPHA32F_EXT:
9625 return GL_ALPHA;
9626 case GL_LUMINANCE32F_EXT:
9627 return GL_LUMINANCE;
9628 case GL_LUMINANCE_ALPHA32F_EXT:
9629 return GL_LUMINANCE_ALPHA;
9630 case GL_RGBA16F_EXT:
9631 return GL_RGBA;
9632 case GL_RGB16F_EXT:
9633 return GL_RGB;
9634 case GL_ALPHA16F_EXT:
9635 return GL_ALPHA;
9636 case GL_LUMINANCE16F_EXT:
9637 return GL_LUMINANCE;
9638 case GL_LUMINANCE_ALPHA16F_EXT:
9639 return GL_LUMINANCE_ALPHA;
9640 case GL_BGRA8_EXT:
9641 return GL_BGRA_EXT;
9642 default:
9643 return GL_NONE;
9647 void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
9648 GLenum target, GLuint source_id, GLuint dest_id, GLint level,
9649 GLenum internal_format, GLenum dest_type) {
9650 TextureRef* dest_texture_ref = GetTexture(dest_id);
9651 TextureRef* source_texture_ref = GetTexture(source_id);
9653 if (!source_texture_ref || !dest_texture_ref) {
9654 LOCAL_SET_GL_ERROR(
9655 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "unknown texture id");
9656 return;
9659 if (GL_TEXTURE_2D != target) {
9660 LOCAL_SET_GL_ERROR(
9661 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "invalid texture target");
9662 return;
9665 Texture* source_texture = source_texture_ref->texture();
9666 Texture* dest_texture = dest_texture_ref->texture();
9667 if (dest_texture->target() != GL_TEXTURE_2D ||
9668 (source_texture->target() != GL_TEXTURE_2D &&
9669 source_texture->target() != GL_TEXTURE_EXTERNAL_OES)) {
9670 LOCAL_SET_GL_ERROR(
9671 GL_INVALID_VALUE,
9672 "glCopyTextureCHROMIUM", "invalid texture target binding");
9673 return;
9676 int source_width, source_height, dest_width, dest_height;
9678 if (source_texture->target() == GL_TEXTURE_2D) {
9679 if (!source_texture->GetLevelSize(GL_TEXTURE_2D, 0, &source_width,
9680 &source_height)) {
9681 LOCAL_SET_GL_ERROR(
9682 GL_INVALID_VALUE,
9683 "glCopyTextureChromium", "source texture has no level 0");
9684 return;
9687 // Check that this type of texture is allowed.
9688 if (!texture_manager()->ValidForTarget(GL_TEXTURE_2D, level, source_width,
9689 source_height, 1)) {
9690 LOCAL_SET_GL_ERROR(
9691 GL_INVALID_VALUE,
9692 "glCopyTextureCHROMIUM", "Bad dimensions");
9693 return;
9697 if (source_texture->target() == GL_TEXTURE_EXTERNAL_OES) {
9698 DCHECK(stream_texture_manager());
9699 StreamTexture* stream_tex =
9700 stream_texture_manager()->LookupStreamTexture(
9701 source_texture->service_id());
9702 if (!stream_tex) {
9703 LOCAL_SET_GL_ERROR(
9704 GL_INVALID_VALUE,
9705 "glCopyTextureChromium", "Stream texture lookup failed");
9706 return;
9708 gfx::Size size = stream_tex->GetSize();
9709 source_width = size.width();
9710 source_height = size.height();
9711 if (source_width <= 0 || source_height <= 0) {
9712 LOCAL_SET_GL_ERROR(
9713 GL_INVALID_VALUE,
9714 "glCopyTextureChromium", "invalid streamtexture size");
9715 return;
9719 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
9720 // needed because it takes 10s of milliseconds to initialize.
9721 if (!copy_texture_CHROMIUM_.get()) {
9722 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
9723 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
9724 copy_texture_CHROMIUM_->Initialize(this);
9725 RestoreCurrentFramebufferBindings();
9726 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR)
9727 return;
9730 GLenum dest_type_previous;
9731 GLenum dest_internal_format;
9732 bool dest_level_defined = dest_texture->GetLevelSize(
9733 GL_TEXTURE_2D, level, &dest_width, &dest_height);
9735 if (dest_level_defined) {
9736 dest_texture->GetLevelType(GL_TEXTURE_2D, level, &dest_type_previous,
9737 &dest_internal_format);
9740 // Resize the destination texture to the dimensions of the source texture.
9741 if (!dest_level_defined || dest_width != source_width ||
9742 dest_height != source_height ||
9743 dest_internal_format != internal_format ||
9744 dest_type_previous != dest_type) {
9745 // Ensure that the glTexImage2D succeeds.
9746 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
9747 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
9748 glTexImage2D(
9749 GL_TEXTURE_2D, level, internal_format, source_width, source_height,
9750 0, internal_format, dest_type, NULL);
9751 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM");
9752 if (error != GL_NO_ERROR) {
9753 RestoreCurrentTexture2DBindings();
9754 return;
9757 texture_manager()->SetLevelInfo(
9758 dest_texture_ref, GL_TEXTURE_2D, level, internal_format, source_width,
9759 source_height, 1, 0, internal_format, dest_type, true);
9760 } else {
9761 texture_manager()->SetLevelCleared(
9762 dest_texture_ref, GL_TEXTURE_2D, level, true);
9765 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
9766 // before presenting.
9767 if (source_texture->target() == GL_TEXTURE_EXTERNAL_OES) {
9768 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
9769 // instead of using default matrix crbug.com/226218.
9770 const static GLfloat default_matrix[16] = {1.0f, 0.0f, 0.0f, 0.0f,
9771 0.0f, 1.0f, 0.0f, 0.0f,
9772 0.0f, 0.0f, 1.0f, 0.0f,
9773 0.0f, 0.0f, 0.0f, 1.0f};
9774 copy_texture_CHROMIUM_->DoCopyTextureWithTransform(
9775 this,
9776 source_texture->target(),
9777 dest_texture->target(),
9778 source_texture->service_id(),
9779 dest_texture->service_id(), level,
9780 source_width, source_height,
9781 unpack_flip_y_,
9782 unpack_premultiply_alpha_,
9783 unpack_unpremultiply_alpha_,
9784 default_matrix);
9785 } else {
9786 copy_texture_CHROMIUM_->DoCopyTexture(
9787 this,
9788 source_texture->target(),
9789 dest_texture->target(),
9790 source_texture->service_id(),
9791 dest_texture->service_id(), level,
9792 source_width, source_height,
9793 unpack_flip_y_,
9794 unpack_premultiply_alpha_,
9795 unpack_unpremultiply_alpha_);
9799 static GLenum ExtractTypeFromStorageFormat(GLenum internalformat) {
9800 switch (internalformat) {
9801 case GL_RGB565:
9802 return GL_UNSIGNED_SHORT_5_6_5;
9803 case GL_RGBA4:
9804 return GL_UNSIGNED_SHORT_4_4_4_4;
9805 case GL_RGB5_A1:
9806 return GL_UNSIGNED_SHORT_5_5_5_1;
9807 case GL_RGB8_OES:
9808 return GL_UNSIGNED_BYTE;
9809 case GL_RGBA8_OES:
9810 return GL_UNSIGNED_BYTE;
9811 case GL_LUMINANCE8_ALPHA8_EXT:
9812 return GL_UNSIGNED_BYTE;
9813 case GL_LUMINANCE8_EXT:
9814 return GL_UNSIGNED_BYTE;
9815 case GL_ALPHA8_EXT:
9816 return GL_UNSIGNED_BYTE;
9817 case GL_RGBA32F_EXT:
9818 return GL_FLOAT;
9819 case GL_RGB32F_EXT:
9820 return GL_FLOAT;
9821 case GL_ALPHA32F_EXT:
9822 return GL_FLOAT;
9823 case GL_LUMINANCE32F_EXT:
9824 return GL_FLOAT;
9825 case GL_LUMINANCE_ALPHA32F_EXT:
9826 return GL_FLOAT;
9827 case GL_RGBA16F_EXT:
9828 return GL_HALF_FLOAT_OES;
9829 case GL_RGB16F_EXT:
9830 return GL_HALF_FLOAT_OES;
9831 case GL_ALPHA16F_EXT:
9832 return GL_HALF_FLOAT_OES;
9833 case GL_LUMINANCE16F_EXT:
9834 return GL_HALF_FLOAT_OES;
9835 case GL_LUMINANCE_ALPHA16F_EXT:
9836 return GL_HALF_FLOAT_OES;
9837 case GL_BGRA8_EXT:
9838 return GL_UNSIGNED_BYTE;
9839 default:
9840 return GL_NONE;
9844 void GLES2DecoderImpl::DoTexStorage2DEXT(
9845 GLenum target,
9846 GLint levels,
9847 GLenum internal_format,
9848 GLsizei width,
9849 GLsizei height) {
9850 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT");
9851 if (!texture_manager()->ValidForTarget(target, 0, width, height, 1) ||
9852 TextureManager::ComputeMipMapCount(width, height, 1) < levels) {
9853 LOCAL_SET_GL_ERROR(
9854 GL_INVALID_VALUE, "glTexStorage2DEXT", "dimensions out of range");
9855 return;
9857 TextureRef* texture_ref = GetTextureInfoForTarget(target);
9858 if (!texture_ref) {
9859 LOCAL_SET_GL_ERROR(
9860 GL_INVALID_OPERATION,
9861 "glTexStorage2DEXT", "unknown texture for target");
9862 return;
9864 Texture* texture = texture_ref->texture();
9865 if (texture->IsAttachedToFramebuffer()) {
9866 clear_state_dirty_ = true;
9868 if (texture->IsImmutable()) {
9869 LOCAL_SET_GL_ERROR(
9870 GL_INVALID_OPERATION,
9871 "glTexStorage2DEXT", "texture is immutable");
9872 return;
9875 GLenum format = ExtractFormatFromStorageFormat(internal_format);
9876 GLenum type = ExtractTypeFromStorageFormat(internal_format);
9879 GLsizei level_width = width;
9880 GLsizei level_height = height;
9881 uint32 estimated_size = 0;
9882 for (int ii = 0; ii < levels; ++ii) {
9883 uint32 level_size = 0;
9884 if (!GLES2Util::ComputeImageDataSizes(
9885 level_width, level_height, format, type, state_.unpack_alignment,
9886 &estimated_size, NULL, NULL) ||
9887 !SafeAddUint32(estimated_size, level_size, &estimated_size)) {
9888 LOCAL_SET_GL_ERROR(
9889 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "dimensions too large");
9890 return;
9892 level_width = std::max(1, level_width >> 1);
9893 level_height = std::max(1, level_height >> 1);
9895 if (!EnsureGPUMemoryAvailable(estimated_size)) {
9896 LOCAL_SET_GL_ERROR(
9897 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "out of memory");
9898 return;
9902 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexStorage2DEXT");
9903 glTexStorage2DEXT(target, levels, internal_format, width, height);
9904 GLenum error = LOCAL_PEEK_GL_ERROR("glTexStorage2DEXT");
9905 if (error == GL_NO_ERROR) {
9906 GLsizei level_width = width;
9907 GLsizei level_height = height;
9908 for (int ii = 0; ii < levels; ++ii) {
9909 texture_manager()->SetLevelInfo(
9910 texture_ref, target, ii, format,
9911 level_width, level_height, 1, 0, format, type, false);
9912 level_width = std::max(1, level_width >> 1);
9913 level_height = std::max(1, level_height >> 1);
9915 texture->SetImmutable(true);
9919 error::Error GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
9920 uint32 immediate_data_size, const cmds::GenMailboxCHROMIUM& c) {
9921 MailboxName name;
9922 mailbox_manager()->GenerateMailboxName(&name);
9923 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
9924 Bucket* bucket = CreateBucket(bucket_id);
9926 bucket->SetSize(GL_MAILBOX_SIZE_CHROMIUM);
9927 bucket->SetData(&name, 0, GL_MAILBOX_SIZE_CHROMIUM);
9929 return error::kNoError;
9932 void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target,
9933 const GLbyte* mailbox) {
9934 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureCHROMIUM",
9935 "context", logger_.GetLogPrefix(),
9936 "mailbox[0]", static_cast<unsigned char>(mailbox[0]));
9938 TextureRef* texture_ref = GetTextureInfoForTarget(target);
9939 if (!texture_ref) {
9940 LOCAL_SET_GL_ERROR(
9941 GL_INVALID_OPERATION,
9942 "glProduceTextureCHROMIUM", "unknown texture for target");
9943 return;
9946 Texture* produced = texture_manager()->Produce(texture_ref);
9947 if (!produced) {
9948 LOCAL_SET_GL_ERROR(
9949 GL_INVALID_OPERATION,
9950 "glProduceTextureCHROMIUM", "invalid texture");
9951 return;
9954 if (!group_->mailbox_manager()->ProduceTexture(
9955 target,
9956 *reinterpret_cast<const MailboxName*>(mailbox),
9957 produced)) {
9958 LOCAL_SET_GL_ERROR(
9959 GL_INVALID_OPERATION,
9960 "glProduceTextureCHROMIUM", "invalid mailbox name");
9961 return;
9965 void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target,
9966 const GLbyte* mailbox) {
9967 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoConsumeTextureCHROMIUM",
9968 "context", logger_.GetLogPrefix(),
9969 "mailbox[0]", static_cast<unsigned char>(mailbox[0]));
9971 scoped_refptr<TextureRef> texture_ref =
9972 GetTextureInfoForTargetUnlessDefault(target);
9973 if (!texture_ref.get()) {
9974 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
9975 "glConsumeTextureCHROMIUM",
9976 "unknown texture for target");
9977 return;
9979 GLuint client_id = texture_ref->client_id();
9980 if (!client_id) {
9981 LOCAL_SET_GL_ERROR(
9982 GL_INVALID_OPERATION,
9983 "glConsumeTextureCHROMIUM", "unknown texture for target");
9984 return;
9986 Texture* texture =
9987 group_->mailbox_manager()->ConsumeTexture(
9988 target,
9989 *reinterpret_cast<const MailboxName*>(mailbox));
9990 if (!texture) {
9991 LOCAL_SET_GL_ERROR(
9992 GL_INVALID_OPERATION,
9993 "glConsumeTextureCHROMIUM", "invalid mailbox name");
9994 return;
9996 if (texture->target() != target) {
9997 LOCAL_SET_GL_ERROR(
9998 GL_INVALID_OPERATION,
9999 "glConsumeTextureCHROMIUM", "invalid target");
10000 return;
10003 DeleteTexturesHelper(1, &client_id);
10004 texture_ref = texture_manager()->Consume(client_id, texture);
10005 glBindTexture(target, texture_ref->service_id());
10007 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
10008 unit.bind_target = target;
10009 switch (target) {
10010 case GL_TEXTURE_2D:
10011 unit.bound_texture_2d = texture_ref;
10012 break;
10013 case GL_TEXTURE_CUBE_MAP:
10014 unit.bound_texture_cube_map = texture_ref;
10015 break;
10016 case GL_TEXTURE_EXTERNAL_OES:
10017 unit.bound_texture_external_oes = texture_ref;
10018 break;
10019 case GL_TEXTURE_RECTANGLE_ARB:
10020 unit.bound_texture_rectangle_arb = texture_ref;
10021 break;
10022 default:
10023 NOTREACHED(); // Validation should prevent us getting here.
10024 break;
10028 void GLES2DecoderImpl::DoInsertEventMarkerEXT(
10029 GLsizei length, const GLchar* marker) {
10030 if (!marker) {
10031 marker = "";
10033 debug_marker_manager_.SetMarker(
10034 length ? std::string(marker, length) : std::string(marker));
10037 void GLES2DecoderImpl::DoPushGroupMarkerEXT(
10038 GLsizei length, const GLchar* marker) {
10039 if (!marker) {
10040 marker = "";
10042 debug_marker_manager_.PushGroup(
10043 length ? std::string(marker, length) : std::string(marker));
10046 void GLES2DecoderImpl::DoPopGroupMarkerEXT(void) {
10047 debug_marker_manager_.PopGroup();
10050 void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(
10051 GLenum target, GLint image_id) {
10052 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM");
10053 if (target != GL_TEXTURE_2D) {
10054 // This might be supported in the future.
10055 LOCAL_SET_GL_ERROR(
10056 GL_INVALID_OPERATION,
10057 "glBindTexImage2DCHROMIUM", "requires TEXTURE_2D target");
10058 return;
10061 // Default target might be conceptually valid, but disallow it to avoid
10062 // accidents.
10063 TextureRef* texture_ref = GetTextureInfoForTargetUnlessDefault(target);
10064 if (!texture_ref) {
10065 LOCAL_SET_GL_ERROR(
10066 GL_INVALID_OPERATION,
10067 "glBindTexImage2DCHROMIUM", "no texture bound");
10068 return;
10071 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
10072 if (!gl_image) {
10073 LOCAL_SET_GL_ERROR(
10074 GL_INVALID_OPERATION,
10075 "glBindTexImage2DCHROMIUM", "no image found with the given ID");
10076 return;
10080 ScopedGLErrorSuppressor suppressor(
10081 "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", this);
10082 if (!gl_image->BindTexImage()) {
10083 LOCAL_SET_GL_ERROR(
10084 GL_INVALID_OPERATION,
10085 "glBindTexImage2DCHROMIUM", "fail to bind image with the given ID");
10086 return;
10090 gfx::Size size = gl_image->GetSize();
10091 texture_manager()->SetLevelInfo(
10092 texture_ref, target, 0, GL_RGBA, size.width(), size.height(), 1, 0,
10093 GL_RGBA, GL_UNSIGNED_BYTE, true);
10094 texture_manager()->SetLevelImage(texture_ref, target, 0, gl_image);
10097 void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(
10098 GLenum target, GLint image_id) {
10099 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM");
10100 if (target != GL_TEXTURE_2D) {
10101 // This might be supported in the future.
10102 LOCAL_SET_GL_ERROR(
10103 GL_INVALID_OPERATION,
10104 "glReleaseTexImage2DCHROMIUM", "requires TEXTURE_2D target");
10105 return;
10108 // Default target might be conceptually valid, but disallow it to avoid
10109 // accidents.
10110 TextureRef* texture_ref = GetTextureInfoForTargetUnlessDefault(target);
10111 if (!texture_ref) {
10112 LOCAL_SET_GL_ERROR(
10113 GL_INVALID_OPERATION,
10114 "glReleaseTexImage2DCHROMIUM", "no texture bound");
10115 return;
10118 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
10119 if (!gl_image) {
10120 LOCAL_SET_GL_ERROR(
10121 GL_INVALID_OPERATION,
10122 "glReleaseTexImage2DCHROMIUM", "no image found with the given ID");
10123 return;
10126 // Do nothing when image is not currently bound.
10127 if (texture_ref->texture()->GetLevelImage(target, 0) != gl_image)
10128 return;
10131 ScopedGLErrorSuppressor suppressor(
10132 "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", this);
10133 gl_image->ReleaseTexImage();
10136 texture_manager()->SetLevelInfo(
10137 texture_ref, target, 0, GL_RGBA, 0, 0, 1, 0,
10138 GL_RGBA, GL_UNSIGNED_BYTE, false);
10141 error::Error GLES2DecoderImpl::HandleTraceBeginCHROMIUM(
10142 uint32 immediate_data_size, const cmds::TraceBeginCHROMIUM& c) {
10143 Bucket* bucket = GetBucket(c.bucket_id);
10144 if (!bucket || bucket->size() == 0) {
10145 return error::kInvalidArguments;
10147 std::string command_name;
10148 if (!bucket->GetAsString(&command_name)) {
10149 return error::kInvalidArguments;
10151 TRACE_EVENT_COPY_ASYNC_BEGIN0("gpu", command_name.c_str(), this);
10152 if (!gpu_tracer_->Begin(command_name)) {
10153 LOCAL_SET_GL_ERROR(
10154 GL_INVALID_OPERATION,
10155 "glTraceBeginCHROMIUM", "unable to create begin trace");
10156 return error::kNoError;
10158 return error::kNoError;
10161 void GLES2DecoderImpl::DoTraceEndCHROMIUM() {
10162 if (gpu_tracer_->CurrentName().empty()) {
10163 LOCAL_SET_GL_ERROR(
10164 GL_INVALID_OPERATION,
10165 "glTraceEndCHROMIUM", "no trace begin found");
10166 return;
10168 TRACE_EVENT_COPY_ASYNC_END0("gpu", gpu_tracer_->CurrentName().c_str(), this);
10169 gpu_tracer_->End();
10172 void GLES2DecoderImpl::DoDrawBuffersEXT(
10173 GLsizei count, const GLenum* bufs) {
10174 if (count > static_cast<GLsizei>(group_->max_draw_buffers())) {
10175 LOCAL_SET_GL_ERROR(
10176 GL_INVALID_VALUE,
10177 "glDrawBuffersEXT", "greater than GL_MAX_DRAW_BUFFERS_EXT");
10178 return;
10181 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
10182 if (framebuffer) {
10183 for (GLsizei i = 0; i < count; ++i) {
10184 if (bufs[i] != static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i) &&
10185 bufs[i] != GL_NONE) {
10186 LOCAL_SET_GL_ERROR(
10187 GL_INVALID_OPERATION,
10188 "glDrawBuffersEXT",
10189 "bufs[i] not GL_NONE or GL_COLOR_ATTACHMENTi_EXT");
10190 return;
10193 glDrawBuffersARB(count, bufs);
10194 framebuffer->SetDrawBuffers(count, bufs);
10195 } else { // backbuffer
10196 if (count > 1 ||
10197 (bufs[0] != GL_BACK && bufs[0] != GL_NONE)) {
10198 LOCAL_SET_GL_ERROR(
10199 GL_INVALID_OPERATION,
10200 "glDrawBuffersEXT",
10201 "more than one buffer or bufs not GL_NONE or GL_BACK");
10202 return;
10204 GLenum mapped_buf = bufs[0];
10205 if (GetBackbufferServiceId() != 0 && // emulated backbuffer
10206 bufs[0] == GL_BACK) {
10207 mapped_buf = GL_COLOR_ATTACHMENT0;
10209 glDrawBuffersARB(count, &mapped_buf);
10210 group_->set_draw_buffer(bufs[0]);
10214 bool GLES2DecoderImpl::ValidateAsyncTransfer(
10215 const char* function_name,
10216 TextureRef* texture_ref,
10217 GLenum target,
10218 GLint level,
10219 const void * data) {
10220 // We only support async uploads to 2D textures for now.
10221 if (GL_TEXTURE_2D != target) {
10222 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
10223 return false;
10225 // We only support uploads to level zero for now.
10226 if (level != 0) {
10227 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "level != 0");
10228 return false;
10230 // A transfer buffer must be bound, even for asyncTexImage2D.
10231 if (data == NULL) {
10232 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, "buffer == 0");
10233 return false;
10235 // We only support one async transfer in progress.
10236 if (!texture_ref ||
10237 async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
10238 LOCAL_SET_GL_ERROR(
10239 GL_INVALID_OPERATION,
10240 function_name, "transfer already in progress");
10241 return false;
10243 return true;
10246 error::Error GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM(
10247 uint32 immediate_data_size, const cmds::AsyncTexImage2DCHROMIUM& c) {
10248 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM");
10249 GLenum target = static_cast<GLenum>(c.target);
10250 GLint level = static_cast<GLint>(c.level);
10251 GLint internal_format = static_cast<GLint>(c.internalformat);
10252 GLsizei width = static_cast<GLsizei>(c.width);
10253 GLsizei height = static_cast<GLsizei>(c.height);
10254 GLint border = static_cast<GLint>(c.border);
10255 GLenum format = static_cast<GLenum>(c.format);
10256 GLenum type = static_cast<GLenum>(c.type);
10257 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
10258 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
10259 uint32 pixels_size;
10261 // TODO(epenner): Move this and copies of this memory validation
10262 // into ValidateTexImage2D step.
10263 if (!GLES2Util::ComputeImageDataSizes(
10264 width, height, format, type, state_.unpack_alignment, &pixels_size, NULL,
10265 NULL)) {
10266 return error::kOutOfBounds;
10268 const void* pixels = NULL;
10269 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
10270 pixels = GetSharedMemoryAs<const void*>(
10271 pixels_shm_id, pixels_shm_offset, pixels_size);
10272 if (!pixels) {
10273 return error::kOutOfBounds;
10277 // All the normal glTexSubImage2D validation.
10278 if (!ValidateTexImage2D(
10279 "glAsyncTexImage2DCHROMIUM", target, level, internal_format,
10280 width, height, border, format, type, pixels, pixels_size)) {
10281 return error::kNoError;
10284 // Extra async validation.
10285 TextureRef* texture_ref = GetTextureInfoForTarget(target);
10286 Texture* texture = texture_ref->texture();
10287 if (!ValidateAsyncTransfer(
10288 "glAsyncTexImage2DCHROMIUM", texture_ref, target, level, pixels))
10289 return error::kNoError;
10291 // Don't allow async redefinition of a textures.
10292 if (texture->IsDefined()) {
10293 LOCAL_SET_GL_ERROR(
10294 GL_INVALID_OPERATION,
10295 "glAsyncTexImage2DCHROMIUM", "already defined");
10296 return error::kNoError;
10299 if (!EnsureGPUMemoryAvailable(pixels_size)) {
10300 LOCAL_SET_GL_ERROR(
10301 GL_OUT_OF_MEMORY, "glAsyncTexImage2DCHROMIUM", "out of memory");
10302 return error::kNoError;
10305 // We know the memory/size is safe, so get the real shared memory since
10306 // it might need to be duped to prevent use-after-free of the memory.
10307 gpu::Buffer buffer = GetSharedMemoryBuffer(c.pixels_shm_id);
10308 base::SharedMemory* shared_memory = buffer.shared_memory;
10309 uint32 shm_size = buffer.size;
10310 uint32 shm_data_offset = c.pixels_shm_offset;
10311 uint32 shm_data_size = pixels_size;
10313 // Setup the parameters.
10314 AsyncTexImage2DParams tex_params = {
10315 target, level, static_cast<GLenum>(internal_format),
10316 width, height, border, format, type};
10317 AsyncMemoryParams mem_params = {
10318 shared_memory, shm_size, shm_data_offset, shm_data_size};
10320 // Set up the async state if needed, and make the texture
10321 // immutable so the async state stays valid. The level info
10322 // is set up lazily when the transfer completes.
10323 AsyncPixelTransferDelegate* delegate =
10324 async_pixel_transfer_manager_->CreatePixelTransferDelegate(texture_ref,
10325 tex_params);
10326 texture->SetImmutable(true);
10328 delegate->AsyncTexImage2D(
10329 tex_params,
10330 mem_params,
10331 base::Bind(&TextureManager::SetLevelInfoFromParams,
10332 // The callback is only invoked if the transfer delegate still
10333 // exists, which implies through manager->texture_ref->state
10334 // ownership that both of these pointers are valid.
10335 base::Unretained(texture_manager()),
10336 base::Unretained(texture_ref),
10337 tex_params));
10338 return error::kNoError;
10341 error::Error GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM(
10342 uint32 immediate_data_size, const cmds::AsyncTexSubImage2DCHROMIUM& c) {
10343 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM");
10344 GLenum target = static_cast<GLenum>(c.target);
10345 GLint level = static_cast<GLint>(c.level);
10346 GLint xoffset = static_cast<GLint>(c.xoffset);
10347 GLint yoffset = static_cast<GLint>(c.yoffset);
10348 GLsizei width = static_cast<GLsizei>(c.width);
10349 GLsizei height = static_cast<GLsizei>(c.height);
10350 GLenum format = static_cast<GLenum>(c.format);
10351 GLenum type = static_cast<GLenum>(c.type);
10353 // TODO(epenner): Move this and copies of this memory validation
10354 // into ValidateTexSubImage2D step.
10355 uint32 data_size;
10356 if (!GLES2Util::ComputeImageDataSizes(
10357 width, height, format, type, state_.unpack_alignment, &data_size,
10358 NULL, NULL)) {
10359 return error::kOutOfBounds;
10361 const void* pixels = GetSharedMemoryAs<const void*>(
10362 c.data_shm_id, c.data_shm_offset, data_size);
10364 // All the normal glTexSubImage2D validation.
10365 error::Error error = error::kNoError;
10366 if (!ValidateTexSubImage2D(&error, "glAsyncTexSubImage2DCHROMIUM",
10367 target, level, xoffset, yoffset, width, height, format, type, pixels)) {
10368 return error;
10371 // Extra async validation.
10372 TextureRef* texture_ref = GetTextureInfoForTarget(target);
10373 Texture* texture = texture_ref->texture();
10374 if (!ValidateAsyncTransfer(
10375 "glAsyncTexSubImage2DCHROMIUM", texture_ref, target, level, pixels))
10376 return error::kNoError;
10378 // Guarantee async textures are always 'cleared' as follows:
10379 // - AsyncTexImage2D can not redefine an existing texture
10380 // - AsyncTexImage2D must initialize the entire image via non-null buffer.
10381 // - AsyncTexSubImage2D clears synchronously if not already cleared.
10382 // - Textures become immutable after an async call.
10383 // This way we know in all cases that an async texture is always clear.
10384 if (!texture->SafeToRenderFrom()) {
10385 if (!texture_manager()->ClearTextureLevel(this, texture_ref,
10386 target, level)) {
10387 LOCAL_SET_GL_ERROR(
10388 GL_OUT_OF_MEMORY,
10389 "glAsyncTexSubImage2DCHROMIUM", "dimensions too big");
10390 return error::kNoError;
10394 // We know the memory/size is safe, so get the real shared memory since
10395 // it might need to be duped to prevent use-after-free of the memory.
10396 gpu::Buffer buffer = GetSharedMemoryBuffer(c.data_shm_id);
10397 base::SharedMemory* shared_memory = buffer.shared_memory;
10398 uint32 shm_size = buffer.size;
10399 uint32 shm_data_offset = c.data_shm_offset;
10400 uint32 shm_data_size = data_size;
10402 // Setup the parameters.
10403 AsyncTexSubImage2DParams tex_params = {target, level, xoffset, yoffset,
10404 width, height, format, type};
10405 AsyncMemoryParams mem_params = {shared_memory, shm_size,
10406 shm_data_offset, shm_data_size};
10407 AsyncPixelTransferDelegate* delegate =
10408 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
10409 if (!delegate) {
10410 // TODO(epenner): We may want to enforce exclusive use
10411 // of async APIs in which case this should become an error,
10412 // (the texture should have been async defined).
10413 AsyncTexImage2DParams define_params = {target, level,
10414 0, 0, 0, 0, 0, 0};
10415 texture->GetLevelSize(target, level, &define_params.width,
10416 &define_params.height);
10417 texture->GetLevelType(target, level, &define_params.type,
10418 &define_params.internal_format);
10419 // Set up the async state if needed, and make the texture
10420 // immutable so the async state stays valid.
10421 delegate = async_pixel_transfer_manager_->CreatePixelTransferDelegate(
10422 texture_ref, define_params);
10423 texture->SetImmutable(true);
10426 delegate->AsyncTexSubImage2D(tex_params, mem_params);
10427 return error::kNoError;
10430 error::Error GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM(
10431 uint32 immediate_data_size, const cmds::WaitAsyncTexImage2DCHROMIUM& c) {
10432 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
10433 GLenum target = static_cast<GLenum>(c.target);
10435 if (GL_TEXTURE_2D != target) {
10436 LOCAL_SET_GL_ERROR(
10437 GL_INVALID_ENUM, "glWaitAsyncTexImage2DCHROMIUM", "target");
10438 return error::kNoError;
10440 TextureRef* texture_ref = GetTextureInfoForTarget(target);
10441 if (!texture_ref) {
10442 LOCAL_SET_GL_ERROR(
10443 GL_INVALID_OPERATION,
10444 "glWaitAsyncTexImage2DCHROMIUM", "unknown texture");
10445 return error::kNoError;
10447 AsyncPixelTransferDelegate* delegate =
10448 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
10449 if (!delegate) {
10450 LOCAL_SET_GL_ERROR(
10451 GL_INVALID_OPERATION,
10452 "glWaitAsyncTexImage2DCHROMIUM", "No async transfer started");
10453 return error::kNoError;
10455 delegate->WaitForTransferCompletion();
10456 ProcessFinishedAsyncTransfers();
10457 return error::kNoError;
10460 // Include the auto-generated part of this file. We split this because it means
10461 // we can easily edit the non-auto generated parts right here in this file
10462 // instead of having to edit some template or the code generator.
10463 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
10465 } // namespace gles2
10466 } // namespace gpu