Supervised user import: Listen for profile creation/deletion
[chromium-blink-merge.git] / gpu / command_buffer / service / gles2_cmd_decoder.cc
blob29d4d5d14e6925ecb99c98dca01097106bcc69b1
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 <cmath>
11 #include <list>
12 #include <map>
13 #include <queue>
14 #include <stack>
15 #include <string>
16 #include <vector>
18 #include "base/at_exit.h"
19 #include "base/bind.h"
20 #include "base/callback_helpers.h"
21 #include "base/command_line.h"
22 #include "base/memory/scoped_ptr.h"
23 #include "base/numerics/safe_math.h"
24 #include "base/strings/string_number_conversions.h"
25 #include "base/strings/string_split.h"
26 #include "base/trace_event/trace_event.h"
27 #include "base/trace_event/trace_event_synthetic_delay.h"
28 #include "build/build_config.h"
29 #define GLES2_GPU_SERVICE 1
30 #include "gpu/command_buffer/common/debug_marker_manager.h"
31 #include "gpu/command_buffer/common/gles2_cmd_format.h"
32 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
33 #include "gpu/command_buffer/common/id_allocator.h"
34 #include "gpu/command_buffer/common/mailbox.h"
35 #include "gpu/command_buffer/service/async_pixel_transfer_delegate.h"
36 #include "gpu/command_buffer/service/async_pixel_transfer_manager.h"
37 #include "gpu/command_buffer/service/buffer_manager.h"
38 #include "gpu/command_buffer/service/cmd_buffer_engine.h"
39 #include "gpu/command_buffer/service/context_group.h"
40 #include "gpu/command_buffer/service/context_state.h"
41 #include "gpu/command_buffer/service/error_state.h"
42 #include "gpu/command_buffer/service/feature_info.h"
43 #include "gpu/command_buffer/service/framebuffer_manager.h"
44 #include "gpu/command_buffer/service/gl_utils.h"
45 #include "gpu/command_buffer/service/gles2_cmd_clear_framebuffer.h"
46 #include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h"
47 #include "gpu/command_buffer/service/gles2_cmd_validation.h"
48 #include "gpu/command_buffer/service/gpu_state_tracer.h"
49 #include "gpu/command_buffer/service/gpu_switches.h"
50 #include "gpu/command_buffer/service/gpu_tracer.h"
51 #include "gpu/command_buffer/service/image_manager.h"
52 #include "gpu/command_buffer/service/mailbox_manager.h"
53 #include "gpu/command_buffer/service/memory_tracking.h"
54 #include "gpu/command_buffer/service/program_manager.h"
55 #include "gpu/command_buffer/service/query_manager.h"
56 #include "gpu/command_buffer/service/renderbuffer_manager.h"
57 #include "gpu/command_buffer/service/shader_manager.h"
58 #include "gpu/command_buffer/service/shader_translator.h"
59 #include "gpu/command_buffer/service/shader_translator_cache.h"
60 #include "gpu/command_buffer/service/texture_manager.h"
61 #include "gpu/command_buffer/service/valuebuffer_manager.h"
62 #include "gpu/command_buffer/service/vertex_array_manager.h"
63 #include "gpu/command_buffer/service/vertex_attrib_manager.h"
64 #include "third_party/smhasher/src/City.h"
65 #include "ui/gl/gl_fence.h"
66 #include "ui/gl/gl_image.h"
67 #include "ui/gl/gl_implementation.h"
68 #include "ui/gl/gl_surface.h"
70 #if defined(OS_MACOSX)
71 #include <IOSurface/IOSurfaceAPI.h>
72 // Note that this must be included after gl_bindings.h to avoid conflicts.
73 #include <OpenGL/CGLIOSurface.h>
74 #endif
76 #if defined(OS_WIN)
77 #include "base/win/win_util.h"
78 #endif
80 namespace gpu {
81 namespace gles2 {
83 namespace {
85 const char kOESDerivativeExtension[] = "GL_OES_standard_derivatives";
86 const char kEXTFragDepthExtension[] = "GL_EXT_frag_depth";
87 const char kEXTDrawBuffersExtension[] = "GL_EXT_draw_buffers";
88 const char kEXTShaderTextureLodExtension[] = "GL_EXT_shader_texture_lod";
90 const GLfloat kIdentityMatrix[16] = {1.0f, 0.0f, 0.0f, 0.0f,
91 0.0f, 1.0f, 0.0f, 0.0f,
92 0.0f, 0.0f, 1.0f, 0.0f,
93 0.0f, 0.0f, 0.0f, 1.0f};
95 static bool PrecisionMeetsSpecForHighpFloat(GLint rangeMin,
96 GLint rangeMax,
97 GLint precision) {
98 return (rangeMin >= 62) && (rangeMax >= 62) && (precision >= 16);
101 static void GetShaderPrecisionFormatImpl(GLenum shader_type,
102 GLenum precision_type,
103 GLint* range, GLint* precision) {
104 switch (precision_type) {
105 case GL_LOW_INT:
106 case GL_MEDIUM_INT:
107 case GL_HIGH_INT:
108 // These values are for a 32-bit twos-complement integer format.
109 range[0] = 31;
110 range[1] = 30;
111 *precision = 0;
112 break;
113 case GL_LOW_FLOAT:
114 case GL_MEDIUM_FLOAT:
115 case GL_HIGH_FLOAT:
116 // These values are for an IEEE single-precision floating-point format.
117 range[0] = 127;
118 range[1] = 127;
119 *precision = 23;
120 break;
121 default:
122 NOTREACHED();
123 break;
126 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
127 gfx::g_driver_gl.fn.glGetShaderPrecisionFormatFn) {
128 // This function is sometimes defined even though it's really just
129 // a stub, so we need to set range and precision as if it weren't
130 // defined before calling it.
131 // On Mac OS with some GPUs, calling this generates a
132 // GL_INVALID_OPERATION error. Avoid calling it on non-GLES2
133 // platforms.
134 glGetShaderPrecisionFormat(shader_type, precision_type,
135 range, precision);
137 // TODO(brianderson): Make the following official workarounds.
139 // Some drivers have bugs where they report the ranges as a negative number.
140 // Taking the absolute value here shouldn't hurt because negative numbers
141 // aren't expected anyway.
142 range[0] = abs(range[0]);
143 range[1] = abs(range[1]);
145 // If the driver reports a precision for highp float that isn't actually
146 // highp, don't pretend like it's supported because shader compilation will
147 // fail anyway.
148 if (precision_type == GL_HIGH_FLOAT &&
149 !PrecisionMeetsSpecForHighpFloat(range[0], range[1], *precision)) {
150 range[0] = 0;
151 range[1] = 0;
152 *precision = 0;
157 static gfx::OverlayTransform GetGFXOverlayTransform(GLenum plane_transform) {
158 switch (plane_transform) {
159 case GL_OVERLAY_TRANSFORM_NONE_CHROMIUM:
160 return gfx::OVERLAY_TRANSFORM_NONE;
161 case GL_OVERLAY_TRANSFORM_FLIP_HORIZONTAL_CHROMIUM:
162 return gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL;
163 case GL_OVERLAY_TRANSFORM_FLIP_VERTICAL_CHROMIUM:
164 return gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL;
165 case GL_OVERLAY_TRANSFORM_ROTATE_90_CHROMIUM:
166 return gfx::OVERLAY_TRANSFORM_ROTATE_90;
167 case GL_OVERLAY_TRANSFORM_ROTATE_180_CHROMIUM:
168 return gfx::OVERLAY_TRANSFORM_ROTATE_180;
169 case GL_OVERLAY_TRANSFORM_ROTATE_270_CHROMIUM:
170 return gfx::OVERLAY_TRANSFORM_ROTATE_270;
171 default:
172 return gfx::OVERLAY_TRANSFORM_INVALID;
176 } // namespace
178 class GLES2DecoderImpl;
180 // Local versions of the SET_GL_ERROR macros
181 #define LOCAL_SET_GL_ERROR(error, function_name, msg) \
182 ERRORSTATE_SET_GL_ERROR(state_.GetErrorState(), error, function_name, msg)
183 #define LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, value, label) \
184 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(state_.GetErrorState(), \
185 function_name, value, label)
186 #define LOCAL_SET_GL_ERROR_INVALID_PARAM(error, function_name, pname) \
187 ERRORSTATE_SET_GL_ERROR_INVALID_PARAM(state_.GetErrorState(), error, \
188 function_name, pname)
189 #define LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name) \
190 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(state_.GetErrorState(), \
191 function_name)
192 #define LOCAL_PEEK_GL_ERROR(function_name) \
193 ERRORSTATE_PEEK_GL_ERROR(state_.GetErrorState(), function_name)
194 #define LOCAL_CLEAR_REAL_GL_ERRORS(function_name) \
195 ERRORSTATE_CLEAR_REAL_GL_ERRORS(state_.GetErrorState(), function_name)
196 #define LOCAL_PERFORMANCE_WARNING(msg) \
197 PerformanceWarning(__FILE__, __LINE__, msg)
198 #define LOCAL_RENDER_WARNING(msg) \
199 RenderWarning(__FILE__, __LINE__, msg)
201 // Check that certain assumptions the code makes are true. There are places in
202 // the code where shared memory is passed direclty to GL. Example, glUniformiv,
203 // glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
204 // a few others) are 32bits. If they are not 32bits the code will have to change
205 // to call those GL functions with service side memory and then copy the results
206 // to shared memory, converting the sizes.
207 static_assert(sizeof(GLint) == sizeof(uint32), // NOLINT
208 "GLint should be the same size as uint32");
209 static_assert(sizeof(GLsizei) == sizeof(uint32), // NOLINT
210 "GLsizei should be the same size as uint32");
211 static_assert(sizeof(GLfloat) == sizeof(float), // NOLINT
212 "GLfloat should be the same size as float");
214 // TODO(kbr): the use of this anonymous namespace core dumps the
215 // linker on Mac OS X 10.6 when the symbol ordering file is used
216 // namespace {
218 // Returns the address of the first byte after a struct.
219 template <typename T>
220 const void* AddressAfterStruct(const T& pod) {
221 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
224 // Returns the address of the frst byte after the struct or NULL if size >
225 // immediate_data_size.
226 template <typename RETURN_TYPE, typename COMMAND_TYPE>
227 RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod,
228 uint32 size,
229 uint32 immediate_data_size) {
230 return (size <= immediate_data_size) ?
231 static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))) :
232 NULL;
235 // Computes the data size for certain gl commands like glUniform.
236 bool ComputeDataSize(
237 GLuint count,
238 size_t size,
239 unsigned int elements_per_unit,
240 uint32* dst) {
241 uint32 value;
242 if (!SafeMultiplyUint32(count, size, &value)) {
243 return false;
245 if (!SafeMultiplyUint32(value, elements_per_unit, &value)) {
246 return false;
248 *dst = value;
249 return true;
252 // Return true if a character belongs to the ASCII subset as defined in
253 // GLSL ES 1.0 spec section 3.1.
254 static bool CharacterIsValidForGLES(unsigned char c) {
255 // Printing characters are valid except " $ ` @ \ ' DEL.
256 if (c >= 32 && c <= 126 &&
257 c != '"' &&
258 c != '$' &&
259 c != '`' &&
260 c != '@' &&
261 c != '\\' &&
262 c != '\'') {
263 return true;
265 // Horizontal tab, line feed, vertical tab, form feed, carriage return
266 // are also valid.
267 if (c >= 9 && c <= 13) {
268 return true;
271 return false;
274 static bool StringIsValidForGLES(const char* str) {
275 for (; *str; ++str) {
276 if (!CharacterIsValidForGLES(*str)) {
277 return false;
280 return true;
283 // This class prevents any GL errors that occur when it is in scope from
284 // being reported to the client.
285 class ScopedGLErrorSuppressor {
286 public:
287 explicit ScopedGLErrorSuppressor(
288 const char* function_name, ErrorState* error_state);
289 ~ScopedGLErrorSuppressor();
290 private:
291 const char* function_name_;
292 ErrorState* error_state_;
293 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor);
296 // Temporarily changes a decoder's bound texture and restore it when this
297 // object goes out of scope. Also temporarily switches to using active texture
298 // unit zero in case the client has changed that to something invalid.
299 class ScopedTextureBinder {
300 public:
301 explicit ScopedTextureBinder(ContextState* state, GLuint id, GLenum target);
302 ~ScopedTextureBinder();
304 private:
305 ContextState* state_;
306 GLenum target_;
307 DISALLOW_COPY_AND_ASSIGN(ScopedTextureBinder);
310 // Temporarily changes a decoder's bound render buffer and restore it when this
311 // object goes out of scope.
312 class ScopedRenderBufferBinder {
313 public:
314 explicit ScopedRenderBufferBinder(ContextState* state, GLuint id);
315 ~ScopedRenderBufferBinder();
317 private:
318 ContextState* state_;
319 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder);
322 // Temporarily changes a decoder's bound frame buffer and restore it when this
323 // object goes out of scope.
324 class ScopedFrameBufferBinder {
325 public:
326 explicit ScopedFrameBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
327 ~ScopedFrameBufferBinder();
329 private:
330 GLES2DecoderImpl* decoder_;
331 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder);
334 // Temporarily changes a decoder's bound frame buffer to a resolved version of
335 // the multisampled offscreen render buffer if that buffer is multisampled, and,
336 // if it is bound or enforce_internal_framebuffer is true. If internal is
337 // true, the resolved framebuffer is not visible to the parent.
338 class ScopedResolvedFrameBufferBinder {
339 public:
340 explicit ScopedResolvedFrameBufferBinder(GLES2DecoderImpl* decoder,
341 bool enforce_internal_framebuffer,
342 bool internal);
343 ~ScopedResolvedFrameBufferBinder();
345 private:
346 GLES2DecoderImpl* decoder_;
347 bool resolve_and_bind_;
348 DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder);
351 class ScopedModifyPixels {
352 public:
353 explicit ScopedModifyPixels(TextureRef* ref);
354 ~ScopedModifyPixels();
356 private:
357 TextureRef* ref_;
360 ScopedModifyPixels::ScopedModifyPixels(TextureRef* ref) : ref_(ref) {
361 if (ref_)
362 ref_->texture()->OnWillModifyPixels();
365 ScopedModifyPixels::~ScopedModifyPixels() {
366 if (ref_)
367 ref_->texture()->OnDidModifyPixels();
370 class ScopedRenderTo {
371 public:
372 explicit ScopedRenderTo(Framebuffer* framebuffer);
373 ~ScopedRenderTo();
375 private:
376 const Framebuffer* framebuffer_;
379 ScopedRenderTo::ScopedRenderTo(Framebuffer* framebuffer)
380 : framebuffer_(framebuffer) {
381 if (framebuffer)
382 framebuffer_->OnWillRenderTo();
385 ScopedRenderTo::~ScopedRenderTo() {
386 if (framebuffer_)
387 framebuffer_->OnDidRenderTo();
390 // Encapsulates an OpenGL texture.
391 class BackTexture {
392 public:
393 explicit BackTexture(MemoryTracker* memory_tracker, ContextState* state);
394 ~BackTexture();
396 // Create a new render texture.
397 void Create();
399 // Set the initial size and format of a render texture or resize it.
400 bool AllocateStorage(const gfx::Size& size, GLenum format, bool zero);
402 // Copy the contents of the currently bound frame buffer.
403 void Copy(const gfx::Size& size, GLenum format);
405 // Destroy the render texture. This must be explicitly called before
406 // destroying this object.
407 void Destroy();
409 // Invalidate the texture. This can be used when a context is lost and it is
410 // not possible to make it current in order to free the resource.
411 void Invalidate();
413 GLuint id() const {
414 return id_;
417 gfx::Size size() const {
418 return size_;
421 private:
422 MemoryTypeTracker memory_tracker_;
423 ContextState* state_;
424 size_t bytes_allocated_;
425 GLuint id_;
426 gfx::Size size_;
427 DISALLOW_COPY_AND_ASSIGN(BackTexture);
430 // Encapsulates an OpenGL render buffer of any format.
431 class BackRenderbuffer {
432 public:
433 explicit BackRenderbuffer(
434 RenderbufferManager* renderbuffer_manager,
435 MemoryTracker* memory_tracker,
436 ContextState* state);
437 ~BackRenderbuffer();
439 // Create a new render buffer.
440 void Create();
442 // Set the initial size and format of a render buffer or resize it.
443 bool AllocateStorage(const FeatureInfo* feature_info,
444 const gfx::Size& size,
445 GLenum format,
446 GLsizei samples);
448 // Destroy the render buffer. This must be explicitly called before destroying
449 // this object.
450 void Destroy();
452 // Invalidate the render buffer. This can be used when a context is lost and
453 // it is not possible to make it current in order to free the resource.
454 void Invalidate();
456 GLuint id() const {
457 return id_;
460 private:
461 RenderbufferManager* renderbuffer_manager_;
462 MemoryTypeTracker memory_tracker_;
463 ContextState* state_;
464 size_t bytes_allocated_;
465 GLuint id_;
466 DISALLOW_COPY_AND_ASSIGN(BackRenderbuffer);
469 // Encapsulates an OpenGL frame buffer.
470 class BackFramebuffer {
471 public:
472 explicit BackFramebuffer(GLES2DecoderImpl* decoder);
473 ~BackFramebuffer();
475 // Create a new frame buffer.
476 void Create();
478 // Attach a color render buffer to a frame buffer.
479 void AttachRenderTexture(BackTexture* texture);
481 // Attach a render buffer to a frame buffer. Note that this unbinds any
482 // currently bound frame buffer.
483 void AttachRenderBuffer(GLenum target, BackRenderbuffer* render_buffer);
485 // Destroy the frame buffer. This must be explicitly called before destroying
486 // this object.
487 void Destroy();
489 // Invalidate the frame buffer. This can be used when a context is lost and it
490 // is not possible to make it current in order to free the resource.
491 void Invalidate();
493 // See glCheckFramebufferStatusEXT.
494 GLenum CheckStatus();
496 GLuint id() const {
497 return id_;
500 private:
501 GLES2DecoderImpl* decoder_;
502 GLuint id_;
503 DISALLOW_COPY_AND_ASSIGN(BackFramebuffer);
506 struct FenceCallback {
507 FenceCallback()
508 : fence(gfx::GLFence::Create()) {
509 DCHECK(fence);
511 std::vector<base::Closure> callbacks;
512 scoped_ptr<gfx::GLFence> fence;
515 class AsyncUploadTokenCompletionObserver
516 : public AsyncPixelTransferCompletionObserver {
517 public:
518 explicit AsyncUploadTokenCompletionObserver(uint32 async_upload_token)
519 : async_upload_token_(async_upload_token) {
522 void DidComplete(const AsyncMemoryParams& mem_params) override {
523 DCHECK(mem_params.buffer().get());
524 void* data = mem_params.GetDataAddress();
525 AsyncUploadSync* sync = static_cast<AsyncUploadSync*>(data);
526 sync->SetAsyncUploadToken(async_upload_token_);
529 private:
530 ~AsyncUploadTokenCompletionObserver() override {}
532 uint32 async_upload_token_;
534 DISALLOW_COPY_AND_ASSIGN(AsyncUploadTokenCompletionObserver);
537 // } // anonymous namespace.
539 // static
540 const unsigned int GLES2Decoder::kDefaultStencilMask =
541 static_cast<unsigned int>(-1);
543 bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id,
544 uint32* service_texture_id) {
545 return false;
548 GLES2Decoder::GLES2Decoder()
549 : initialized_(false),
550 debug_(false),
551 log_commands_(false),
552 unsafe_es3_apis_enabled_(false) {
555 GLES2Decoder::~GLES2Decoder() {
558 void GLES2Decoder::BeginDecoding() {}
560 void GLES2Decoder::EndDecoding() {}
562 // This class implements GLES2Decoder so we don't have to expose all the GLES2
563 // cmd stuff to outside this class.
564 class GLES2DecoderImpl : public GLES2Decoder,
565 public FramebufferManager::TextureDetachObserver,
566 public ErrorStateClient {
567 public:
568 explicit GLES2DecoderImpl(ContextGroup* group);
569 ~GLES2DecoderImpl() override;
571 // Overridden from AsyncAPIInterface.
572 Error DoCommand(unsigned int command,
573 unsigned int arg_count,
574 const void* args) override;
576 error::Error DoCommands(unsigned int num_commands,
577 const void* buffer,
578 int num_entries,
579 int* entries_processed) override;
581 template <bool DebugImpl>
582 error::Error DoCommandsImpl(unsigned int num_commands,
583 const void* buffer,
584 int num_entries,
585 int* entries_processed);
587 // Overridden from AsyncAPIInterface.
588 const char* GetCommandName(unsigned int command_id) const override;
590 // Overridden from GLES2Decoder.
591 bool Initialize(const scoped_refptr<gfx::GLSurface>& surface,
592 const scoped_refptr<gfx::GLContext>& context,
593 bool offscreen,
594 const gfx::Size& offscreen_size,
595 const DisallowedFeatures& disallowed_features,
596 const std::vector<int32>& attribs) override;
597 void Destroy(bool have_context) override;
598 void SetSurface(const scoped_refptr<gfx::GLSurface>& surface) override;
599 void ProduceFrontBuffer(const Mailbox& mailbox) override;
600 bool ResizeOffscreenFrameBuffer(const gfx::Size& size) override;
601 void UpdateParentTextureInfo();
602 bool MakeCurrent() override;
603 GLES2Util* GetGLES2Util() override { return &util_; }
604 gfx::GLContext* GetGLContext() override { return context_.get(); }
605 ContextGroup* GetContextGroup() override { return group_.get(); }
606 Capabilities GetCapabilities() override;
607 void RestoreState(const ContextState* prev_state) override;
609 void RestoreActiveTexture() const override { state_.RestoreActiveTexture(); }
610 void RestoreAllTextureUnitBindings(
611 const ContextState* prev_state) const override {
612 state_.RestoreAllTextureUnitBindings(prev_state);
614 void RestoreActiveTextureUnitBinding(unsigned int target) const override {
615 state_.RestoreActiveTextureUnitBinding(target);
617 void RestoreBufferBindings() const override {
618 state_.RestoreBufferBindings();
620 void RestoreGlobalState() const override { state_.RestoreGlobalState(NULL); }
621 void RestoreProgramBindings() const override {
622 state_.RestoreProgramBindings();
624 void RestoreTextureUnitBindings(unsigned unit) const override {
625 state_.RestoreTextureUnitBindings(unit, NULL);
627 void RestoreFramebufferBindings() const override;
628 void RestoreRenderbufferBindings() override;
629 void RestoreTextureState(unsigned service_id) const override;
631 void ClearAllAttributes() const override;
632 void RestoreAllAttributes() const override;
634 QueryManager* GetQueryManager() override { return query_manager_.get(); }
635 VertexArrayManager* GetVertexArrayManager() override {
636 return vertex_array_manager_.get();
638 ImageManager* GetImageManager() override { return image_manager_.get(); }
640 ValuebufferManager* GetValuebufferManager() override {
641 return valuebuffer_manager();
644 bool ProcessPendingQueries(bool did_finish) override;
646 bool HasMoreIdleWork() override;
647 void PerformIdleWork() override;
649 void WaitForReadPixels(base::Closure callback) override;
651 void SetResizeCallback(
652 const base::Callback<void(gfx::Size, float)>& callback) override;
654 Logger* GetLogger() override;
656 void BeginDecoding() override;
657 void EndDecoding() override;
659 ErrorState* GetErrorState() override;
660 const ContextState* GetContextState() override { return &state_; }
662 void SetShaderCacheCallback(const ShaderCacheCallback& callback) override;
663 void SetWaitSyncPointCallback(const WaitSyncPointCallback& callback) override;
665 AsyncPixelTransferManager* GetAsyncPixelTransferManager() override;
666 void ResetAsyncPixelTransferManagerForTest() override;
667 void SetAsyncPixelTransferManagerForTest(
668 AsyncPixelTransferManager* manager) override;
669 void SetIgnoreCachedStateForTest(bool ignore) override;
670 void ProcessFinishedAsyncTransfers();
672 bool GetServiceTextureId(uint32 client_texture_id,
673 uint32* service_texture_id) override;
675 uint32 GetTextureUploadCount() override;
676 base::TimeDelta GetTotalTextureUploadTime() override;
677 base::TimeDelta GetTotalProcessingCommandsTime() override;
678 void AddProcessingCommandsTime(base::TimeDelta) override;
680 // Restores the current state to the user's settings.
681 void RestoreCurrentFramebufferBindings();
683 // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
684 void ApplyDirtyState();
686 // These check the state of the currently bound framebuffer or the
687 // backbuffer if no framebuffer is bound.
688 // If all_draw_buffers is false, only check with COLOR_ATTACHMENT0, otherwise
689 // check with all attached and enabled color attachments.
690 bool BoundFramebufferHasColorAttachmentWithAlpha(bool all_draw_buffers);
691 bool BoundFramebufferHasDepthAttachment();
692 bool BoundFramebufferHasStencilAttachment();
694 error::ContextLostReason GetContextLostReason() override;
696 // Overridden from FramebufferManager::TextureDetachObserver:
697 void OnTextureRefDetachedFromFramebuffer(TextureRef* texture) override;
699 // Overriden from ErrorStateClient.
700 void OnContextLostError() override;
701 void OnOutOfMemoryError() override;
703 // Ensure Renderbuffer corresponding to last DoBindRenderbuffer() is bound.
704 void EnsureRenderbufferBound();
706 // Helpers to facilitate calling into compatible extensions.
707 static void RenderbufferStorageMultisampleHelper(
708 const FeatureInfo* feature_info,
709 GLenum target,
710 GLsizei samples,
711 GLenum internal_format,
712 GLsizei width,
713 GLsizei height);
715 void BlitFramebufferHelper(GLint srcX0,
716 GLint srcY0,
717 GLint srcX1,
718 GLint srcY1,
719 GLint dstX0,
720 GLint dstY0,
721 GLint dstX1,
722 GLint dstY1,
723 GLbitfield mask,
724 GLenum filter);
726 private:
727 friend class ScopedFrameBufferBinder;
728 friend class ScopedResolvedFrameBufferBinder;
729 friend class BackFramebuffer;
731 // Initialize or re-initialize the shader translator.
732 bool InitializeShaderTranslator();
734 void UpdateCapabilities();
736 // Helpers for the glGen and glDelete functions.
737 bool GenTexturesHelper(GLsizei n, const GLuint* client_ids);
738 void DeleteTexturesHelper(GLsizei n, const GLuint* client_ids);
739 bool GenBuffersHelper(GLsizei n, const GLuint* client_ids);
740 void DeleteBuffersHelper(GLsizei n, const GLuint* client_ids);
741 bool GenFramebuffersHelper(GLsizei n, const GLuint* client_ids);
742 void DeleteFramebuffersHelper(GLsizei n, const GLuint* client_ids);
743 bool GenRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
744 void DeleteRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
745 bool GenValuebuffersCHROMIUMHelper(GLsizei n, const GLuint* client_ids);
746 void DeleteValuebuffersCHROMIUMHelper(GLsizei n, const GLuint* client_ids);
747 bool GenQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
748 void DeleteQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
749 bool GenVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
750 void DeleteVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
752 // Helper for async upload token completion notification callback.
753 base::Closure AsyncUploadTokenCompletionClosure(uint32 async_upload_token,
754 uint32 sync_data_shm_id,
755 uint32 sync_data_shm_offset);
759 // Workarounds
760 void OnFboChanged() const;
761 void OnUseFramebuffer() const;
763 error::ContextLostReason GetContextLostReasonFromResetStatus(
764 GLenum reset_status) const;
766 // TODO(gman): Cache these pointers?
767 BufferManager* buffer_manager() {
768 return group_->buffer_manager();
771 RenderbufferManager* renderbuffer_manager() {
772 return group_->renderbuffer_manager();
775 FramebufferManager* framebuffer_manager() {
776 return group_->framebuffer_manager();
779 ValuebufferManager* valuebuffer_manager() {
780 return group_->valuebuffer_manager();
783 ProgramManager* program_manager() {
784 return group_->program_manager();
787 ShaderManager* shader_manager() {
788 return group_->shader_manager();
791 ShaderTranslatorCache* shader_translator_cache() {
792 return group_->shader_translator_cache();
795 const TextureManager* texture_manager() const {
796 return group_->texture_manager();
799 TextureManager* texture_manager() {
800 return group_->texture_manager();
803 MailboxManager* mailbox_manager() {
804 return group_->mailbox_manager();
807 ImageManager* image_manager() { return image_manager_.get(); }
809 VertexArrayManager* vertex_array_manager() {
810 return vertex_array_manager_.get();
813 MemoryTracker* memory_tracker() {
814 return group_->memory_tracker();
817 bool EnsureGPUMemoryAvailable(size_t estimated_size) {
818 MemoryTracker* tracker = memory_tracker();
819 if (tracker) {
820 return tracker->EnsureGPUMemoryAvailable(estimated_size);
822 return true;
825 bool IsOffscreenBufferMultisampled() const {
826 return offscreen_target_samples_ > 1;
829 // Creates a Texture for the given texture.
830 TextureRef* CreateTexture(
831 GLuint client_id, GLuint service_id) {
832 return texture_manager()->CreateTexture(client_id, service_id);
835 // Gets the texture info for the given texture. Returns NULL if none exists.
836 TextureRef* GetTexture(GLuint client_id) const {
837 return texture_manager()->GetTexture(client_id);
840 // Deletes the texture info for the given texture.
841 void RemoveTexture(GLuint client_id) {
842 texture_manager()->RemoveTexture(client_id);
845 // Get the size (in pixels) of the currently bound frame buffer (either FBO
846 // or regular back buffer).
847 gfx::Size GetBoundReadFrameBufferSize();
849 // Get the format of the currently bound frame buffer (either FBO or regular
850 // back buffer)
851 GLenum GetBoundReadFrameBufferTextureType();
852 GLenum GetBoundReadFrameBufferInternalFormat();
853 GLenum GetBoundDrawFrameBufferInternalFormat();
855 // Wrapper for CompressedTexImage2D commands.
856 error::Error DoCompressedTexImage2D(
857 GLenum target,
858 GLint level,
859 GLenum internal_format,
860 GLsizei width,
861 GLsizei height,
862 GLint border,
863 GLsizei image_size,
864 const void* data);
866 // Wrapper for CompressedTexImage3D commands.
867 error::Error DoCompressedTexImage3D(
868 GLenum target,
869 GLint level,
870 GLenum internal_format,
871 GLsizei width,
872 GLsizei height,
873 GLsizei depth,
874 GLint border,
875 GLsizei image_size,
876 const void* data);
878 // Wrapper for CompressedTexSubImage2D.
879 void DoCompressedTexSubImage2D(
880 GLenum target,
881 GLint level,
882 GLint xoffset,
883 GLint yoffset,
884 GLsizei width,
885 GLsizei height,
886 GLenum format,
887 GLsizei imageSize,
888 const void * data);
890 // Wrapper for CopyTexImage2D.
891 void DoCopyTexImage2D(
892 GLenum target,
893 GLint level,
894 GLenum internal_format,
895 GLint x,
896 GLint y,
897 GLsizei width,
898 GLsizei height,
899 GLint border);
901 // Wrapper for SwapBuffers.
902 void DoSwapBuffers();
904 // Wrapper for SwapInterval.
905 void DoSwapInterval(int interval);
907 // Wrapper for CopyTexSubImage2D.
908 void DoCopyTexSubImage2D(
909 GLenum target,
910 GLint level,
911 GLint xoffset,
912 GLint yoffset,
913 GLint x,
914 GLint y,
915 GLsizei width,
916 GLsizei height);
918 // Validation for TexSubImage2D.
919 bool ValidateTexSubImage2D(
920 error::Error* error,
921 const char* function_name,
922 GLenum target,
923 GLint level,
924 GLint xoffset,
925 GLint yoffset,
926 GLsizei width,
927 GLsizei height,
928 GLenum format,
929 GLenum type,
930 const void * data);
932 // Wrapper for TexSubImage2D.
933 error::Error DoTexSubImage2D(
934 GLenum target,
935 GLint level,
936 GLint xoffset,
937 GLint yoffset,
938 GLsizei width,
939 GLsizei height,
940 GLenum format,
941 GLenum type,
942 const void * data);
944 // Extra validation for async tex(Sub)Image2D.
945 bool ValidateAsyncTransfer(
946 const char* function_name,
947 TextureRef* texture_ref,
948 GLenum target,
949 GLint level,
950 const void * data);
952 // Wrapper for TexImageIOSurface2DCHROMIUM.
953 void DoTexImageIOSurface2DCHROMIUM(
954 GLenum target,
955 GLsizei width,
956 GLsizei height,
957 GLuint io_surface_id,
958 GLuint plane);
960 void DoCopyTextureCHROMIUM(GLenum target,
961 GLuint source_id,
962 GLuint dest_id,
963 GLenum internal_format,
964 GLenum dest_type);
966 void DoCopySubTextureCHROMIUM(GLenum target,
967 GLuint source_id,
968 GLuint dest_id,
969 GLint xoffset,
970 GLint yoffset);
972 // Wrapper for TexStorage2DEXT.
973 void DoTexStorage2DEXT(
974 GLenum target,
975 GLint levels,
976 GLenum internal_format,
977 GLsizei width,
978 GLsizei height);
980 void DoProduceTextureCHROMIUM(GLenum target, const GLbyte* key);
981 void DoProduceTextureDirectCHROMIUM(GLuint texture, GLenum target,
982 const GLbyte* key);
983 void ProduceTextureRef(std::string func_name, TextureRef* texture_ref,
984 GLenum target, const GLbyte* data);
986 void EnsureTextureForClientId(GLenum target, GLuint client_id);
987 void DoConsumeTextureCHROMIUM(GLenum target, const GLbyte* key);
988 void DoCreateAndConsumeTextureCHROMIUM(GLenum target, const GLbyte* key,
989 GLuint client_id);
991 bool DoIsValuebufferCHROMIUM(GLuint client_id);
992 void DoBindValueBufferCHROMIUM(GLenum target, GLuint valuebuffer);
993 void DoSubscribeValueCHROMIUM(GLenum target, GLenum subscription);
994 void DoPopulateSubscribedValuesCHROMIUM(GLenum target);
995 void DoUniformValueBufferCHROMIUM(GLint location,
996 GLenum target,
997 GLenum subscription);
999 void DoBindTexImage2DCHROMIUM(
1000 GLenum target,
1001 GLint image_id);
1002 void DoReleaseTexImage2DCHROMIUM(
1003 GLenum target,
1004 GLint image_id);
1006 void DoTraceEndCHROMIUM(void);
1008 void DoDrawBuffersEXT(GLsizei count, const GLenum* bufs);
1010 void DoLoseContextCHROMIUM(GLenum current, GLenum other);
1012 void DoMatrixLoadfCHROMIUM(GLenum matrix_mode, const GLfloat* matrix);
1013 void DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode);
1015 // Creates a Program for the given program.
1016 Program* CreateProgram(
1017 GLuint client_id, GLuint service_id) {
1018 return program_manager()->CreateProgram(client_id, service_id);
1021 // Gets the program info for the given program. Returns NULL if none exists.
1022 Program* GetProgram(GLuint client_id) {
1023 return program_manager()->GetProgram(client_id);
1026 #if defined(NDEBUG)
1027 void LogClientServiceMapping(
1028 const char* /* function_name */,
1029 GLuint /* client_id */,
1030 GLuint /* service_id */) {
1032 template<typename T>
1033 void LogClientServiceForInfo(
1034 T* /* info */, GLuint /* client_id */, const char* /* function_name */) {
1036 #else
1037 void LogClientServiceMapping(
1038 const char* function_name, GLuint client_id, GLuint service_id) {
1039 if (service_logging_) {
1040 VLOG(1) << "[" << logger_.GetLogPrefix() << "] " << function_name
1041 << ": client_id = " << client_id
1042 << ", service_id = " << service_id;
1045 template<typename T>
1046 void LogClientServiceForInfo(
1047 T* info, GLuint client_id, const char* function_name) {
1048 if (info) {
1049 LogClientServiceMapping(function_name, client_id, info->service_id());
1052 #endif
1054 // Gets the program info for the given program. If it's not a program
1055 // generates a GL error. Returns NULL if not program.
1056 Program* GetProgramInfoNotShader(
1057 GLuint client_id, const char* function_name) {
1058 Program* program = GetProgram(client_id);
1059 if (!program) {
1060 if (GetShader(client_id)) {
1061 LOCAL_SET_GL_ERROR(
1062 GL_INVALID_OPERATION, function_name, "shader passed for program");
1063 } else {
1064 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "unknown program");
1067 LogClientServiceForInfo(program, client_id, function_name);
1068 return program;
1072 // Creates a Shader for the given shader.
1073 Shader* CreateShader(
1074 GLuint client_id,
1075 GLuint service_id,
1076 GLenum shader_type) {
1077 return shader_manager()->CreateShader(
1078 client_id, service_id, shader_type);
1081 // Gets the shader info for the given shader. Returns NULL if none exists.
1082 Shader* GetShader(GLuint client_id) {
1083 return shader_manager()->GetShader(client_id);
1086 // Gets the shader info for the given shader. If it's not a shader generates a
1087 // GL error. Returns NULL if not shader.
1088 Shader* GetShaderInfoNotProgram(
1089 GLuint client_id, const char* function_name) {
1090 Shader* shader = GetShader(client_id);
1091 if (!shader) {
1092 if (GetProgram(client_id)) {
1093 LOCAL_SET_GL_ERROR(
1094 GL_INVALID_OPERATION, function_name, "program passed for shader");
1095 } else {
1096 LOCAL_SET_GL_ERROR(
1097 GL_INVALID_VALUE, function_name, "unknown shader");
1100 LogClientServiceForInfo(shader, client_id, function_name);
1101 return shader;
1104 // Creates a buffer info for the given buffer.
1105 void CreateBuffer(GLuint client_id, GLuint service_id) {
1106 return buffer_manager()->CreateBuffer(client_id, service_id);
1109 // Gets the buffer info for the given buffer.
1110 Buffer* GetBuffer(GLuint client_id) {
1111 Buffer* buffer = buffer_manager()->GetBuffer(client_id);
1112 return buffer;
1115 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
1116 // on glDeleteBuffers so we can make sure the user does not try to render
1117 // with deleted buffers.
1118 void RemoveBuffer(GLuint client_id);
1120 // Creates a framebuffer info for the given framebuffer.
1121 void CreateFramebuffer(GLuint client_id, GLuint service_id) {
1122 return framebuffer_manager()->CreateFramebuffer(client_id, service_id);
1125 // Gets the framebuffer info for the given framebuffer.
1126 Framebuffer* GetFramebuffer(GLuint client_id) {
1127 return framebuffer_manager()->GetFramebuffer(client_id);
1130 // Removes the framebuffer info for the given framebuffer.
1131 void RemoveFramebuffer(GLuint client_id) {
1132 framebuffer_manager()->RemoveFramebuffer(client_id);
1135 // Creates a renderbuffer info for the given renderbuffer.
1136 void CreateRenderbuffer(GLuint client_id, GLuint service_id) {
1137 return renderbuffer_manager()->CreateRenderbuffer(
1138 client_id, service_id);
1141 // Gets the renderbuffer info for the given renderbuffer.
1142 Renderbuffer* GetRenderbuffer(GLuint client_id) {
1143 return renderbuffer_manager()->GetRenderbuffer(client_id);
1146 // Removes the renderbuffer info for the given renderbuffer.
1147 void RemoveRenderbuffer(GLuint client_id) {
1148 renderbuffer_manager()->RemoveRenderbuffer(client_id);
1151 // Creates a valuebuffer info for the given valuebuffer.
1152 void CreateValuebuffer(GLuint client_id) {
1153 return valuebuffer_manager()->CreateValuebuffer(client_id);
1156 // Gets the valuebuffer info for a given valuebuffer.
1157 Valuebuffer* GetValuebuffer(GLuint client_id) {
1158 return valuebuffer_manager()->GetValuebuffer(client_id);
1161 // Removes the valuebuffer info for the given valuebuffer.
1162 void RemoveValuebuffer(GLuint client_id) {
1163 valuebuffer_manager()->RemoveValuebuffer(client_id);
1166 // Gets the vertex attrib manager for the given vertex array.
1167 VertexAttribManager* GetVertexAttribManager(GLuint client_id) {
1168 VertexAttribManager* info =
1169 vertex_array_manager()->GetVertexAttribManager(client_id);
1170 return info;
1173 // Removes the vertex attrib manager for the given vertex array.
1174 void RemoveVertexAttribManager(GLuint client_id) {
1175 vertex_array_manager()->RemoveVertexAttribManager(client_id);
1178 // Creates a vertex attrib manager for the given vertex array.
1179 scoped_refptr<VertexAttribManager> CreateVertexAttribManager(
1180 GLuint client_id,
1181 GLuint service_id,
1182 bool client_visible) {
1183 return vertex_array_manager()->CreateVertexAttribManager(
1184 client_id, service_id, group_->max_vertex_attribs(), client_visible);
1187 void DoBindAttribLocation(GLuint client_id, GLuint index, const char* name);
1188 void DoBindUniformLocationCHROMIUM(
1189 GLuint client_id, GLint location, const char* name);
1191 error::Error GetAttribLocationHelper(
1192 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1193 const std::string& name_str);
1195 error::Error GetUniformLocationHelper(
1196 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1197 const std::string& name_str);
1199 error::Error GetFragDataLocationHelper(
1200 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1201 const std::string& name_str);
1203 // Wrapper for glShaderSource.
1204 void DoShaderSource(
1205 GLuint client_id, GLsizei count, const char** data, const GLint* length);
1207 // Wrapper for glTransformFeedbackVaryings.
1208 void DoTransformFeedbackVaryings(
1209 GLuint client_program_id, GLsizei count, const char* const* varyings,
1210 GLenum buffer_mode);
1212 // Clear any textures used by the current program.
1213 bool ClearUnclearedTextures();
1215 // Clears any uncleared attachments attached to the given frame buffer.
1216 // Returns false if there was a generated GL error.
1217 void ClearUnclearedAttachments(GLenum target, Framebuffer* framebuffer);
1219 // overridden from GLES2Decoder
1220 bool ClearLevel(Texture* texture,
1221 unsigned target,
1222 int level,
1223 unsigned internal_format,
1224 unsigned format,
1225 unsigned type,
1226 int width,
1227 int height,
1228 bool is_texture_immutable) override;
1230 // Restore all GL state that affects clearing.
1231 void RestoreClearState();
1233 // Remembers the state of some capabilities.
1234 // Returns: true if glEnable/glDisable should actually be called.
1235 bool SetCapabilityState(GLenum cap, bool enabled);
1237 // Check that the currently bound framebuffers are valid.
1238 // Generates GL error if not.
1239 bool CheckBoundFramebuffersValid(const char* func_name);
1241 // Check that the currently bound read framebuffer has a color image
1242 // attached. Generates GL error if not.
1243 bool CheckBoundReadFramebufferColorAttachment(const char* func_name);
1245 // Check that the currently bound read framebuffer's color image
1246 // isn't the target texture of the glCopyTex{Sub}Image2D.
1247 bool FormsTextureCopyingFeedbackLoop(TextureRef* texture, GLint level);
1249 // Check if a framebuffer meets our requirements.
1250 bool CheckFramebufferValid(
1251 Framebuffer* framebuffer,
1252 GLenum target,
1253 const char* func_name);
1255 // Check if the current valuebuffer exists and is valid. If not generates
1256 // the appropriate GL error. Returns true if the current valuebuffer is in
1257 // a usable state.
1258 bool CheckCurrentValuebuffer(const char* function_name);
1260 // Check if the current valuebuffer exists and is valiud and that the
1261 // value buffer is actually subscribed to the given subscription
1262 bool CheckCurrentValuebufferForSubscription(GLenum subscription,
1263 const char* function_name);
1265 // Check if the location can be used for the given subscription target. If not
1266 // generates the appropriate GL error. Returns true if the location is usable
1267 bool CheckSubscriptionTarget(GLint location,
1268 GLenum subscription,
1269 const char* function_name);
1271 // Checks if the current program exists and is valid. If not generates the
1272 // appropriate GL error. Returns true if the current program is in a usable
1273 // state.
1274 bool CheckCurrentProgram(const char* function_name);
1276 // Checks if the current program exists and is valid and that location is not
1277 // -1. If the current program is not valid generates the appropriate GL
1278 // error. Returns true if the current program is in a usable state and
1279 // location is not -1.
1280 bool CheckCurrentProgramForUniform(GLint location, const char* function_name);
1282 // Checks if the current program samples a texture that is also the color
1283 // image of the current bound framebuffer, i.e., the source and destination
1284 // of the draw operation are the same.
1285 bool CheckDrawingFeedbackLoops();
1287 // Checks if |api_type| is valid for the given uniform
1288 // If the api type is not valid generates the appropriate GL
1289 // error. Returns true if |api_type| is valid for the uniform
1290 bool CheckUniformForApiType(const Program::UniformInfo* info,
1291 const char* function_name,
1292 Program::UniformApiType api_type);
1294 // Gets the type of a uniform for a location in the current program. Sets GL
1295 // errors if the current program is not valid. Returns true if the current
1296 // program is valid and the location exists. Adjusts count so it
1297 // does not overflow the uniform.
1298 bool PrepForSetUniformByLocation(GLint fake_location,
1299 const char* function_name,
1300 Program::UniformApiType api_type,
1301 GLint* real_location,
1302 GLenum* type,
1303 GLsizei* count);
1305 // Gets the service id for any simulated backbuffer fbo.
1306 GLuint GetBackbufferServiceId() const;
1308 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
1309 bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
1311 // Helper for glGetVertexAttrib
1312 void GetVertexAttribHelper(
1313 const VertexAttrib* attrib, GLenum pname, GLint* param);
1315 // Wrapper for glActiveTexture
1316 void DoActiveTexture(GLenum texture_unit);
1318 // Wrapper for glAttachShader
1319 void DoAttachShader(GLuint client_program_id, GLint client_shader_id);
1321 // Wrapper for glBindBuffer since we need to track the current targets.
1322 void DoBindBuffer(GLenum target, GLuint buffer);
1324 // Wrapper for glBindFramebuffer since we need to track the current targets.
1325 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
1327 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1328 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
1330 // Wrapper for glBindTexture since we need to track the current targets.
1331 void DoBindTexture(GLenum target, GLuint texture);
1333 // Wrapper for glBindVertexArrayOES
1334 void DoBindVertexArrayOES(GLuint array);
1335 void EmulateVertexArrayState();
1337 // Wrapper for glBlitFramebufferCHROMIUM.
1338 void DoBlitFramebufferCHROMIUM(
1339 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
1340 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
1341 GLbitfield mask, GLenum filter);
1343 // Wrapper for glBufferSubData.
1344 void DoBufferSubData(
1345 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
1347 // Wrapper for glCheckFramebufferStatus
1348 GLenum DoCheckFramebufferStatus(GLenum target);
1350 // Wrapper for glClear
1351 error::Error DoClear(GLbitfield mask);
1353 // Wrappers for various state.
1354 void DoDepthRangef(GLclampf znear, GLclampf zfar);
1355 void DoSampleCoverage(GLclampf value, GLboolean invert);
1357 // Wrapper for glCompileShader.
1358 void DoCompileShader(GLuint shader);
1360 // Wrapper for glDetachShader
1361 void DoDetachShader(GLuint client_program_id, GLint client_shader_id);
1363 // Wrapper for glDisable
1364 void DoDisable(GLenum cap);
1366 // Wrapper for glDisableVertexAttribArray.
1367 void DoDisableVertexAttribArray(GLuint index);
1369 // Wrapper for glDiscardFramebufferEXT, since we need to track undefined
1370 // attachments.
1371 void DoDiscardFramebufferEXT(GLenum target,
1372 GLsizei numAttachments,
1373 const GLenum* attachments);
1375 // Wrapper for glEnable
1376 void DoEnable(GLenum cap);
1378 // Wrapper for glEnableVertexAttribArray.
1379 void DoEnableVertexAttribArray(GLuint index);
1381 // Wrapper for glFinish.
1382 void DoFinish();
1384 // Wrapper for glFlush.
1385 void DoFlush();
1387 // Wrapper for glFramebufferRenderbufffer.
1388 void DoFramebufferRenderbuffer(
1389 GLenum target, GLenum attachment, GLenum renderbuffertarget,
1390 GLuint renderbuffer);
1392 // Wrapper for glFramebufferTexture2D.
1393 void DoFramebufferTexture2D(
1394 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
1395 GLint level);
1397 // Wrapper for glFramebufferTexture2DMultisampleEXT.
1398 void DoFramebufferTexture2DMultisample(
1399 GLenum target, GLenum attachment, GLenum textarget,
1400 GLuint texture, GLint level, GLsizei samples);
1402 // Common implementation for both DoFramebufferTexture2D wrappers.
1403 void DoFramebufferTexture2DCommon(const char* name,
1404 GLenum target, GLenum attachment, GLenum textarget,
1405 GLuint texture, GLint level, GLsizei samples);
1407 // Wrapper for glFramebufferTextureLayer.
1408 void DoFramebufferTextureLayer(
1409 GLenum target, GLenum attachment, GLuint texture, GLint level,
1410 GLint layer);
1412 // Wrapper for glGenerateMipmap
1413 void DoGenerateMipmap(GLenum target);
1415 // Helper for DoGetBooleanv, Floatv, and Intergerv to adjust pname
1416 // to account for different pname values defined in different extension
1417 // variants.
1418 GLenum AdjustGetPname(GLenum pname);
1420 // Wrapper for DoGetBooleanv.
1421 void DoGetBooleanv(GLenum pname, GLboolean* params);
1423 // Wrapper for DoGetFloatv.
1424 void DoGetFloatv(GLenum pname, GLfloat* params);
1426 // Wrapper for glGetFramebufferAttachmentParameteriv.
1427 void DoGetFramebufferAttachmentParameteriv(
1428 GLenum target, GLenum attachment, GLenum pname, GLint* params);
1430 // Wrapper for glGetInteger64v.
1431 void DoGetInteger64v(GLenum pname, GLint64* params);
1433 // Wrapper for glGetIntegerv.
1434 void DoGetIntegerv(GLenum pname, GLint* params);
1436 // Gets the max value in a range in a buffer.
1437 GLuint DoGetMaxValueInBufferCHROMIUM(
1438 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset);
1440 // Wrapper for glGetBufferParameteriv.
1441 void DoGetBufferParameteriv(
1442 GLenum target, GLenum pname, GLint* params);
1444 // Wrapper for glGetProgramiv.
1445 void DoGetProgramiv(
1446 GLuint program_id, GLenum pname, GLint* params);
1448 // Wrapper for glRenderbufferParameteriv.
1449 void DoGetRenderbufferParameteriv(
1450 GLenum target, GLenum pname, GLint* params);
1452 // Wrapper for glGetShaderiv
1453 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
1455 // Wrappers for glGetTexParameter.
1456 void DoGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params);
1457 void DoGetTexParameteriv(GLenum target, GLenum pname, GLint* params);
1458 void InitTextureMaxAnisotropyIfNeeded(GLenum target, GLenum pname);
1460 // Wrappers for glGetVertexAttrib.
1461 void DoGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params);
1462 void DoGetVertexAttribiv(GLuint index, GLenum pname, GLint *params);
1464 // Wrappers for glIsXXX functions.
1465 bool DoIsEnabled(GLenum cap);
1466 bool DoIsBuffer(GLuint client_id);
1467 bool DoIsFramebuffer(GLuint client_id);
1468 bool DoIsProgram(GLuint client_id);
1469 bool DoIsRenderbuffer(GLuint client_id);
1470 bool DoIsShader(GLuint client_id);
1471 bool DoIsTexture(GLuint client_id);
1472 bool DoIsVertexArrayOES(GLuint client_id);
1474 // Wrapper for glLinkProgram
1475 void DoLinkProgram(GLuint program);
1477 // Wrapper for glRenderbufferStorage.
1478 void DoRenderbufferStorage(
1479 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
1481 // Handler for glRenderbufferStorageMultisampleCHROMIUM.
1482 void DoRenderbufferStorageMultisampleCHROMIUM(
1483 GLenum target, GLsizei samples, GLenum internalformat,
1484 GLsizei width, GLsizei height);
1486 // Handler for glRenderbufferStorageMultisampleEXT
1487 // (multisampled_render_to_texture).
1488 void DoRenderbufferStorageMultisampleEXT(
1489 GLenum target, GLsizei samples, GLenum internalformat,
1490 GLsizei width, GLsizei height);
1492 // Common validation for multisample extensions.
1493 bool ValidateRenderbufferStorageMultisample(GLsizei samples,
1494 GLenum internalformat,
1495 GLsizei width,
1496 GLsizei height);
1498 // Verifies that the currently bound multisample renderbuffer is valid
1499 // Very slow! Only done on platforms with driver bugs that return invalid
1500 // buffers under memory pressure
1501 bool VerifyMultisampleRenderbufferIntegrity(
1502 GLuint renderbuffer, GLenum format);
1504 // Wrapper for glReleaseShaderCompiler.
1505 void DoReleaseShaderCompiler() { }
1507 // Wrappers for glSamplerParameter*v functions.
1508 void DoSamplerParameterfv(
1509 GLuint sampler, GLenum pname, const GLfloat* params);
1510 void DoSamplerParameteriv(GLuint sampler, GLenum pname, const GLint* params);
1512 // Wrappers for glTexParameter functions.
1513 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
1514 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
1515 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
1516 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
1518 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1519 // spec only these 2 functions can be used to set sampler uniforms.
1520 void DoUniform1i(GLint fake_location, GLint v0);
1521 void DoUniform1iv(GLint fake_location, GLsizei count, const GLint* value);
1522 void DoUniform2iv(GLint fake_location, GLsizei count, const GLint* value);
1523 void DoUniform3iv(GLint fake_location, GLsizei count, const GLint* value);
1524 void DoUniform4iv(GLint fake_location, GLsizei count, const GLint* value);
1526 // Wrappers for glUniformfv because some drivers don't correctly accept
1527 // bool uniforms.
1528 void DoUniform1fv(GLint fake_location, GLsizei count, const GLfloat* value);
1529 void DoUniform2fv(GLint fake_location, GLsizei count, const GLfloat* value);
1530 void DoUniform3fv(GLint fake_location, GLsizei count, const GLfloat* value);
1531 void DoUniform4fv(GLint fake_location, GLsizei count, const GLfloat* value);
1533 void DoUniformMatrix2fv(
1534 GLint fake_location, GLsizei count, GLboolean transpose,
1535 const GLfloat* value);
1536 void DoUniformMatrix3fv(
1537 GLint fake_location, GLsizei count, GLboolean transpose,
1538 const GLfloat* value);
1539 void DoUniformMatrix4fv(
1540 GLint fake_location, GLsizei count, GLboolean transpose,
1541 const GLfloat* value);
1543 bool SetVertexAttribValue(
1544 const char* function_name, GLuint index, const GLfloat* value);
1546 // Wrappers for glVertexAttrib??
1547 void DoVertexAttrib1f(GLuint index, GLfloat v0);
1548 void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
1549 void DoVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
1550 void DoVertexAttrib4f(
1551 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
1552 void DoVertexAttrib1fv(GLuint index, const GLfloat *v);
1553 void DoVertexAttrib2fv(GLuint index, const GLfloat *v);
1554 void DoVertexAttrib3fv(GLuint index, const GLfloat *v);
1555 void DoVertexAttrib4fv(GLuint index, const GLfloat *v);
1557 // Wrapper for glViewport
1558 void DoViewport(GLint x, GLint y, GLsizei width, GLsizei height);
1560 // Wrapper for glUseProgram
1561 void DoUseProgram(GLuint program);
1563 // Wrapper for glValidateProgram.
1564 void DoValidateProgram(GLuint program_client_id);
1566 void DoInsertEventMarkerEXT(GLsizei length, const GLchar* marker);
1567 void DoPushGroupMarkerEXT(GLsizei length, const GLchar* group);
1568 void DoPopGroupMarkerEXT(void);
1570 // Gets the number of values that will be returned by glGetXXX. Returns
1571 // false if pname is unknown.
1572 bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
1574 // Checks if the current program and vertex attributes are valid for drawing.
1575 bool IsDrawValid(
1576 const char* function_name, GLuint max_vertex_accessed, bool instanced,
1577 GLsizei primcount);
1579 // Returns true if successful, simulated will be true if attrib0 was
1580 // simulated.
1581 bool SimulateAttrib0(
1582 const char* function_name, GLuint max_vertex_accessed, bool* simulated);
1583 void RestoreStateForAttrib(GLuint attrib, bool restore_array_binding);
1585 // If an image is bound to texture, this will call Will/DidUseTexImage
1586 // if needed.
1587 void DoWillUseTexImageIfNeeded(Texture* texture, GLenum textarget);
1588 void DoDidUseTexImageIfNeeded(Texture* texture, GLenum textarget);
1590 // Returns false if textures were replaced.
1591 bool PrepareTexturesForRender();
1592 void RestoreStateForTextures();
1594 // Returns true if GL_FIXED attribs were simulated.
1595 bool SimulateFixedAttribs(
1596 const char* function_name,
1597 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount);
1598 void RestoreStateForSimulatedFixedAttribs();
1600 // Handle DrawArrays and DrawElements for both instanced and non-instanced
1601 // cases (primcount is always 1 for non-instanced).
1602 error::Error DoDrawArrays(
1603 const char* function_name,
1604 bool instanced, GLenum mode, GLint first, GLsizei count,
1605 GLsizei primcount);
1606 error::Error DoDrawElements(
1607 const char* function_name,
1608 bool instanced, GLenum mode, GLsizei count, GLenum type,
1609 int32 offset, GLsizei primcount);
1611 GLenum GetBindTargetForSamplerType(GLenum type) {
1612 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
1613 type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB);
1614 switch (type) {
1615 case GL_SAMPLER_2D:
1616 return GL_TEXTURE_2D;
1617 case GL_SAMPLER_CUBE:
1618 return GL_TEXTURE_CUBE_MAP;
1619 case GL_SAMPLER_EXTERNAL_OES:
1620 return GL_TEXTURE_EXTERNAL_OES;
1621 case GL_SAMPLER_2D_RECT_ARB:
1622 return GL_TEXTURE_RECTANGLE_ARB;
1625 NOTREACHED();
1626 return 0;
1629 // Gets the framebuffer info for a particular target.
1630 Framebuffer* GetFramebufferInfoForTarget(GLenum target) {
1631 Framebuffer* framebuffer = NULL;
1632 switch (target) {
1633 case GL_FRAMEBUFFER:
1634 case GL_DRAW_FRAMEBUFFER_EXT:
1635 framebuffer = framebuffer_state_.bound_draw_framebuffer.get();
1636 break;
1637 case GL_READ_FRAMEBUFFER_EXT:
1638 framebuffer = framebuffer_state_.bound_read_framebuffer.get();
1639 break;
1640 default:
1641 NOTREACHED();
1642 break;
1644 return framebuffer;
1647 Renderbuffer* GetRenderbufferInfoForTarget(
1648 GLenum target) {
1649 Renderbuffer* renderbuffer = NULL;
1650 switch (target) {
1651 case GL_RENDERBUFFER:
1652 renderbuffer = state_.bound_renderbuffer.get();
1653 break;
1654 default:
1655 NOTREACHED();
1656 break;
1658 return renderbuffer;
1661 // Validates the program and location for a glGetUniform call and returns
1662 // a SizeResult setup to receive the result. Returns true if glGetUniform
1663 // should be called.
1664 bool GetUniformSetup(GLuint program,
1665 GLint fake_location,
1666 uint32 shm_id,
1667 uint32 shm_offset,
1668 error::Error* error,
1669 GLint* real_location,
1670 GLuint* service_id,
1671 void** result,
1672 GLenum* result_type,
1673 GLsizei* result_size);
1675 bool WasContextLost() const override;
1676 bool WasContextLostByRobustnessExtension() const override;
1677 void MarkContextLost(error::ContextLostReason reason) override;
1678 bool CheckResetStatus();
1680 #if defined(OS_MACOSX)
1681 void ReleaseIOSurfaceForTexture(GLuint texture_id);
1682 #endif
1684 bool ValidateCompressedTexDimensions(
1685 const char* function_name, GLenum target, GLint level,
1686 GLsizei width, GLsizei height, GLsizei depth, GLenum format);
1687 bool ValidateCompressedTexFuncData(
1688 const char* function_name, GLsizei width, GLsizei height, GLsizei depth,
1689 GLenum format, GLsizei size);
1690 bool ValidateCompressedTexSubDimensions(
1691 const char* function_name,
1692 GLenum target, GLint level, GLint xoffset, GLint yoffset,
1693 GLsizei width, GLsizei height, GLenum format,
1694 Texture* texture);
1695 bool ValidateCopyTextureCHROMIUM(const char* function_name,
1696 GLenum target,
1697 TextureRef* source_texture_ref,
1698 TextureRef* dest_texture_ref,
1699 GLenum dest_internal_format);
1701 void RenderWarning(const char* filename, int line, const std::string& msg);
1702 void PerformanceWarning(
1703 const char* filename, int line, const std::string& msg);
1705 const FeatureInfo::FeatureFlags& features() const {
1706 return feature_info_->feature_flags();
1709 const FeatureInfo::Workarounds& workarounds() const {
1710 return feature_info_->workarounds();
1713 bool ShouldDeferDraws() {
1714 return !offscreen_target_frame_buffer_.get() &&
1715 framebuffer_state_.bound_draw_framebuffer.get() == NULL &&
1716 surface_->DeferDraws();
1719 bool ShouldDeferReads() {
1720 return !offscreen_target_frame_buffer_.get() &&
1721 framebuffer_state_.bound_read_framebuffer.get() == NULL &&
1722 surface_->DeferDraws();
1725 bool IsRobustnessSupported() {
1726 return has_robustness_extension_ &&
1727 context_->WasAllocatedUsingRobustnessExtension();
1730 error::Error WillAccessBoundFramebufferForDraw() {
1731 if (ShouldDeferDraws())
1732 return error::kDeferCommandUntilLater;
1733 if (!offscreen_target_frame_buffer_.get() &&
1734 !framebuffer_state_.bound_draw_framebuffer.get() &&
1735 !surface_->SetBackbufferAllocation(true))
1736 return error::kLostContext;
1737 return error::kNoError;
1740 error::Error WillAccessBoundFramebufferForRead() {
1741 if (ShouldDeferReads())
1742 return error::kDeferCommandUntilLater;
1743 if (!offscreen_target_frame_buffer_.get() &&
1744 !framebuffer_state_.bound_read_framebuffer.get() &&
1745 !surface_->SetBackbufferAllocation(true))
1746 return error::kLostContext;
1747 return error::kNoError;
1750 // Set remaining commands to process to 0 to force DoCommands to return
1751 // and allow context preemption and GPU watchdog checks in GpuScheduler().
1752 void ExitCommandProcessingEarly() { commands_to_process_ = 0; }
1754 void ProcessPendingReadPixels();
1755 void FinishReadPixels(const cmds::ReadPixels& c, GLuint buffer);
1757 // Generate a member function prototype for each command in an automated and
1758 // typesafe way.
1759 #define GLES2_CMD_OP(name) \
1760 Error Handle##name(uint32 immediate_data_size, const void* data);
1762 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1764 #undef GLES2_CMD_OP
1766 // The GL context this decoder renders to on behalf of the client.
1767 scoped_refptr<gfx::GLSurface> surface_;
1768 scoped_refptr<gfx::GLContext> context_;
1770 // The ContextGroup for this decoder uses to track resources.
1771 scoped_refptr<ContextGroup> group_;
1773 DebugMarkerManager debug_marker_manager_;
1774 Logger logger_;
1776 // All the state for this context.
1777 ContextState state_;
1779 // Current width and height of the offscreen frame buffer.
1780 gfx::Size offscreen_size_;
1782 // Util to help with GL.
1783 GLES2Util util_;
1785 // unpack flip y as last set by glPixelStorei
1786 bool unpack_flip_y_;
1788 // unpack (un)premultiply alpha as last set by glPixelStorei
1789 bool unpack_premultiply_alpha_;
1790 bool unpack_unpremultiply_alpha_;
1792 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1793 GLuint attrib_0_buffer_id_;
1795 // The value currently in attrib_0.
1796 Vec4 attrib_0_value_;
1798 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1799 bool attrib_0_buffer_matches_value_;
1801 // The size of attrib 0.
1802 GLsizei attrib_0_size_;
1804 // The buffer used to simulate GL_FIXED attribs.
1805 GLuint fixed_attrib_buffer_id_;
1807 // The size of fiixed attrib buffer.
1808 GLsizei fixed_attrib_buffer_size_;
1810 // The offscreen frame buffer that the client renders to. With EGL, the
1811 // depth and stencil buffers are separate. With regular GL there is a single
1812 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1813 // offscreen_target_stencil_render_buffer_ is unused.
1814 scoped_ptr<BackFramebuffer> offscreen_target_frame_buffer_;
1815 scoped_ptr<BackTexture> offscreen_target_color_texture_;
1816 scoped_ptr<BackRenderbuffer> offscreen_target_color_render_buffer_;
1817 scoped_ptr<BackRenderbuffer> offscreen_target_depth_render_buffer_;
1818 scoped_ptr<BackRenderbuffer> offscreen_target_stencil_render_buffer_;
1819 GLenum offscreen_target_color_format_;
1820 GLenum offscreen_target_depth_format_;
1821 GLenum offscreen_target_stencil_format_;
1822 GLsizei offscreen_target_samples_;
1823 GLboolean offscreen_target_buffer_preserved_;
1825 // The copy that is saved when SwapBuffers is called.
1826 scoped_ptr<BackFramebuffer> offscreen_saved_frame_buffer_;
1827 scoped_ptr<BackTexture> offscreen_saved_color_texture_;
1828 scoped_refptr<TextureRef>
1829 offscreen_saved_color_texture_info_;
1831 // The copy that is used as the destination for multi-sample resolves.
1832 scoped_ptr<BackFramebuffer> offscreen_resolved_frame_buffer_;
1833 scoped_ptr<BackTexture> offscreen_resolved_color_texture_;
1834 GLenum offscreen_saved_color_format_;
1836 scoped_ptr<QueryManager> query_manager_;
1838 scoped_ptr<VertexArrayManager> vertex_array_manager_;
1840 scoped_ptr<ImageManager> image_manager_;
1842 base::Callback<void(gfx::Size, float)> resize_callback_;
1844 WaitSyncPointCallback wait_sync_point_callback_;
1846 ShaderCacheCallback shader_cache_callback_;
1848 scoped_ptr<AsyncPixelTransferManager> async_pixel_transfer_manager_;
1850 // The format of the back buffer_
1851 GLenum back_buffer_color_format_;
1852 bool back_buffer_has_depth_;
1853 bool back_buffer_has_stencil_;
1855 bool surfaceless_;
1857 // Backbuffer attachments that are currently undefined.
1858 uint32 backbuffer_needs_clear_bits_;
1860 // The current decoder error communicates the decoder error through command
1861 // processing functions that do not return the error value. Should be set only
1862 // if not returning an error.
1863 error::Error current_decoder_error_;
1865 bool use_shader_translator_;
1866 scoped_refptr<ShaderTranslatorInterface> vertex_translator_;
1867 scoped_refptr<ShaderTranslatorInterface> fragment_translator_;
1869 DisallowedFeatures disallowed_features_;
1871 // Cached from ContextGroup
1872 const Validators* validators_;
1873 scoped_refptr<FeatureInfo> feature_info_;
1875 int frame_number_;
1877 // Number of commands remaining to be processed in DoCommands().
1878 int commands_to_process_;
1880 bool has_robustness_extension_;
1881 error::ContextLostReason context_lost_reason_;
1882 bool context_was_lost_;
1883 bool reset_by_robustness_extension_;
1884 bool supports_post_sub_buffer_;
1886 // These flags are used to override the state of the shared feature_info_
1887 // member. Because the same FeatureInfo instance may be shared among many
1888 // contexts, the assumptions on the availablity of extensions in WebGL
1889 // contexts may be broken. These flags override the shared state to preserve
1890 // WebGL semantics.
1891 bool force_webgl_glsl_validation_;
1892 bool derivatives_explicitly_enabled_;
1893 bool frag_depth_explicitly_enabled_;
1894 bool draw_buffers_explicitly_enabled_;
1895 bool shader_texture_lod_explicitly_enabled_;
1897 bool compile_shader_always_succeeds_;
1899 // An optional behaviour to lose the context and group when OOM.
1900 bool lose_context_when_out_of_memory_;
1902 // Log extra info.
1903 bool service_logging_;
1905 #if defined(OS_MACOSX)
1906 typedef std::map<GLuint, IOSurfaceRef> TextureToIOSurfaceMap;
1907 TextureToIOSurfaceMap texture_to_io_surface_map_;
1908 #endif
1910 scoped_ptr<CopyTextureCHROMIUMResourceManager> copy_texture_CHROMIUM_;
1911 scoped_ptr<ClearFramebufferResourceManager> clear_framebuffer_blit_;
1913 // Cached values of the currently assigned viewport dimensions.
1914 GLsizei viewport_max_width_;
1915 GLsizei viewport_max_height_;
1917 // Command buffer stats.
1918 base::TimeDelta total_processing_commands_time_;
1920 // States related to each manager.
1921 DecoderTextureState texture_state_;
1922 DecoderFramebufferState framebuffer_state_;
1924 scoped_ptr<GPUTracer> gpu_tracer_;
1925 scoped_ptr<GPUStateTracer> gpu_state_tracer_;
1926 const unsigned char* cb_command_trace_category_;
1927 const unsigned char* gpu_decoder_category_;
1928 int gpu_trace_level_;
1929 bool gpu_trace_commands_;
1930 bool gpu_debug_commands_;
1932 std::queue<linked_ptr<FenceCallback> > pending_readpixel_fences_;
1934 // Used to validate multisample renderbuffers if needed
1935 GLuint validation_texture_;
1936 GLuint validation_fbo_multisample_;
1937 GLuint validation_fbo_;
1939 typedef gpu::gles2::GLES2Decoder::Error (GLES2DecoderImpl::*CmdHandler)(
1940 uint32 immediate_data_size,
1941 const void* data);
1943 // A struct to hold info about each command.
1944 struct CommandInfo {
1945 CmdHandler cmd_handler;
1946 uint8 arg_flags; // How to handle the arguments for this command
1947 uint8 cmd_flags; // How to handle this command
1948 uint16 arg_count; // How many arguments are expected for this command.
1951 // A table of CommandInfo for all the commands.
1952 static const CommandInfo command_info[kNumCommands - kStartPoint];
1954 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
1957 const GLES2DecoderImpl::CommandInfo GLES2DecoderImpl::command_info[] = {
1958 #define GLES2_CMD_OP(name) \
1960 &GLES2DecoderImpl::Handle##name, cmds::name::kArgFlags, \
1961 cmds::name::cmd_flags, \
1962 sizeof(cmds::name) / sizeof(CommandBufferEntry) - 1, \
1964 , /* NOLINT */
1965 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1966 #undef GLES2_CMD_OP
1969 ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(
1970 const char* function_name, ErrorState* error_state)
1971 : function_name_(function_name),
1972 error_state_(error_state) {
1973 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state_, function_name_);
1976 ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
1977 ERRORSTATE_CLEAR_REAL_GL_ERRORS(error_state_, function_name_);
1980 static void RestoreCurrentTextureBindings(ContextState* state, GLenum target) {
1981 TextureUnit& info = state->texture_units[0];
1982 GLuint last_id;
1983 scoped_refptr<TextureRef> texture_ref;
1984 switch (target) {
1985 case GL_TEXTURE_2D:
1986 texture_ref = info.bound_texture_2d;
1987 break;
1988 case GL_TEXTURE_CUBE_MAP:
1989 texture_ref = info.bound_texture_cube_map;
1990 break;
1991 case GL_TEXTURE_EXTERNAL_OES:
1992 texture_ref = info.bound_texture_external_oes;
1993 break;
1994 case GL_TEXTURE_RECTANGLE_ARB:
1995 texture_ref = info.bound_texture_rectangle_arb;
1996 break;
1997 default:
1998 NOTREACHED();
1999 break;
2001 if (texture_ref.get()) {
2002 last_id = texture_ref->service_id();
2003 } else {
2004 last_id = 0;
2007 glBindTexture(target, last_id);
2008 glActiveTexture(GL_TEXTURE0 + state->active_texture_unit);
2011 ScopedTextureBinder::ScopedTextureBinder(ContextState* state,
2012 GLuint id,
2013 GLenum target)
2014 : state_(state),
2015 target_(target) {
2016 ScopedGLErrorSuppressor suppressor(
2017 "ScopedTextureBinder::ctor", state_->GetErrorState());
2019 // TODO(apatrick): Check if there are any other states that need to be reset
2020 // before binding a new texture.
2021 glActiveTexture(GL_TEXTURE0);
2022 glBindTexture(target, id);
2025 ScopedTextureBinder::~ScopedTextureBinder() {
2026 ScopedGLErrorSuppressor suppressor(
2027 "ScopedTextureBinder::dtor", state_->GetErrorState());
2028 RestoreCurrentTextureBindings(state_, target_);
2031 ScopedRenderBufferBinder::ScopedRenderBufferBinder(ContextState* state,
2032 GLuint id)
2033 : state_(state) {
2034 ScopedGLErrorSuppressor suppressor(
2035 "ScopedRenderBufferBinder::ctor", state_->GetErrorState());
2036 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
2039 ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
2040 ScopedGLErrorSuppressor suppressor(
2041 "ScopedRenderBufferBinder::dtor", state_->GetErrorState());
2042 state_->RestoreRenderbufferBindings();
2045 ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
2046 GLuint id)
2047 : decoder_(decoder) {
2048 ScopedGLErrorSuppressor suppressor(
2049 "ScopedFrameBufferBinder::ctor", decoder_->GetErrorState());
2050 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
2051 decoder->OnFboChanged();
2054 ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
2055 ScopedGLErrorSuppressor suppressor(
2056 "ScopedFrameBufferBinder::dtor", decoder_->GetErrorState());
2057 decoder_->RestoreCurrentFramebufferBindings();
2060 ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
2061 GLES2DecoderImpl* decoder, bool enforce_internal_framebuffer, bool internal)
2062 : decoder_(decoder) {
2063 resolve_and_bind_ = (
2064 decoder_->offscreen_target_frame_buffer_.get() &&
2065 decoder_->IsOffscreenBufferMultisampled() &&
2066 (!decoder_->framebuffer_state_.bound_read_framebuffer.get() ||
2067 enforce_internal_framebuffer));
2068 if (!resolve_and_bind_)
2069 return;
2071 ScopedGLErrorSuppressor suppressor(
2072 "ScopedResolvedFrameBufferBinder::ctor", decoder_->GetErrorState());
2073 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT,
2074 decoder_->offscreen_target_frame_buffer_->id());
2075 GLuint targetid;
2076 if (internal) {
2077 if (!decoder_->offscreen_resolved_frame_buffer_.get()) {
2078 decoder_->offscreen_resolved_frame_buffer_.reset(
2079 new BackFramebuffer(decoder_));
2080 decoder_->offscreen_resolved_frame_buffer_->Create();
2081 decoder_->offscreen_resolved_color_texture_.reset(
2082 new BackTexture(decoder->memory_tracker(), &decoder->state_));
2083 decoder_->offscreen_resolved_color_texture_->Create();
2085 DCHECK(decoder_->offscreen_saved_color_format_);
2086 decoder_->offscreen_resolved_color_texture_->AllocateStorage(
2087 decoder_->offscreen_size_, decoder_->offscreen_saved_color_format_,
2088 false);
2089 decoder_->offscreen_resolved_frame_buffer_->AttachRenderTexture(
2090 decoder_->offscreen_resolved_color_texture_.get());
2091 if (decoder_->offscreen_resolved_frame_buffer_->CheckStatus() !=
2092 GL_FRAMEBUFFER_COMPLETE) {
2093 LOG(ERROR) << "ScopedResolvedFrameBufferBinder failed "
2094 << "because offscreen resolved FBO was incomplete.";
2095 return;
2098 targetid = decoder_->offscreen_resolved_frame_buffer_->id();
2099 } else {
2100 targetid = decoder_->offscreen_saved_frame_buffer_->id();
2102 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, targetid);
2103 const int width = decoder_->offscreen_size_.width();
2104 const int height = decoder_->offscreen_size_.height();
2105 decoder->state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
2106 decoder->BlitFramebufferHelper(0,
2108 width,
2109 height,
2112 width,
2113 height,
2114 GL_COLOR_BUFFER_BIT,
2115 GL_NEAREST);
2116 glBindFramebufferEXT(GL_FRAMEBUFFER, targetid);
2119 ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
2120 if (!resolve_and_bind_)
2121 return;
2123 ScopedGLErrorSuppressor suppressor(
2124 "ScopedResolvedFrameBufferBinder::dtor", decoder_->GetErrorState());
2125 decoder_->RestoreCurrentFramebufferBindings();
2126 if (decoder_->state_.enable_flags.scissor_test) {
2127 decoder_->state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
2131 BackTexture::BackTexture(
2132 MemoryTracker* memory_tracker,
2133 ContextState* state)
2134 : memory_tracker_(memory_tracker, MemoryTracker::kUnmanaged),
2135 state_(state),
2136 bytes_allocated_(0),
2137 id_(0) {
2140 BackTexture::~BackTexture() {
2141 // This does not destroy the render texture because that would require that
2142 // the associated GL context was current. Just check that it was explicitly
2143 // destroyed.
2144 DCHECK_EQ(id_, 0u);
2147 void BackTexture::Create() {
2148 ScopedGLErrorSuppressor suppressor("BackTexture::Create",
2149 state_->GetErrorState());
2150 Destroy();
2151 glGenTextures(1, &id_);
2152 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2153 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2154 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2155 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2156 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2158 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
2159 // never called on an offscreen context, no data will ever be uploaded to the
2160 // saved offscreen color texture (it is deferred until to when SwapBuffers
2161 // is called). My idea is that some nvidia drivers might have a bug where
2162 // deleting a texture that has never been populated might cause a
2163 // crash.
2164 glTexImage2D(
2165 GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
2167 bytes_allocated_ = 16u * 16u * 4u;
2168 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2171 bool BackTexture::AllocateStorage(
2172 const gfx::Size& size, GLenum format, bool zero) {
2173 DCHECK_NE(id_, 0u);
2174 ScopedGLErrorSuppressor suppressor("BackTexture::AllocateStorage",
2175 state_->GetErrorState());
2176 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2177 uint32 image_size = 0;
2178 GLES2Util::ComputeImageDataSizes(
2179 size.width(), size.height(), 1, format, GL_UNSIGNED_BYTE, 8, &image_size,
2180 NULL, NULL);
2182 if (!memory_tracker_.EnsureGPUMemoryAvailable(image_size)) {
2183 return false;
2186 scoped_ptr<char[]> zero_data;
2187 if (zero) {
2188 zero_data.reset(new char[image_size]);
2189 memset(zero_data.get(), 0, image_size);
2192 glTexImage2D(GL_TEXTURE_2D,
2193 0, // mip level
2194 format,
2195 size.width(),
2196 size.height(),
2197 0, // border
2198 format,
2199 GL_UNSIGNED_BYTE,
2200 zero_data.get());
2202 size_ = size;
2204 bool success = glGetError() == GL_NO_ERROR;
2205 if (success) {
2206 memory_tracker_.TrackMemFree(bytes_allocated_);
2207 bytes_allocated_ = image_size;
2208 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2210 return success;
2213 void BackTexture::Copy(const gfx::Size& size, GLenum format) {
2214 DCHECK_NE(id_, 0u);
2215 ScopedGLErrorSuppressor suppressor("BackTexture::Copy",
2216 state_->GetErrorState());
2217 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2218 glCopyTexImage2D(GL_TEXTURE_2D,
2219 0, // level
2220 format,
2221 0, 0,
2222 size.width(),
2223 size.height(),
2224 0); // border
2227 void BackTexture::Destroy() {
2228 if (id_ != 0) {
2229 ScopedGLErrorSuppressor suppressor("BackTexture::Destroy",
2230 state_->GetErrorState());
2231 glDeleteTextures(1, &id_);
2232 id_ = 0;
2234 memory_tracker_.TrackMemFree(bytes_allocated_);
2235 bytes_allocated_ = 0;
2238 void BackTexture::Invalidate() {
2239 id_ = 0;
2242 BackRenderbuffer::BackRenderbuffer(
2243 RenderbufferManager* renderbuffer_manager,
2244 MemoryTracker* memory_tracker,
2245 ContextState* state)
2246 : renderbuffer_manager_(renderbuffer_manager),
2247 memory_tracker_(memory_tracker, MemoryTracker::kUnmanaged),
2248 state_(state),
2249 bytes_allocated_(0),
2250 id_(0) {
2253 BackRenderbuffer::~BackRenderbuffer() {
2254 // This does not destroy the render buffer because that would require that
2255 // the associated GL context was current. Just check that it was explicitly
2256 // destroyed.
2257 DCHECK_EQ(id_, 0u);
2260 void BackRenderbuffer::Create() {
2261 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Create",
2262 state_->GetErrorState());
2263 Destroy();
2264 glGenRenderbuffersEXT(1, &id_);
2267 bool BackRenderbuffer::AllocateStorage(const FeatureInfo* feature_info,
2268 const gfx::Size& size,
2269 GLenum format,
2270 GLsizei samples) {
2271 ScopedGLErrorSuppressor suppressor(
2272 "BackRenderbuffer::AllocateStorage", state_->GetErrorState());
2273 ScopedRenderBufferBinder binder(state_, id_);
2275 uint32 estimated_size = 0;
2276 if (!renderbuffer_manager_->ComputeEstimatedRenderbufferSize(
2277 size.width(), size.height(), samples, format, &estimated_size)) {
2278 return false;
2281 if (!memory_tracker_.EnsureGPUMemoryAvailable(estimated_size)) {
2282 return false;
2285 if (samples <= 1) {
2286 glRenderbufferStorageEXT(GL_RENDERBUFFER,
2287 format,
2288 size.width(),
2289 size.height());
2290 } else {
2291 GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(feature_info,
2292 GL_RENDERBUFFER,
2293 samples,
2294 format,
2295 size.width(),
2296 size.height());
2298 bool success = glGetError() == GL_NO_ERROR;
2299 if (success) {
2300 // Mark the previously allocated bytes as free.
2301 memory_tracker_.TrackMemFree(bytes_allocated_);
2302 bytes_allocated_ = estimated_size;
2303 // Track the newly allocated bytes.
2304 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2306 return success;
2309 void BackRenderbuffer::Destroy() {
2310 if (id_ != 0) {
2311 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Destroy",
2312 state_->GetErrorState());
2313 glDeleteRenderbuffersEXT(1, &id_);
2314 id_ = 0;
2316 memory_tracker_.TrackMemFree(bytes_allocated_);
2317 bytes_allocated_ = 0;
2320 void BackRenderbuffer::Invalidate() {
2321 id_ = 0;
2324 BackFramebuffer::BackFramebuffer(GLES2DecoderImpl* decoder)
2325 : decoder_(decoder),
2326 id_(0) {
2329 BackFramebuffer::~BackFramebuffer() {
2330 // This does not destroy the frame buffer because that would require that
2331 // the associated GL context was current. Just check that it was explicitly
2332 // destroyed.
2333 DCHECK_EQ(id_, 0u);
2336 void BackFramebuffer::Create() {
2337 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Create",
2338 decoder_->GetErrorState());
2339 Destroy();
2340 glGenFramebuffersEXT(1, &id_);
2343 void BackFramebuffer::AttachRenderTexture(BackTexture* texture) {
2344 DCHECK_NE(id_, 0u);
2345 ScopedGLErrorSuppressor suppressor(
2346 "BackFramebuffer::AttachRenderTexture", decoder_->GetErrorState());
2347 ScopedFrameBufferBinder binder(decoder_, id_);
2348 GLuint attach_id = texture ? texture->id() : 0;
2349 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
2350 GL_COLOR_ATTACHMENT0,
2351 GL_TEXTURE_2D,
2352 attach_id,
2356 void BackFramebuffer::AttachRenderBuffer(GLenum target,
2357 BackRenderbuffer* render_buffer) {
2358 DCHECK_NE(id_, 0u);
2359 ScopedGLErrorSuppressor suppressor(
2360 "BackFramebuffer::AttachRenderBuffer", decoder_->GetErrorState());
2361 ScopedFrameBufferBinder binder(decoder_, id_);
2362 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
2363 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
2364 target,
2365 GL_RENDERBUFFER,
2366 attach_id);
2369 void BackFramebuffer::Destroy() {
2370 if (id_ != 0) {
2371 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Destroy",
2372 decoder_->GetErrorState());
2373 glDeleteFramebuffersEXT(1, &id_);
2374 id_ = 0;
2378 void BackFramebuffer::Invalidate() {
2379 id_ = 0;
2382 GLenum BackFramebuffer::CheckStatus() {
2383 DCHECK_NE(id_, 0u);
2384 ScopedGLErrorSuppressor suppressor("BackFramebuffer::CheckStatus",
2385 decoder_->GetErrorState());
2386 ScopedFrameBufferBinder binder(decoder_, id_);
2387 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
2390 GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
2391 return new GLES2DecoderImpl(group);
2394 GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
2395 : GLES2Decoder(),
2396 group_(group),
2397 logger_(&debug_marker_manager_),
2398 state_(group_->feature_info(), this, &logger_),
2399 unpack_flip_y_(false),
2400 unpack_premultiply_alpha_(false),
2401 unpack_unpremultiply_alpha_(false),
2402 attrib_0_buffer_id_(0),
2403 attrib_0_buffer_matches_value_(true),
2404 attrib_0_size_(0),
2405 fixed_attrib_buffer_id_(0),
2406 fixed_attrib_buffer_size_(0),
2407 offscreen_target_color_format_(0),
2408 offscreen_target_depth_format_(0),
2409 offscreen_target_stencil_format_(0),
2410 offscreen_target_samples_(0),
2411 offscreen_target_buffer_preserved_(true),
2412 offscreen_saved_color_format_(0),
2413 back_buffer_color_format_(0),
2414 back_buffer_has_depth_(false),
2415 back_buffer_has_stencil_(false),
2416 surfaceless_(false),
2417 backbuffer_needs_clear_bits_(0),
2418 current_decoder_error_(error::kNoError),
2419 use_shader_translator_(true),
2420 validators_(group_->feature_info()->validators()),
2421 feature_info_(group_->feature_info()),
2422 frame_number_(0),
2423 has_robustness_extension_(false),
2424 context_lost_reason_(error::kUnknown),
2425 context_was_lost_(false),
2426 reset_by_robustness_extension_(false),
2427 supports_post_sub_buffer_(false),
2428 force_webgl_glsl_validation_(false),
2429 derivatives_explicitly_enabled_(false),
2430 frag_depth_explicitly_enabled_(false),
2431 draw_buffers_explicitly_enabled_(false),
2432 shader_texture_lod_explicitly_enabled_(false),
2433 compile_shader_always_succeeds_(false),
2434 lose_context_when_out_of_memory_(false),
2435 service_logging_(base::CommandLine::ForCurrentProcess()->HasSwitch(
2436 switches::kEnableGPUServiceLoggingGPU)),
2437 viewport_max_width_(0),
2438 viewport_max_height_(0),
2439 texture_state_(group_->feature_info()
2440 ->workarounds()
2441 .texsubimage2d_faster_than_teximage2d),
2442 cb_command_trace_category_(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
2443 TRACE_DISABLED_BY_DEFAULT("cb_command"))),
2444 gpu_decoder_category_(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
2445 TRACE_DISABLED_BY_DEFAULT("gpu_decoder"))),
2446 gpu_trace_level_(2),
2447 gpu_trace_commands_(false),
2448 gpu_debug_commands_(false),
2449 validation_texture_(0),
2450 validation_fbo_multisample_(0),
2451 validation_fbo_(0) {
2452 DCHECK(group);
2454 attrib_0_value_.v[0] = 0.0f;
2455 attrib_0_value_.v[1] = 0.0f;
2456 attrib_0_value_.v[2] = 0.0f;
2457 attrib_0_value_.v[3] = 1.0f;
2459 // The shader translator is used for WebGL even when running on EGL
2460 // because additional restrictions are needed (like only enabling
2461 // GL_OES_standard_derivatives on demand). It is used for the unit
2462 // tests because GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes
2463 // the empty string to CompileShader and this is not a valid shader.
2464 if (gfx::GetGLImplementation() == gfx::kGLImplementationMockGL ||
2465 base::CommandLine::ForCurrentProcess()->HasSwitch(
2466 switches::kDisableGLSLTranslator)) {
2467 use_shader_translator_ = false;
2471 GLES2DecoderImpl::~GLES2DecoderImpl() {
2474 bool GLES2DecoderImpl::Initialize(
2475 const scoped_refptr<gfx::GLSurface>& surface,
2476 const scoped_refptr<gfx::GLContext>& context,
2477 bool offscreen,
2478 const gfx::Size& offscreen_size,
2479 const DisallowedFeatures& disallowed_features,
2480 const std::vector<int32>& attribs) {
2481 TRACE_EVENT0("gpu", "GLES2DecoderImpl::Initialize");
2482 DCHECK(context->IsCurrent(surface.get()));
2483 DCHECK(!context_.get());
2484 DCHECK(!offscreen || !offscreen_size.IsEmpty());
2486 ContextCreationAttribHelper attrib_parser;
2487 if (!attrib_parser.Parse(attribs))
2488 return false;
2490 surfaceless_ = surface->IsSurfaceless() && !offscreen;
2492 set_initialized();
2493 gpu_state_tracer_ = GPUStateTracer::Create(&state_);
2495 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2496 switches::kEnableGPUDebugging)) {
2497 set_debug(true);
2500 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2501 switches::kEnableGPUCommandLogging)) {
2502 set_log_commands(true);
2505 compile_shader_always_succeeds_ =
2506 base::CommandLine::ForCurrentProcess()->HasSwitch(
2507 switches::kCompileShaderAlwaysSucceeds);
2509 // Take ownership of the context and surface. The surface can be replaced with
2510 // SetSurface.
2511 context_ = context;
2512 surface_ = surface;
2514 // Create GPU Tracer for timing values.
2515 gpu_tracer_.reset(new GPUTracer(this));
2517 // Save the loseContextWhenOutOfMemory context creation attribute.
2518 lose_context_when_out_of_memory_ =
2519 attrib_parser.lose_context_when_out_of_memory;
2521 // If the failIfMajorPerformanceCaveat context creation attribute was true
2522 // and we are using a software renderer, fail.
2523 if (attrib_parser.fail_if_major_perf_caveat &&
2524 feature_info_->feature_flags().is_swiftshader) {
2525 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
2526 Destroy(true);
2527 return false;
2530 if (!group_->Initialize(this, disallowed_features)) {
2531 LOG(ERROR) << "GpuScheduler::InitializeCommon failed because group "
2532 << "failed to initialize.";
2533 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
2534 Destroy(true);
2535 return false;
2537 CHECK_GL_ERROR();
2539 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2540 switches::kEnableUnsafeES3APIs) &&
2541 attrib_parser.es3_context_required &&
2542 feature_info_->IsES3Capable()) {
2543 feature_info_->EnableES3Validators();
2544 set_unsafe_es3_apis_enabled(true);
2547 disallowed_features_ = disallowed_features;
2549 state_.attrib_values.resize(group_->max_vertex_attribs());
2550 vertex_array_manager_.reset(new VertexArrayManager());
2552 GLuint default_vertex_attrib_service_id = 0;
2553 if (features().native_vertex_array_object) {
2554 glGenVertexArraysOES(1, &default_vertex_attrib_service_id);
2555 glBindVertexArrayOES(default_vertex_attrib_service_id);
2558 state_.default_vertex_attrib_manager =
2559 CreateVertexAttribManager(0, default_vertex_attrib_service_id, false);
2561 state_.default_vertex_attrib_manager->Initialize(
2562 group_->max_vertex_attribs(),
2563 feature_info_->workarounds().init_vertex_attributes);
2565 // vertex_attrib_manager is set to default_vertex_attrib_manager by this call
2566 DoBindVertexArrayOES(0);
2568 query_manager_.reset(new QueryManager(this, feature_info_.get()));
2570 image_manager_.reset(new ImageManager);
2572 util_.set_num_compressed_texture_formats(
2573 validators_->compressed_texture_format.GetValues().size());
2575 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2576 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
2577 // OpenGL ES 2.0 does not have this issue.
2578 glEnableVertexAttribArray(0);
2580 glGenBuffersARB(1, &attrib_0_buffer_id_);
2581 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
2582 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
2583 glBindBuffer(GL_ARRAY_BUFFER, 0);
2584 glGenBuffersARB(1, &fixed_attrib_buffer_id_);
2586 state_.texture_units.resize(group_->max_texture_units());
2587 for (uint32 tt = 0; tt < state_.texture_units.size(); ++tt) {
2588 glActiveTexture(GL_TEXTURE0 + tt);
2589 // We want the last bind to be 2D.
2590 TextureRef* ref;
2591 if (features().oes_egl_image_external) {
2592 ref = texture_manager()->GetDefaultTextureInfo(
2593 GL_TEXTURE_EXTERNAL_OES);
2594 state_.texture_units[tt].bound_texture_external_oes = ref;
2595 glBindTexture(GL_TEXTURE_EXTERNAL_OES, ref ? ref->service_id() : 0);
2597 if (features().arb_texture_rectangle) {
2598 ref = texture_manager()->GetDefaultTextureInfo(
2599 GL_TEXTURE_RECTANGLE_ARB);
2600 state_.texture_units[tt].bound_texture_rectangle_arb = ref;
2601 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, ref ? ref->service_id() : 0);
2603 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
2604 state_.texture_units[tt].bound_texture_cube_map = ref;
2605 glBindTexture(GL_TEXTURE_CUBE_MAP, ref ? ref->service_id() : 0);
2606 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
2607 state_.texture_units[tt].bound_texture_2d = ref;
2608 glBindTexture(GL_TEXTURE_2D, ref ? ref->service_id() : 0);
2610 glActiveTexture(GL_TEXTURE0);
2611 CHECK_GL_ERROR();
2613 if (offscreen) {
2614 if (attrib_parser.samples > 0 && attrib_parser.sample_buffers > 0 &&
2615 features().chromium_framebuffer_multisample) {
2616 // Per ext_framebuffer_multisample spec, need max bound on sample count.
2617 // max_sample_count must be initialized to a sane value. If
2618 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2619 GLint max_sample_count = 1;
2620 glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count);
2621 offscreen_target_samples_ = std::min(attrib_parser.samples,
2622 max_sample_count);
2623 } else {
2624 offscreen_target_samples_ = 1;
2626 offscreen_target_buffer_preserved_ = attrib_parser.buffer_preserved;
2628 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
2629 const bool rgb8_supported =
2630 context_->HasExtension("GL_OES_rgb8_rgba8");
2631 // The only available default render buffer formats in GLES2 have very
2632 // little precision. Don't enable multisampling unless 8-bit render
2633 // buffer formats are available--instead fall back to 8-bit textures.
2634 if (rgb8_supported && offscreen_target_samples_ > 1) {
2635 offscreen_target_color_format_ = attrib_parser.alpha_size > 0 ?
2636 GL_RGBA8 : GL_RGB8;
2637 } else {
2638 offscreen_target_samples_ = 1;
2639 offscreen_target_color_format_ =
2640 attrib_parser.alpha_size > 0 || workarounds().disable_gl_rgb_format
2641 ? GL_RGBA
2642 : GL_RGB;
2645 // ANGLE only supports packed depth/stencil formats, so use it if it is
2646 // available.
2647 const bool depth24_stencil8_supported =
2648 feature_info_->feature_flags().packed_depth24_stencil8;
2649 VLOG(1) << "GL_OES_packed_depth_stencil "
2650 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
2651 if ((attrib_parser.depth_size > 0 || attrib_parser.stencil_size > 0) &&
2652 depth24_stencil8_supported) {
2653 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2654 offscreen_target_stencil_format_ = 0;
2655 } else {
2656 // It may be the case that this depth/stencil combination is not
2657 // supported, but this will be checked later by CheckFramebufferStatus.
2658 offscreen_target_depth_format_ = attrib_parser.depth_size > 0 ?
2659 GL_DEPTH_COMPONENT16 : 0;
2660 offscreen_target_stencil_format_ = attrib_parser.stencil_size > 0 ?
2661 GL_STENCIL_INDEX8 : 0;
2663 } else {
2664 offscreen_target_color_format_ =
2665 attrib_parser.alpha_size > 0 || workarounds().disable_gl_rgb_format
2666 ? GL_RGBA
2667 : GL_RGB;
2669 // If depth is requested at all, use the packed depth stencil format if
2670 // it's available, as some desktop GL drivers don't support any non-packed
2671 // formats for depth attachments.
2672 const bool depth24_stencil8_supported =
2673 feature_info_->feature_flags().packed_depth24_stencil8;
2674 VLOG(1) << "GL_EXT_packed_depth_stencil "
2675 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
2677 if ((attrib_parser.depth_size > 0 || attrib_parser.stencil_size > 0) &&
2678 depth24_stencil8_supported) {
2679 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2680 offscreen_target_stencil_format_ = 0;
2681 } else {
2682 offscreen_target_depth_format_ = attrib_parser.depth_size > 0 ?
2683 GL_DEPTH_COMPONENT : 0;
2684 offscreen_target_stencil_format_ = attrib_parser.stencil_size > 0 ?
2685 GL_STENCIL_INDEX : 0;
2689 offscreen_saved_color_format_ =
2690 attrib_parser.alpha_size > 0 || workarounds().disable_gl_rgb_format
2691 ? GL_RGBA
2692 : GL_RGB;
2694 // Create the target frame buffer. This is the one that the client renders
2695 // directly to.
2696 offscreen_target_frame_buffer_.reset(new BackFramebuffer(this));
2697 offscreen_target_frame_buffer_->Create();
2698 // Due to GLES2 format limitations, either the color texture (for
2699 // non-multisampling) or the color render buffer (for multisampling) will be
2700 // attached to the offscreen frame buffer. The render buffer has more
2701 // limited formats available to it, but the texture can't do multisampling.
2702 if (IsOffscreenBufferMultisampled()) {
2703 offscreen_target_color_render_buffer_.reset(new BackRenderbuffer(
2704 renderbuffer_manager(), memory_tracker(), &state_));
2705 offscreen_target_color_render_buffer_->Create();
2706 } else {
2707 offscreen_target_color_texture_.reset(new BackTexture(
2708 memory_tracker(), &state_));
2709 offscreen_target_color_texture_->Create();
2711 offscreen_target_depth_render_buffer_.reset(new BackRenderbuffer(
2712 renderbuffer_manager(), memory_tracker(), &state_));
2713 offscreen_target_depth_render_buffer_->Create();
2714 offscreen_target_stencil_render_buffer_.reset(new BackRenderbuffer(
2715 renderbuffer_manager(), memory_tracker(), &state_));
2716 offscreen_target_stencil_render_buffer_->Create();
2718 // Create the saved offscreen texture. The target frame buffer is copied
2719 // here when SwapBuffers is called.
2720 offscreen_saved_frame_buffer_.reset(new BackFramebuffer(this));
2721 offscreen_saved_frame_buffer_->Create();
2723 offscreen_saved_color_texture_.reset(new BackTexture(
2724 memory_tracker(), &state_));
2725 offscreen_saved_color_texture_->Create();
2727 // Allocate the render buffers at their initial size and check the status
2728 // of the frame buffers is okay.
2729 if (!ResizeOffscreenFrameBuffer(offscreen_size)) {
2730 LOG(ERROR) << "Could not allocate offscreen buffer storage.";
2731 Destroy(true);
2732 return false;
2735 state_.viewport_width = offscreen_size.width();
2736 state_.viewport_height = offscreen_size.height();
2738 // Allocate the offscreen saved color texture.
2739 DCHECK(offscreen_saved_color_format_);
2740 offscreen_saved_color_texture_->AllocateStorage(
2741 gfx::Size(1, 1), offscreen_saved_color_format_, true);
2743 offscreen_saved_frame_buffer_->AttachRenderTexture(
2744 offscreen_saved_color_texture_.get());
2745 if (offscreen_saved_frame_buffer_->CheckStatus() !=
2746 GL_FRAMEBUFFER_COMPLETE) {
2747 LOG(ERROR) << "Offscreen saved FBO was incomplete.";
2748 Destroy(true);
2749 return false;
2752 // Bind to the new default frame buffer (the offscreen target frame buffer).
2753 // This should now be associated with ID zero.
2754 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2755 } else {
2756 glBindFramebufferEXT(GL_FRAMEBUFFER, GetBackbufferServiceId());
2757 // These are NOT if the back buffer has these proprorties. They are
2758 // if we want the command buffer to enforce them regardless of what
2759 // the real backbuffer is assuming the real back buffer gives us more than
2760 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2761 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2762 // can't do anything about that.
2764 if (!surfaceless_) {
2765 GLint alpha_bits = 0;
2766 GLint depth_bits = 0;
2767 GLint stencil_bits = 0;
2769 bool default_fb = (GetBackbufferServiceId() == 0);
2771 if (feature_info_->gl_version_info().is_desktop_core_profile) {
2772 glGetFramebufferAttachmentParameterivEXT(
2773 GL_FRAMEBUFFER,
2774 default_fb ? GL_BACK_LEFT : GL_COLOR_ATTACHMENT0,
2775 GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE, &alpha_bits);
2776 glGetFramebufferAttachmentParameterivEXT(
2777 GL_FRAMEBUFFER,
2778 default_fb ? GL_DEPTH : GL_DEPTH_ATTACHMENT,
2779 GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE, &depth_bits);
2780 glGetFramebufferAttachmentParameterivEXT(
2781 GL_FRAMEBUFFER,
2782 default_fb ? GL_STENCIL : GL_STENCIL_ATTACHMENT,
2783 GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE, &stencil_bits);
2784 } else {
2785 glGetIntegerv(GL_ALPHA_BITS, &alpha_bits);
2786 glGetIntegerv(GL_DEPTH_BITS, &depth_bits);
2787 glGetIntegerv(GL_STENCIL_BITS, &stencil_bits);
2790 // This checks if the user requested RGBA and we have RGBA then RGBA. If
2791 // the user requested RGB then RGB. If the user did not specify a
2792 // preference than use whatever we were given. Same for DEPTH and STENCIL.
2793 back_buffer_color_format_ =
2794 (attrib_parser.alpha_size != 0 && alpha_bits > 0) ? GL_RGBA : GL_RGB;
2795 back_buffer_has_depth_ = attrib_parser.depth_size != 0 && depth_bits > 0;
2796 back_buffer_has_stencil_ =
2797 attrib_parser.stencil_size != 0 && stencil_bits > 0;
2800 state_.viewport_width = surface->GetSize().width();
2801 state_.viewport_height = surface->GetSize().height();
2804 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2805 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2806 // isn't well documented; it was discovered in the Khronos OpenGL ES
2807 // mailing list archives. It also implicitly enables the desktop GL
2808 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2809 // variable in fragment shaders.
2810 if (!feature_info_->gl_version_info().BehavesLikeGLES()) {
2811 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
2812 glEnable(GL_POINT_SPRITE);
2815 has_robustness_extension_ =
2816 context->HasExtension("GL_ARB_robustness") ||
2817 context->HasExtension("GL_KHR_robustness") ||
2818 context->HasExtension("GL_EXT_robustness");
2820 if (!InitializeShaderTranslator()) {
2821 return false;
2824 GLint viewport_params[4] = { 0 };
2825 glGetIntegerv(GL_MAX_VIEWPORT_DIMS, viewport_params);
2826 viewport_max_width_ = viewport_params[0];
2827 viewport_max_height_ = viewport_params[1];
2829 state_.scissor_width = state_.viewport_width;
2830 state_.scissor_height = state_.viewport_height;
2832 // Set all the default state because some GL drivers get it wrong.
2833 state_.InitCapabilities(NULL);
2834 state_.InitState(NULL);
2835 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
2837 DoBindBuffer(GL_ARRAY_BUFFER, 0);
2838 DoBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
2839 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2840 DoBindRenderbuffer(GL_RENDERBUFFER, 0);
2841 DoBindValueBufferCHROMIUM(GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM, 0);
2843 bool call_gl_clear = !surfaceless_;
2844 #if defined(OS_ANDROID)
2845 // Temporary workaround for Android WebView because this clear ignores the
2846 // clip and corrupts that external UI of the App. Not calling glClear is ok
2847 // because the system already clears the buffer before each draw. Proper
2848 // fix might be setting the scissor clip properly before initialize. See
2849 // crbug.com/259023 for details.
2850 call_gl_clear = surface_->GetHandle();
2851 #endif
2852 if (call_gl_clear) {
2853 // Clear the backbuffer.
2854 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2857 supports_post_sub_buffer_ = surface->SupportsPostSubBuffer();
2858 if (feature_info_->workarounds()
2859 .disable_post_sub_buffers_for_onscreen_surfaces &&
2860 !surface->IsOffscreen())
2861 supports_post_sub_buffer_ = false;
2863 if (feature_info_->workarounds().reverse_point_sprite_coord_origin) {
2864 glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT);
2867 if (feature_info_->workarounds().unbind_fbo_on_context_switch) {
2868 context_->SetUnbindFboOnMakeCurrent();
2871 // Only compositor contexts are known to use only the subset of GL
2872 // that can be safely migrated between the iGPU and the dGPU. Mark
2873 // those contexts as safe to forcibly transition between the GPUs.
2874 // http://crbug.com/180876, http://crbug.com/227228
2875 if (!offscreen)
2876 context_->SetSafeToForceGpuSwitch();
2878 async_pixel_transfer_manager_.reset(
2879 AsyncPixelTransferManager::Create(context.get()));
2880 async_pixel_transfer_manager_->Initialize(texture_manager());
2882 if (workarounds().gl_clear_broken) {
2883 DCHECK(!clear_framebuffer_blit_.get());
2884 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glClearWorkaroundInit");
2885 clear_framebuffer_blit_.reset(new ClearFramebufferResourceManager(this));
2886 if (LOCAL_PEEK_GL_ERROR("glClearWorkaroundInit") != GL_NO_ERROR)
2887 return false;
2890 framebuffer_manager()->AddObserver(this);
2892 return true;
2895 Capabilities GLES2DecoderImpl::GetCapabilities() {
2896 DCHECK(initialized());
2898 Capabilities caps;
2899 caps.VisitPrecisions([](GLenum shader, GLenum type,
2900 Capabilities::ShaderPrecision* shader_precision) {
2901 GLint range[2] = {0, 0};
2902 GLint precision = 0;
2903 GetShaderPrecisionFormatImpl(shader, type, range, &precision);
2904 shader_precision->min_range = range[0];
2905 shader_precision->max_range = range[1];
2906 shader_precision->precision = precision;
2908 DoGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS,
2909 &caps.max_combined_texture_image_units);
2910 DoGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &caps.max_cube_map_texture_size);
2911 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS,
2912 &caps.max_fragment_uniform_vectors);
2913 DoGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &caps.max_renderbuffer_size);
2914 DoGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &caps.max_texture_image_units);
2915 DoGetIntegerv(GL_MAX_TEXTURE_SIZE, &caps.max_texture_size);
2916 DoGetIntegerv(GL_MAX_VARYING_VECTORS, &caps.max_varying_vectors);
2917 DoGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &caps.max_vertex_attribs);
2918 DoGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS,
2919 &caps.max_vertex_texture_image_units);
2920 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS,
2921 &caps.max_vertex_uniform_vectors);
2922 DoGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS,
2923 &caps.num_compressed_texture_formats);
2924 DoGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS, &caps.num_shader_binary_formats);
2925 DoGetIntegerv(GL_BIND_GENERATES_RESOURCE_CHROMIUM,
2926 &caps.bind_generates_resource_chromium);
2927 if (unsafe_es3_apis_enabled()) {
2928 // TODO(zmo): Note that some parameter values could be more than 32-bit,
2929 // but for now we clamp them to 32-bit max.
2930 DoGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &caps.max_3d_texture_size);
2931 DoGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &caps.max_array_texture_layers);
2932 DoGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &caps.max_color_attachments);
2933 DoGetIntegerv(GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS,
2934 &caps.max_combined_fragment_uniform_components);
2935 DoGetIntegerv(GL_MAX_COMBINED_UNIFORM_BLOCKS,
2936 &caps.max_combined_uniform_blocks);
2937 DoGetIntegerv(GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS,
2938 &caps.max_combined_vertex_uniform_components);
2939 DoGetIntegerv(GL_MAX_DRAW_BUFFERS, &caps.max_draw_buffers);
2940 DoGetIntegerv(GL_MAX_ELEMENT_INDEX, &caps.max_element_index);
2941 DoGetIntegerv(GL_MAX_ELEMENTS_INDICES, &caps.max_elements_indices);
2942 DoGetIntegerv(GL_MAX_ELEMENTS_VERTICES, &caps.max_elements_vertices);
2943 DoGetIntegerv(GL_MAX_FRAGMENT_INPUT_COMPONENTS,
2944 &caps.max_fragment_input_components);
2945 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_BLOCKS,
2946 &caps.max_fragment_uniform_blocks);
2947 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS,
2948 &caps.max_fragment_uniform_components);
2949 DoGetIntegerv(GL_MAX_PROGRAM_TEXEL_OFFSET,
2950 &caps.max_program_texel_offset);
2951 DoGetIntegerv(GL_MAX_SAMPLES, &caps.max_samples);
2952 DoGetIntegerv(GL_MAX_SERVER_WAIT_TIMEOUT, &caps.max_server_wait_timeout);
2953 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS,
2954 &caps.max_transform_feedback_interleaved_components);
2955 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS,
2956 &caps.max_transform_feedback_separate_attribs);
2957 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS,
2958 &caps.max_transform_feedback_separate_components);
2959 DoGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &caps.max_uniform_block_size);
2960 DoGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS,
2961 &caps.max_uniform_buffer_bindings);
2962 DoGetIntegerv(GL_MAX_VARYING_COMPONENTS, &caps.max_varying_components);
2963 DoGetIntegerv(GL_MAX_VERTEX_OUTPUT_COMPONENTS,
2964 &caps.max_vertex_output_components);
2965 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_BLOCKS,
2966 &caps.max_vertex_uniform_blocks);
2967 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS,
2968 &caps.max_vertex_uniform_components);
2969 DoGetIntegerv(GL_MIN_PROGRAM_TEXEL_OFFSET, &caps.min_program_texel_offset);
2970 DoGetIntegerv(GL_NUM_EXTENSIONS, &caps.num_extensions);
2971 DoGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS,
2972 &caps.num_program_binary_formats);
2973 DoGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT,
2974 &caps.uniform_buffer_offset_alignment);
2975 // TODO(zmo): once we switch to MANGLE, we should query version numbers.
2976 caps.major_version = 3;
2977 caps.minor_version = 0;
2980 caps.egl_image_external =
2981 feature_info_->feature_flags().oes_egl_image_external;
2982 caps.texture_format_atc =
2983 feature_info_->feature_flags().ext_texture_format_atc;
2984 caps.texture_format_bgra8888 =
2985 feature_info_->feature_flags().ext_texture_format_bgra8888;
2986 caps.texture_format_dxt1 =
2987 feature_info_->feature_flags().ext_texture_format_dxt1;
2988 caps.texture_format_dxt5 =
2989 feature_info_->feature_flags().ext_texture_format_dxt5;
2990 caps.texture_format_etc1 =
2991 feature_info_->feature_flags().oes_compressed_etc1_rgb8_texture;
2992 caps.texture_format_etc1_npot =
2993 caps.texture_format_etc1 && !workarounds().etc1_power_of_two_only;
2994 caps.texture_rectangle = feature_info_->feature_flags().arb_texture_rectangle;
2995 caps.texture_usage = feature_info_->feature_flags().angle_texture_usage;
2996 caps.texture_storage = feature_info_->feature_flags().ext_texture_storage;
2997 caps.discard_framebuffer =
2998 feature_info_->feature_flags().ext_discard_framebuffer;
2999 caps.sync_query = feature_info_->feature_flags().chromium_sync_query;
3001 #if defined(OS_MACOSX)
3002 // This is unconditionally true on mac, no need to test for it at runtime.
3003 caps.iosurface = true;
3004 #endif
3006 caps.post_sub_buffer = supports_post_sub_buffer_;
3007 caps.image = true;
3009 caps.blend_equation_advanced =
3010 feature_info_->feature_flags().blend_equation_advanced;
3011 caps.blend_equation_advanced_coherent =
3012 feature_info_->feature_flags().blend_equation_advanced_coherent;
3013 caps.texture_rg = feature_info_->feature_flags().ext_texture_rg;
3014 return caps;
3017 void GLES2DecoderImpl::UpdateCapabilities() {
3018 util_.set_num_compressed_texture_formats(
3019 validators_->compressed_texture_format.GetValues().size());
3020 util_.set_num_shader_binary_formats(
3021 validators_->shader_binary_format.GetValues().size());
3024 bool GLES2DecoderImpl::InitializeShaderTranslator() {
3025 TRACE_EVENT0("gpu", "GLES2DecoderImpl::InitializeShaderTranslator");
3027 if (!use_shader_translator_) {
3028 return true;
3030 ShBuiltInResources resources;
3031 ShInitBuiltInResources(&resources);
3032 resources.MaxVertexAttribs = group_->max_vertex_attribs();
3033 resources.MaxVertexUniformVectors =
3034 group_->max_vertex_uniform_vectors();
3035 resources.MaxVaryingVectors = group_->max_varying_vectors();
3036 resources.MaxVertexTextureImageUnits =
3037 group_->max_vertex_texture_image_units();
3038 resources.MaxCombinedTextureImageUnits = group_->max_texture_units();
3039 resources.MaxTextureImageUnits = group_->max_texture_image_units();
3040 resources.MaxFragmentUniformVectors =
3041 group_->max_fragment_uniform_vectors();
3042 resources.MaxDrawBuffers = group_->max_draw_buffers();
3043 resources.MaxExpressionComplexity = 256;
3044 resources.MaxCallStackDepth = 256;
3046 GLint range[2] = { 0, 0 };
3047 GLint precision = 0;
3048 GetShaderPrecisionFormatImpl(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT,
3049 range, &precision);
3050 resources.FragmentPrecisionHigh =
3051 PrecisionMeetsSpecForHighpFloat(range[0], range[1], precision);
3053 if (force_webgl_glsl_validation_) {
3054 resources.OES_standard_derivatives = derivatives_explicitly_enabled_;
3055 resources.EXT_frag_depth = frag_depth_explicitly_enabled_;
3056 resources.EXT_draw_buffers = draw_buffers_explicitly_enabled_;
3057 if (!draw_buffers_explicitly_enabled_)
3058 resources.MaxDrawBuffers = 1;
3059 resources.EXT_shader_texture_lod = shader_texture_lod_explicitly_enabled_;
3060 resources.NV_draw_buffers =
3061 draw_buffers_explicitly_enabled_ && features().nv_draw_buffers;
3062 } else {
3063 resources.OES_standard_derivatives =
3064 features().oes_standard_derivatives ? 1 : 0;
3065 resources.ARB_texture_rectangle =
3066 features().arb_texture_rectangle ? 1 : 0;
3067 resources.OES_EGL_image_external =
3068 features().oes_egl_image_external ? 1 : 0;
3069 resources.EXT_draw_buffers =
3070 features().ext_draw_buffers ? 1 : 0;
3071 resources.EXT_frag_depth =
3072 features().ext_frag_depth ? 1 : 0;
3073 resources.EXT_shader_texture_lod =
3074 features().ext_shader_texture_lod ? 1 : 0;
3075 resources.NV_draw_buffers =
3076 features().nv_draw_buffers ? 1 : 0;
3079 ShShaderSpec shader_spec;
3080 if (force_webgl_glsl_validation_) {
3081 shader_spec = unsafe_es3_apis_enabled() ? SH_WEBGL2_SPEC : SH_WEBGL_SPEC;
3082 } else {
3083 shader_spec = unsafe_es3_apis_enabled() ? SH_GLES3_SPEC : SH_GLES2_SPEC;
3086 if ((shader_spec == SH_WEBGL_SPEC || shader_spec == SH_WEBGL2_SPEC) &&
3087 features().enable_shader_name_hashing)
3088 resources.HashFunction = &CityHash64;
3089 else
3090 resources.HashFunction = NULL;
3091 ShaderTranslatorInterface::GlslImplementationType implementation_type =
3092 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 ?
3093 ShaderTranslatorInterface::kGlslES : ShaderTranslatorInterface::kGlsl;
3094 int driver_bug_workarounds = 0;
3095 if (workarounds().needs_glsl_built_in_function_emulation)
3096 driver_bug_workarounds |= SH_EMULATE_BUILT_IN_FUNCTIONS;
3097 if (workarounds().init_gl_position_in_vertex_shader)
3098 driver_bug_workarounds |= SH_INIT_GL_POSITION;
3099 if (workarounds().unfold_short_circuit_as_ternary_operation)
3100 driver_bug_workarounds |= SH_UNFOLD_SHORT_CIRCUIT;
3101 if (workarounds().init_varyings_without_static_use)
3102 driver_bug_workarounds |= SH_INIT_VARYINGS_WITHOUT_STATIC_USE;
3103 if (workarounds().unroll_for_loop_with_sampler_array_index)
3104 driver_bug_workarounds |= SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX;
3105 if (workarounds().scalarize_vec_and_mat_constructor_args)
3106 driver_bug_workarounds |= SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS;
3107 if (workarounds().regenerate_struct_names)
3108 driver_bug_workarounds |= SH_REGENERATE_STRUCT_NAMES;
3110 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
3111 switches::kEmulateShaderPrecision))
3112 resources.WEBGL_debug_shader_precision = true;
3114 vertex_translator_ = shader_translator_cache()->GetTranslator(
3115 GL_VERTEX_SHADER,
3116 shader_spec,
3117 &resources,
3118 implementation_type,
3119 static_cast<ShCompileOptions>(driver_bug_workarounds));
3120 if (!vertex_translator_.get()) {
3121 LOG(ERROR) << "Could not initialize vertex shader translator.";
3122 Destroy(true);
3123 return false;
3126 fragment_translator_ = shader_translator_cache()->GetTranslator(
3127 GL_FRAGMENT_SHADER,
3128 shader_spec,
3129 &resources,
3130 implementation_type,
3131 static_cast<ShCompileOptions>(driver_bug_workarounds));
3132 if (!fragment_translator_.get()) {
3133 LOG(ERROR) << "Could not initialize fragment shader translator.";
3134 Destroy(true);
3135 return false;
3137 return true;
3140 bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
3141 for (GLsizei ii = 0; ii < n; ++ii) {
3142 if (GetBuffer(client_ids[ii])) {
3143 return false;
3146 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3147 glGenBuffersARB(n, service_ids.get());
3148 for (GLsizei ii = 0; ii < n; ++ii) {
3149 CreateBuffer(client_ids[ii], service_ids[ii]);
3151 return true;
3154 bool GLES2DecoderImpl::GenFramebuffersHelper(
3155 GLsizei n, const GLuint* client_ids) {
3156 for (GLsizei ii = 0; ii < n; ++ii) {
3157 if (GetFramebuffer(client_ids[ii])) {
3158 return false;
3161 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3162 glGenFramebuffersEXT(n, service_ids.get());
3163 for (GLsizei ii = 0; ii < n; ++ii) {
3164 CreateFramebuffer(client_ids[ii], service_ids[ii]);
3166 return true;
3169 bool GLES2DecoderImpl::GenRenderbuffersHelper(
3170 GLsizei n, const GLuint* client_ids) {
3171 for (GLsizei ii = 0; ii < n; ++ii) {
3172 if (GetRenderbuffer(client_ids[ii])) {
3173 return false;
3176 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3177 glGenRenderbuffersEXT(n, service_ids.get());
3178 for (GLsizei ii = 0; ii < n; ++ii) {
3179 CreateRenderbuffer(client_ids[ii], service_ids[ii]);
3181 return true;
3184 bool GLES2DecoderImpl::GenValuebuffersCHROMIUMHelper(GLsizei n,
3185 const GLuint* client_ids) {
3186 for (GLsizei ii = 0; ii < n; ++ii) {
3187 if (GetValuebuffer(client_ids[ii])) {
3188 return false;
3191 for (GLsizei ii = 0; ii < n; ++ii) {
3192 CreateValuebuffer(client_ids[ii]);
3194 return true;
3197 bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
3198 for (GLsizei ii = 0; ii < n; ++ii) {
3199 if (GetTexture(client_ids[ii])) {
3200 return false;
3203 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3204 glGenTextures(n, service_ids.get());
3205 for (GLsizei ii = 0; ii < n; ++ii) {
3206 CreateTexture(client_ids[ii], service_ids[ii]);
3208 return true;
3211 void GLES2DecoderImpl::DeleteBuffersHelper(
3212 GLsizei n, const GLuint* client_ids) {
3213 for (GLsizei ii = 0; ii < n; ++ii) {
3214 Buffer* buffer = GetBuffer(client_ids[ii]);
3215 if (buffer && !buffer->IsDeleted()) {
3216 buffer->RemoveMappedRange();
3217 state_.vertex_attrib_manager->Unbind(buffer);
3218 if (state_.bound_array_buffer.get() == buffer) {
3219 state_.bound_array_buffer = NULL;
3221 RemoveBuffer(client_ids[ii]);
3226 void GLES2DecoderImpl::DeleteFramebuffersHelper(
3227 GLsizei n, const GLuint* client_ids) {
3228 bool supports_separate_framebuffer_binds =
3229 features().chromium_framebuffer_multisample;
3231 for (GLsizei ii = 0; ii < n; ++ii) {
3232 Framebuffer* framebuffer =
3233 GetFramebuffer(client_ids[ii]);
3234 if (framebuffer && !framebuffer->IsDeleted()) {
3235 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
3236 GLenum target = supports_separate_framebuffer_binds ?
3237 GL_DRAW_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
3239 // Unbind attachments on FBO before deletion.
3240 if (workarounds().unbind_attachments_on_bound_render_fbo_delete)
3241 framebuffer->DoUnbindGLAttachmentsForWorkaround(target);
3243 glBindFramebufferEXT(target, GetBackbufferServiceId());
3244 framebuffer_state_.bound_draw_framebuffer = NULL;
3245 framebuffer_state_.clear_state_dirty = true;
3247 if (framebuffer == framebuffer_state_.bound_read_framebuffer.get()) {
3248 framebuffer_state_.bound_read_framebuffer = NULL;
3249 GLenum target = supports_separate_framebuffer_binds ?
3250 GL_READ_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
3251 glBindFramebufferEXT(target, GetBackbufferServiceId());
3253 OnFboChanged();
3254 RemoveFramebuffer(client_ids[ii]);
3259 void GLES2DecoderImpl::DeleteRenderbuffersHelper(
3260 GLsizei n, const GLuint* client_ids) {
3261 bool supports_separate_framebuffer_binds =
3262 features().chromium_framebuffer_multisample;
3263 for (GLsizei ii = 0; ii < n; ++ii) {
3264 Renderbuffer* renderbuffer =
3265 GetRenderbuffer(client_ids[ii]);
3266 if (renderbuffer && !renderbuffer->IsDeleted()) {
3267 if (state_.bound_renderbuffer.get() == renderbuffer) {
3268 state_.bound_renderbuffer = NULL;
3270 // Unbind from current framebuffers.
3271 if (supports_separate_framebuffer_binds) {
3272 if (framebuffer_state_.bound_read_framebuffer.get()) {
3273 framebuffer_state_.bound_read_framebuffer
3274 ->UnbindRenderbuffer(GL_READ_FRAMEBUFFER_EXT, renderbuffer);
3276 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3277 framebuffer_state_.bound_draw_framebuffer
3278 ->UnbindRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT, renderbuffer);
3280 } else {
3281 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3282 framebuffer_state_.bound_draw_framebuffer
3283 ->UnbindRenderbuffer(GL_FRAMEBUFFER, renderbuffer);
3286 framebuffer_state_.clear_state_dirty = true;
3287 RemoveRenderbuffer(client_ids[ii]);
3292 void GLES2DecoderImpl::DeleteValuebuffersCHROMIUMHelper(
3293 GLsizei n,
3294 const GLuint* client_ids) {
3295 for (GLsizei ii = 0; ii < n; ++ii) {
3296 Valuebuffer* valuebuffer = GetValuebuffer(client_ids[ii]);
3297 if (valuebuffer) {
3298 if (state_.bound_valuebuffer.get() == valuebuffer) {
3299 state_.bound_valuebuffer = NULL;
3301 RemoveValuebuffer(client_ids[ii]);
3306 void GLES2DecoderImpl::DeleteTexturesHelper(
3307 GLsizei n, const GLuint* client_ids) {
3308 bool supports_separate_framebuffer_binds =
3309 features().chromium_framebuffer_multisample;
3310 for (GLsizei ii = 0; ii < n; ++ii) {
3311 TextureRef* texture_ref = GetTexture(client_ids[ii]);
3312 if (texture_ref) {
3313 Texture* texture = texture_ref->texture();
3314 if (texture->IsAttachedToFramebuffer()) {
3315 framebuffer_state_.clear_state_dirty = true;
3317 // Unbind texture_ref from texture_ref units.
3318 for (size_t jj = 0; jj < state_.texture_units.size(); ++jj) {
3319 state_.texture_units[jj].Unbind(texture_ref);
3321 // Unbind from current framebuffers.
3322 if (supports_separate_framebuffer_binds) {
3323 if (framebuffer_state_.bound_read_framebuffer.get()) {
3324 framebuffer_state_.bound_read_framebuffer
3325 ->UnbindTexture(GL_READ_FRAMEBUFFER_EXT, texture_ref);
3327 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3328 framebuffer_state_.bound_draw_framebuffer
3329 ->UnbindTexture(GL_DRAW_FRAMEBUFFER_EXT, texture_ref);
3331 } else {
3332 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3333 framebuffer_state_.bound_draw_framebuffer
3334 ->UnbindTexture(GL_FRAMEBUFFER, texture_ref);
3337 #if defined(OS_MACOSX)
3338 GLuint service_id = texture->service_id();
3339 if (texture->target() == GL_TEXTURE_RECTANGLE_ARB) {
3340 ReleaseIOSurfaceForTexture(service_id);
3342 #endif
3343 RemoveTexture(client_ids[ii]);
3348 // } // anonymous namespace
3350 bool GLES2DecoderImpl::MakeCurrent() {
3351 if (!context_.get())
3352 return false;
3354 if (WasContextLost()) {
3355 LOG(ERROR) << " GLES2DecoderImpl: Trying to make lost context current.";
3356 return false;
3359 if (!context_->MakeCurrent(surface_.get())) {
3360 LOG(ERROR) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
3361 MarkContextLost(error::kMakeCurrentFailed);
3362 group_->LoseContexts(error::kUnknown);
3363 return false;
3366 if (CheckResetStatus()) {
3367 LOG(ERROR)
3368 << " GLES2DecoderImpl: Context reset detected after MakeCurrent.";
3369 group_->LoseContexts(error::kUnknown);
3370 return false;
3373 ProcessFinishedAsyncTransfers();
3375 // Rebind the FBO if it was unbound by the context.
3376 if (workarounds().unbind_fbo_on_context_switch)
3377 RestoreFramebufferBindings();
3379 framebuffer_state_.clear_state_dirty = true;
3381 return true;
3384 void GLES2DecoderImpl::ProcessFinishedAsyncTransfers() {
3385 ProcessPendingReadPixels();
3386 if (engine() && query_manager_.get())
3387 query_manager_->ProcessPendingTransferQueries();
3389 // TODO(epenner): Is there a better place to do this?
3390 // This needs to occur before we execute any batch of commands
3391 // from the client, as the client may have recieved an async
3392 // completion while issuing those commands.
3393 // "DidFlushStart" would be ideal if we had such a callback.
3394 async_pixel_transfer_manager_->BindCompletedAsyncTransfers();
3397 static void RebindCurrentFramebuffer(
3398 GLenum target,
3399 Framebuffer* framebuffer,
3400 GLuint back_buffer_service_id) {
3401 GLuint framebuffer_id = framebuffer ? framebuffer->service_id() : 0;
3403 if (framebuffer_id == 0) {
3404 framebuffer_id = back_buffer_service_id;
3407 glBindFramebufferEXT(target, framebuffer_id);
3410 void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
3411 framebuffer_state_.clear_state_dirty = true;
3413 if (!features().chromium_framebuffer_multisample) {
3414 RebindCurrentFramebuffer(
3415 GL_FRAMEBUFFER,
3416 framebuffer_state_.bound_draw_framebuffer.get(),
3417 GetBackbufferServiceId());
3418 } else {
3419 RebindCurrentFramebuffer(
3420 GL_READ_FRAMEBUFFER_EXT,
3421 framebuffer_state_.bound_read_framebuffer.get(),
3422 GetBackbufferServiceId());
3423 RebindCurrentFramebuffer(
3424 GL_DRAW_FRAMEBUFFER_EXT,
3425 framebuffer_state_.bound_draw_framebuffer.get(),
3426 GetBackbufferServiceId());
3428 OnFboChanged();
3431 bool GLES2DecoderImpl::CheckFramebufferValid(
3432 Framebuffer* framebuffer,
3433 GLenum target, const char* func_name) {
3434 if (!framebuffer) {
3435 if (surfaceless_)
3436 return false;
3437 if (backbuffer_needs_clear_bits_) {
3438 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3439 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1.f);
3440 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3441 glClearStencil(0);
3442 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
3443 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
3444 glClearDepth(1.0f);
3445 state_.SetDeviceDepthMask(GL_TRUE);
3446 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
3447 bool reset_draw_buffer = false;
3448 if ((backbuffer_needs_clear_bits_ & GL_COLOR_BUFFER_BIT) != 0 &&
3449 group_->draw_buffer() == GL_NONE) {
3450 reset_draw_buffer = true;
3451 GLenum buf = GL_BACK;
3452 if (GetBackbufferServiceId() != 0) // emulated backbuffer
3453 buf = GL_COLOR_ATTACHMENT0;
3454 glDrawBuffersARB(1, &buf);
3456 glClear(backbuffer_needs_clear_bits_);
3457 if (reset_draw_buffer) {
3458 GLenum buf = GL_NONE;
3459 glDrawBuffersARB(1, &buf);
3461 backbuffer_needs_clear_bits_ = 0;
3462 RestoreClearState();
3464 return true;
3467 if (framebuffer_manager()->IsComplete(framebuffer)) {
3468 return true;
3471 GLenum completeness = framebuffer->IsPossiblyComplete();
3472 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
3473 LOCAL_SET_GL_ERROR(
3474 GL_INVALID_FRAMEBUFFER_OPERATION, func_name, "framebuffer incomplete");
3475 return false;
3478 // Are all the attachments cleared?
3479 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
3480 texture_manager()->HaveUnclearedMips()) {
3481 if (!framebuffer->IsCleared()) {
3482 // Can we clear them?
3483 if (framebuffer->GetStatus(texture_manager(), target) !=
3484 GL_FRAMEBUFFER_COMPLETE) {
3485 LOCAL_SET_GL_ERROR(
3486 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
3487 "framebuffer incomplete (clear)");
3488 return false;
3490 ClearUnclearedAttachments(target, framebuffer);
3494 if (!framebuffer_manager()->IsComplete(framebuffer)) {
3495 if (framebuffer->GetStatus(texture_manager(), target) !=
3496 GL_FRAMEBUFFER_COMPLETE) {
3497 LOCAL_SET_GL_ERROR(
3498 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
3499 "framebuffer incomplete (check)");
3500 return false;
3502 framebuffer_manager()->MarkAsComplete(framebuffer);
3505 // NOTE: At this point we don't know if the framebuffer is complete but
3506 // we DO know that everything that needs to be cleared has been cleared.
3507 return true;
3510 bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name) {
3511 if (!features().chromium_framebuffer_multisample) {
3512 bool valid = CheckFramebufferValid(
3513 framebuffer_state_.bound_draw_framebuffer.get(), GL_FRAMEBUFFER_EXT,
3514 func_name);
3516 if (valid)
3517 OnUseFramebuffer();
3519 return valid;
3521 return CheckFramebufferValid(framebuffer_state_.bound_draw_framebuffer.get(),
3522 GL_DRAW_FRAMEBUFFER_EXT,
3523 func_name) &&
3524 CheckFramebufferValid(framebuffer_state_.bound_read_framebuffer.get(),
3525 GL_READ_FRAMEBUFFER_EXT,
3526 func_name);
3529 bool GLES2DecoderImpl::CheckBoundReadFramebufferColorAttachment(
3530 const char* func_name) {
3531 Framebuffer* framebuffer = features().chromium_framebuffer_multisample ?
3532 framebuffer_state_.bound_read_framebuffer.get() :
3533 framebuffer_state_.bound_draw_framebuffer.get();
3534 if (!framebuffer)
3535 return true;
3536 if (framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0) == NULL) {
3537 LOCAL_SET_GL_ERROR(
3538 GL_INVALID_OPERATION, func_name, "no color image attached");
3539 return false;
3541 return true;
3544 bool GLES2DecoderImpl::FormsTextureCopyingFeedbackLoop(
3545 TextureRef* texture, GLint level) {
3546 Framebuffer* framebuffer = features().chromium_framebuffer_multisample ?
3547 framebuffer_state_.bound_read_framebuffer.get() :
3548 framebuffer_state_.bound_draw_framebuffer.get();
3549 if (!framebuffer)
3550 return false;
3551 const Framebuffer::Attachment* attachment = framebuffer->GetAttachment(
3552 GL_COLOR_ATTACHMENT0);
3553 if (!attachment)
3554 return false;
3555 return attachment->FormsFeedbackLoop(texture, level);
3558 gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
3559 Framebuffer* framebuffer =
3560 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3561 if (framebuffer != NULL) {
3562 const Framebuffer::Attachment* attachment =
3563 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
3564 if (attachment) {
3565 return gfx::Size(attachment->width(), attachment->height());
3567 return gfx::Size(0, 0);
3568 } else if (offscreen_target_frame_buffer_.get()) {
3569 return offscreen_size_;
3570 } else {
3571 return surface_->GetSize();
3575 GLenum GLES2DecoderImpl::GetBoundReadFrameBufferTextureType() {
3576 Framebuffer* framebuffer =
3577 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3578 if (framebuffer != NULL) {
3579 return framebuffer->GetColorAttachmentTextureType();
3580 } else {
3581 return GL_UNSIGNED_BYTE;
3585 GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
3586 Framebuffer* framebuffer =
3587 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3588 if (framebuffer != NULL) {
3589 return framebuffer->GetColorAttachmentFormat();
3590 } else if (offscreen_target_frame_buffer_.get()) {
3591 return offscreen_target_color_format_;
3592 } else {
3593 return back_buffer_color_format_;
3597 GLenum GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
3598 Framebuffer* framebuffer =
3599 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3600 if (framebuffer != NULL) {
3601 return framebuffer->GetColorAttachmentFormat();
3602 } else if (offscreen_target_frame_buffer_.get()) {
3603 return offscreen_target_color_format_;
3604 } else {
3605 return back_buffer_color_format_;
3609 void GLES2DecoderImpl::UpdateParentTextureInfo() {
3610 if (!offscreen_saved_color_texture_info_.get())
3611 return;
3612 GLenum target = offscreen_saved_color_texture_info_->texture()->target();
3613 glBindTexture(target, offscreen_saved_color_texture_info_->service_id());
3614 texture_manager()->SetLevelInfo(
3615 offscreen_saved_color_texture_info_.get(),
3616 GL_TEXTURE_2D,
3617 0, // level
3618 GL_RGBA,
3619 offscreen_size_.width(),
3620 offscreen_size_.height(),
3621 1, // depth
3622 0, // border
3623 GL_RGBA,
3624 GL_UNSIGNED_BYTE,
3625 true);
3626 texture_manager()->SetParameteri(
3627 "UpdateParentTextureInfo",
3628 GetErrorState(),
3629 offscreen_saved_color_texture_info_.get(),
3630 GL_TEXTURE_MAG_FILTER,
3631 GL_LINEAR);
3632 texture_manager()->SetParameteri(
3633 "UpdateParentTextureInfo",
3634 GetErrorState(),
3635 offscreen_saved_color_texture_info_.get(),
3636 GL_TEXTURE_MIN_FILTER,
3637 GL_LINEAR);
3638 texture_manager()->SetParameteri(
3639 "UpdateParentTextureInfo",
3640 GetErrorState(),
3641 offscreen_saved_color_texture_info_.get(),
3642 GL_TEXTURE_WRAP_S,
3643 GL_CLAMP_TO_EDGE);
3644 texture_manager()->SetParameteri(
3645 "UpdateParentTextureInfo",
3646 GetErrorState(),
3647 offscreen_saved_color_texture_info_.get(),
3648 GL_TEXTURE_WRAP_T,
3649 GL_CLAMP_TO_EDGE);
3650 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
3651 &state_, target);
3652 glBindTexture(target, texture_ref ? texture_ref->service_id() : 0);
3655 void GLES2DecoderImpl::SetResizeCallback(
3656 const base::Callback<void(gfx::Size, float)>& callback) {
3657 resize_callback_ = callback;
3660 Logger* GLES2DecoderImpl::GetLogger() {
3661 return &logger_;
3664 void GLES2DecoderImpl::BeginDecoding() {
3665 gpu_tracer_->BeginDecoding();
3666 gpu_trace_commands_ = gpu_tracer_->IsTracing() && *gpu_decoder_category_;
3667 gpu_debug_commands_ = log_commands() || debug() || gpu_trace_commands_ ||
3668 (*cb_command_trace_category_ != 0);
3671 void GLES2DecoderImpl::EndDecoding() {
3672 gpu_tracer_->EndDecoding();
3675 ErrorState* GLES2DecoderImpl::GetErrorState() {
3676 return state_.GetErrorState();
3679 void GLES2DecoderImpl::SetShaderCacheCallback(
3680 const ShaderCacheCallback& callback) {
3681 shader_cache_callback_ = callback;
3684 void GLES2DecoderImpl::SetWaitSyncPointCallback(
3685 const WaitSyncPointCallback& callback) {
3686 wait_sync_point_callback_ = callback;
3689 AsyncPixelTransferManager*
3690 GLES2DecoderImpl::GetAsyncPixelTransferManager() {
3691 return async_pixel_transfer_manager_.get();
3694 void GLES2DecoderImpl::ResetAsyncPixelTransferManagerForTest() {
3695 async_pixel_transfer_manager_.reset();
3698 void GLES2DecoderImpl::SetAsyncPixelTransferManagerForTest(
3699 AsyncPixelTransferManager* manager) {
3700 async_pixel_transfer_manager_ = make_scoped_ptr(manager);
3703 bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
3704 uint32* service_texture_id) {
3705 TextureRef* texture_ref = texture_manager()->GetTexture(client_texture_id);
3706 if (texture_ref) {
3707 *service_texture_id = texture_ref->service_id();
3708 return true;
3710 return false;
3713 uint32 GLES2DecoderImpl::GetTextureUploadCount() {
3714 return texture_state_.texture_upload_count +
3715 async_pixel_transfer_manager_->GetTextureUploadCount();
3718 base::TimeDelta GLES2DecoderImpl::GetTotalTextureUploadTime() {
3719 return texture_state_.total_texture_upload_time +
3720 async_pixel_transfer_manager_->GetTotalTextureUploadTime();
3723 base::TimeDelta GLES2DecoderImpl::GetTotalProcessingCommandsTime() {
3724 return total_processing_commands_time_;
3727 void GLES2DecoderImpl::AddProcessingCommandsTime(base::TimeDelta time) {
3728 total_processing_commands_time_ += time;
3731 void GLES2DecoderImpl::Destroy(bool have_context) {
3732 if (!initialized())
3733 return;
3735 DCHECK(!have_context || context_->IsCurrent(NULL));
3737 // Unbind everything.
3738 state_.vertex_attrib_manager = NULL;
3739 state_.default_vertex_attrib_manager = NULL;
3740 state_.texture_units.clear();
3741 state_.bound_array_buffer = NULL;
3742 state_.current_queries.clear();
3743 framebuffer_state_.bound_read_framebuffer = NULL;
3744 framebuffer_state_.bound_draw_framebuffer = NULL;
3745 state_.bound_renderbuffer = NULL;
3746 state_.bound_valuebuffer = NULL;
3748 if (offscreen_saved_color_texture_info_.get()) {
3749 DCHECK(offscreen_target_color_texture_);
3750 DCHECK_EQ(offscreen_saved_color_texture_info_->service_id(),
3751 offscreen_saved_color_texture_->id());
3752 offscreen_saved_color_texture_->Invalidate();
3753 offscreen_saved_color_texture_info_ = NULL;
3755 if (have_context) {
3756 if (copy_texture_CHROMIUM_.get()) {
3757 copy_texture_CHROMIUM_->Destroy();
3758 copy_texture_CHROMIUM_.reset();
3761 clear_framebuffer_blit_.reset();
3763 if (state_.current_program.get()) {
3764 program_manager()->UnuseProgram(shader_manager(),
3765 state_.current_program.get());
3768 if (attrib_0_buffer_id_) {
3769 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
3771 if (fixed_attrib_buffer_id_) {
3772 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_);
3775 if (validation_texture_) {
3776 glDeleteTextures(1, &validation_texture_);
3777 glDeleteFramebuffersEXT(1, &validation_fbo_multisample_);
3778 glDeleteFramebuffersEXT(1, &validation_fbo_);
3781 if (offscreen_target_frame_buffer_.get())
3782 offscreen_target_frame_buffer_->Destroy();
3783 if (offscreen_target_color_texture_.get())
3784 offscreen_target_color_texture_->Destroy();
3785 if (offscreen_target_color_render_buffer_.get())
3786 offscreen_target_color_render_buffer_->Destroy();
3787 if (offscreen_target_depth_render_buffer_.get())
3788 offscreen_target_depth_render_buffer_->Destroy();
3789 if (offscreen_target_stencil_render_buffer_.get())
3790 offscreen_target_stencil_render_buffer_->Destroy();
3791 if (offscreen_saved_frame_buffer_.get())
3792 offscreen_saved_frame_buffer_->Destroy();
3793 if (offscreen_saved_color_texture_.get())
3794 offscreen_saved_color_texture_->Destroy();
3795 if (offscreen_resolved_frame_buffer_.get())
3796 offscreen_resolved_frame_buffer_->Destroy();
3797 if (offscreen_resolved_color_texture_.get())
3798 offscreen_resolved_color_texture_->Destroy();
3799 } else {
3800 if (offscreen_target_frame_buffer_.get())
3801 offscreen_target_frame_buffer_->Invalidate();
3802 if (offscreen_target_color_texture_.get())
3803 offscreen_target_color_texture_->Invalidate();
3804 if (offscreen_target_color_render_buffer_.get())
3805 offscreen_target_color_render_buffer_->Invalidate();
3806 if (offscreen_target_depth_render_buffer_.get())
3807 offscreen_target_depth_render_buffer_->Invalidate();
3808 if (offscreen_target_stencil_render_buffer_.get())
3809 offscreen_target_stencil_render_buffer_->Invalidate();
3810 if (offscreen_saved_frame_buffer_.get())
3811 offscreen_saved_frame_buffer_->Invalidate();
3812 if (offscreen_saved_color_texture_.get())
3813 offscreen_saved_color_texture_->Invalidate();
3814 if (offscreen_resolved_frame_buffer_.get())
3815 offscreen_resolved_frame_buffer_->Invalidate();
3816 if (offscreen_resolved_color_texture_.get())
3817 offscreen_resolved_color_texture_->Invalidate();
3820 // Current program must be cleared after calling ProgramManager::UnuseProgram.
3821 // Otherwise, we can leak objects. http://crbug.com/258772.
3822 // state_.current_program must be reset before group_ is reset because
3823 // the later deletes the ProgramManager object that referred by
3824 // state_.current_program object.
3825 state_.current_program = NULL;
3827 copy_texture_CHROMIUM_.reset();
3828 clear_framebuffer_blit_.reset();
3830 if (query_manager_.get()) {
3831 query_manager_->Destroy(have_context);
3832 query_manager_.reset();
3835 if (vertex_array_manager_ .get()) {
3836 vertex_array_manager_->Destroy(have_context);
3837 vertex_array_manager_.reset();
3840 if (image_manager_.get()) {
3841 image_manager_->Destroy(have_context);
3842 image_manager_.reset();
3845 offscreen_target_frame_buffer_.reset();
3846 offscreen_target_color_texture_.reset();
3847 offscreen_target_color_render_buffer_.reset();
3848 offscreen_target_depth_render_buffer_.reset();
3849 offscreen_target_stencil_render_buffer_.reset();
3850 offscreen_saved_frame_buffer_.reset();
3851 offscreen_saved_color_texture_.reset();
3852 offscreen_resolved_frame_buffer_.reset();
3853 offscreen_resolved_color_texture_.reset();
3855 // Need to release these before releasing |group_| which may own the
3856 // ShaderTranslatorCache.
3857 fragment_translator_ = NULL;
3858 vertex_translator_ = NULL;
3860 // Should destroy the transfer manager before the texture manager held
3861 // by the context group.
3862 async_pixel_transfer_manager_.reset();
3864 // Destroy the GPU Tracer which may own some in process GPU Timings.
3865 if (gpu_tracer_) {
3866 gpu_tracer_->Destroy(have_context);
3867 gpu_tracer_.reset();
3870 if (group_.get()) {
3871 framebuffer_manager()->RemoveObserver(this);
3872 group_->Destroy(this, have_context);
3873 group_ = NULL;
3876 if (context_.get()) {
3877 context_->ReleaseCurrent(NULL);
3878 context_ = NULL;
3881 #if defined(OS_MACOSX)
3882 for (TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.begin();
3883 it != texture_to_io_surface_map_.end(); ++it) {
3884 CFRelease(it->second);
3886 texture_to_io_surface_map_.clear();
3887 #endif
3890 void GLES2DecoderImpl::SetSurface(
3891 const scoped_refptr<gfx::GLSurface>& surface) {
3892 DCHECK(context_->IsCurrent(NULL));
3893 DCHECK(surface_.get());
3894 surface_ = surface;
3895 RestoreCurrentFramebufferBindings();
3898 void GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox& mailbox) {
3899 if (!offscreen_saved_color_texture_.get()) {
3900 LOG(ERROR) << "Called ProduceFrontBuffer on a non-offscreen context";
3901 return;
3903 if (!offscreen_saved_color_texture_info_.get()) {
3904 GLuint service_id = offscreen_saved_color_texture_->id();
3905 offscreen_saved_color_texture_info_ = TextureRef::Create(
3906 texture_manager(), 0, service_id);
3907 texture_manager()->SetTarget(offscreen_saved_color_texture_info_.get(),
3908 GL_TEXTURE_2D);
3909 UpdateParentTextureInfo();
3911 mailbox_manager()->ProduceTexture(
3912 mailbox, offscreen_saved_color_texture_info_->texture());
3915 bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
3916 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
3917 if (!is_offscreen) {
3918 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
3919 << " with an onscreen framebuffer.";
3920 return false;
3923 if (offscreen_size_ == size)
3924 return true;
3926 offscreen_size_ = size;
3927 int w = offscreen_size_.width();
3928 int h = offscreen_size_.height();
3929 if (w < 0 || h < 0 || h >= (INT_MAX / 4) / (w ? w : 1)) {
3930 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3931 << "to allocate storage due to excessive dimensions.";
3932 return false;
3935 // Reallocate the offscreen target buffers.
3936 DCHECK(offscreen_target_color_format_);
3937 if (IsOffscreenBufferMultisampled()) {
3938 if (!offscreen_target_color_render_buffer_->AllocateStorage(
3939 feature_info_.get(),
3940 offscreen_size_,
3941 offscreen_target_color_format_,
3942 offscreen_target_samples_)) {
3943 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3944 << "to allocate storage for offscreen target color buffer.";
3945 return false;
3947 } else {
3948 if (!offscreen_target_color_texture_->AllocateStorage(
3949 offscreen_size_, offscreen_target_color_format_, false)) {
3950 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3951 << "to allocate storage for offscreen target color texture.";
3952 return false;
3955 if (offscreen_target_depth_format_ &&
3956 !offscreen_target_depth_render_buffer_->AllocateStorage(
3957 feature_info_.get(),
3958 offscreen_size_,
3959 offscreen_target_depth_format_,
3960 offscreen_target_samples_)) {
3961 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3962 << "to allocate storage for offscreen target depth buffer.";
3963 return false;
3965 if (offscreen_target_stencil_format_ &&
3966 !offscreen_target_stencil_render_buffer_->AllocateStorage(
3967 feature_info_.get(),
3968 offscreen_size_,
3969 offscreen_target_stencil_format_,
3970 offscreen_target_samples_)) {
3971 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3972 << "to allocate storage for offscreen target stencil buffer.";
3973 return false;
3976 // Attach the offscreen target buffers to the target frame buffer.
3977 if (IsOffscreenBufferMultisampled()) {
3978 offscreen_target_frame_buffer_->AttachRenderBuffer(
3979 GL_COLOR_ATTACHMENT0,
3980 offscreen_target_color_render_buffer_.get());
3981 } else {
3982 offscreen_target_frame_buffer_->AttachRenderTexture(
3983 offscreen_target_color_texture_.get());
3985 if (offscreen_target_depth_format_) {
3986 offscreen_target_frame_buffer_->AttachRenderBuffer(
3987 GL_DEPTH_ATTACHMENT,
3988 offscreen_target_depth_render_buffer_.get());
3990 const bool packed_depth_stencil =
3991 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
3992 if (packed_depth_stencil) {
3993 offscreen_target_frame_buffer_->AttachRenderBuffer(
3994 GL_STENCIL_ATTACHMENT,
3995 offscreen_target_depth_render_buffer_.get());
3996 } else if (offscreen_target_stencil_format_) {
3997 offscreen_target_frame_buffer_->AttachRenderBuffer(
3998 GL_STENCIL_ATTACHMENT,
3999 offscreen_target_stencil_render_buffer_.get());
4002 if (offscreen_target_frame_buffer_->CheckStatus() !=
4003 GL_FRAMEBUFFER_COMPLETE) {
4004 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4005 << "because offscreen FBO was incomplete.";
4006 return false;
4009 // Clear the target frame buffer.
4011 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
4012 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
4013 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1.f);
4014 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4015 glClearStencil(0);
4016 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
4017 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
4018 glClearDepth(0);
4019 state_.SetDeviceDepthMask(GL_TRUE);
4020 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
4021 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
4022 RestoreClearState();
4025 // Destroy the offscreen resolved framebuffers.
4026 if (offscreen_resolved_frame_buffer_.get())
4027 offscreen_resolved_frame_buffer_->Destroy();
4028 if (offscreen_resolved_color_texture_.get())
4029 offscreen_resolved_color_texture_->Destroy();
4030 offscreen_resolved_color_texture_.reset();
4031 offscreen_resolved_frame_buffer_.reset();
4033 return true;
4036 error::Error GLES2DecoderImpl::HandleResizeCHROMIUM(uint32 immediate_data_size,
4037 const void* cmd_data) {
4038 const gles2::cmds::ResizeCHROMIUM& c =
4039 *static_cast<const gles2::cmds::ResizeCHROMIUM*>(cmd_data);
4040 if (!offscreen_target_frame_buffer_.get() && surface_->DeferDraws())
4041 return error::kDeferCommandUntilLater;
4043 GLuint width = static_cast<GLuint>(c.width);
4044 GLuint height = static_cast<GLuint>(c.height);
4045 GLfloat scale_factor = c.scale_factor;
4046 TRACE_EVENT2("gpu", "glResizeChromium", "width", width, "height", height);
4048 width = std::max(1U, width);
4049 height = std::max(1U, height);
4051 #if defined(OS_POSIX) && !defined(OS_MACOSX) && \
4052 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
4053 // Make sure that we are done drawing to the back buffer before resizing.
4054 glFinish();
4055 #endif
4056 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
4057 if (is_offscreen) {
4058 if (!ResizeOffscreenFrameBuffer(gfx::Size(width, height))) {
4059 LOG(ERROR) << "GLES2DecoderImpl: Context lost because "
4060 << "ResizeOffscreenFrameBuffer failed.";
4061 return error::kLostContext;
4065 if (!resize_callback_.is_null()) {
4066 resize_callback_.Run(gfx::Size(width, height), scale_factor);
4067 DCHECK(context_->IsCurrent(surface_.get()));
4068 if (!context_->IsCurrent(surface_.get())) {
4069 LOG(ERROR) << "GLES2DecoderImpl: Context lost because context no longer "
4070 << "current after resize callback.";
4071 return error::kLostContext;
4075 return error::kNoError;
4078 const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
4079 if (command_id > kStartPoint && command_id < kNumCommands) {
4080 return gles2::GetCommandName(static_cast<CommandId>(command_id));
4082 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
4085 // Decode a command, and call the corresponding GL functions.
4086 // NOTE: DoCommand() is slower than calling DoCommands() on larger batches
4087 // of commands at once, and is now only used for tests that need to track
4088 // individual commands.
4089 error::Error GLES2DecoderImpl::DoCommand(unsigned int command,
4090 unsigned int arg_count,
4091 const void* cmd_data) {
4092 return DoCommands(1, cmd_data, arg_count + 1, 0);
4095 // Decode multiple commands, and call the corresponding GL functions.
4096 // NOTE: 'buffer' is a pointer to the command buffer. As such, it could be
4097 // changed by a (malicious) client at any time, so if validation has to happen,
4098 // it should operate on a copy of them.
4099 // NOTE: This is duplicating code from AsyncAPIInterface::DoCommands() in the
4100 // interest of performance in this critical execution loop.
4101 template <bool DebugImpl>
4102 error::Error GLES2DecoderImpl::DoCommandsImpl(unsigned int num_commands,
4103 const void* buffer,
4104 int num_entries,
4105 int* entries_processed) {
4106 commands_to_process_ = num_commands;
4107 error::Error result = error::kNoError;
4108 const CommandBufferEntry* cmd_data =
4109 static_cast<const CommandBufferEntry*>(buffer);
4110 int process_pos = 0;
4111 unsigned int command = 0;
4113 while (process_pos < num_entries && result == error::kNoError &&
4114 commands_to_process_--) {
4115 const unsigned int size = cmd_data->value_header.size;
4116 command = cmd_data->value_header.command;
4118 if (size == 0) {
4119 result = error::kInvalidSize;
4120 break;
4123 if (static_cast<int>(size) + process_pos > num_entries) {
4124 result = error::kOutOfBounds;
4125 break;
4128 if (DebugImpl) {
4129 TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
4130 GetCommandName(command));
4132 if (log_commands()) {
4133 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "]"
4134 << "cmd: " << GetCommandName(command);
4138 const unsigned int arg_count = size - 1;
4139 unsigned int command_index = command - kStartPoint - 1;
4140 if (command_index < arraysize(command_info)) {
4141 const CommandInfo& info = command_info[command_index];
4142 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
4143 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
4144 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
4145 bool doing_gpu_trace = false;
4146 if (DebugImpl && gpu_trace_commands_) {
4147 if (CMD_FLAG_GET_TRACE_LEVEL(info.cmd_flags) <= gpu_trace_level_) {
4148 doing_gpu_trace = true;
4149 gpu_tracer_->Begin(TRACE_DISABLED_BY_DEFAULT("gpu_decoder"),
4150 GetCommandName(command),
4151 kTraceDecoder);
4155 uint32 immediate_data_size = (arg_count - info_arg_count) *
4156 sizeof(CommandBufferEntry); // NOLINT
4158 result = (this->*info.cmd_handler)(immediate_data_size, cmd_data);
4160 if (DebugImpl && doing_gpu_trace)
4161 gpu_tracer_->End(kTraceDecoder);
4163 if (DebugImpl && debug()) {
4164 GLenum error;
4165 while ((error = glGetError()) != GL_NO_ERROR) {
4166 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "] "
4167 << "GL ERROR: " << GLES2Util::GetStringEnum(error)
4168 << " : " << GetCommandName(command);
4169 LOCAL_SET_GL_ERROR(error, "DoCommand", "GL error from driver");
4172 } else {
4173 result = error::kInvalidArguments;
4175 } else {
4176 result = DoCommonCommand(command, arg_count, cmd_data);
4179 if (DebugImpl) {
4180 TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
4181 GetCommandName(command));
4184 if (result == error::kNoError &&
4185 current_decoder_error_ != error::kNoError) {
4186 result = current_decoder_error_;
4187 current_decoder_error_ = error::kNoError;
4190 if (result != error::kDeferCommandUntilLater) {
4191 process_pos += size;
4192 cmd_data += size;
4196 if (entries_processed)
4197 *entries_processed = process_pos;
4199 if (error::IsError(result)) {
4200 LOG(ERROR) << "Error: " << result << " for Command "
4201 << GetCommandName(command);
4204 return result;
4207 error::Error GLES2DecoderImpl::DoCommands(unsigned int num_commands,
4208 const void* buffer,
4209 int num_entries,
4210 int* entries_processed) {
4211 if (gpu_debug_commands_) {
4212 return DoCommandsImpl<true>(
4213 num_commands, buffer, num_entries, entries_processed);
4214 } else {
4215 return DoCommandsImpl<false>(
4216 num_commands, buffer, num_entries, entries_processed);
4220 void GLES2DecoderImpl::RemoveBuffer(GLuint client_id) {
4221 buffer_manager()->RemoveBuffer(client_id);
4224 void GLES2DecoderImpl::DoFinish() {
4225 glFinish();
4226 ProcessPendingReadPixels();
4227 ProcessPendingQueries(true);
4230 void GLES2DecoderImpl::DoFlush() {
4231 glFlush();
4232 ProcessPendingQueries(false);
4235 void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
4236 GLuint texture_index = texture_unit - GL_TEXTURE0;
4237 if (texture_index >= state_.texture_units.size()) {
4238 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4239 "glActiveTexture", texture_unit, "texture_unit");
4240 return;
4242 state_.active_texture_unit = texture_index;
4243 glActiveTexture(texture_unit);
4246 void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
4247 Buffer* buffer = NULL;
4248 GLuint service_id = 0;
4249 if (client_id != 0) {
4250 buffer = GetBuffer(client_id);
4251 if (!buffer) {
4252 if (!group_->bind_generates_resource()) {
4253 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4254 "glBindBuffer",
4255 "id not generated by glGenBuffers");
4256 return;
4259 // It's a new id so make a buffer buffer for it.
4260 glGenBuffersARB(1, &service_id);
4261 CreateBuffer(client_id, service_id);
4262 buffer = GetBuffer(client_id);
4265 LogClientServiceForInfo(buffer, client_id, "glBindBuffer");
4266 if (buffer) {
4267 if (!buffer_manager()->SetTarget(buffer, target)) {
4268 LOCAL_SET_GL_ERROR(
4269 GL_INVALID_OPERATION,
4270 "glBindBuffer", "buffer bound to more than 1 target");
4271 return;
4273 service_id = buffer->service_id();
4275 switch (target) {
4276 case GL_ARRAY_BUFFER:
4277 state_.bound_array_buffer = buffer;
4278 break;
4279 case GL_ELEMENT_ARRAY_BUFFER:
4280 state_.vertex_attrib_manager->SetElementArrayBuffer(buffer);
4281 break;
4282 default:
4283 NOTREACHED(); // Validation should prevent us getting here.
4284 break;
4286 glBindBuffer(target, service_id);
4289 bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha(
4290 bool all_draw_buffers) {
4291 Framebuffer* framebuffer =
4292 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4293 if (!all_draw_buffers || !framebuffer) {
4294 return (GLES2Util::GetChannelsForFormat(
4295 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
4297 return framebuffer->HasAlphaMRT();
4300 bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
4301 Framebuffer* framebuffer =
4302 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4303 if (framebuffer) {
4304 return framebuffer->HasDepthAttachment();
4306 if (offscreen_target_frame_buffer_.get()) {
4307 return offscreen_target_depth_format_ != 0;
4309 return back_buffer_has_depth_;
4312 bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
4313 Framebuffer* framebuffer =
4314 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4315 if (framebuffer) {
4316 return framebuffer->HasStencilAttachment();
4318 if (offscreen_target_frame_buffer_.get()) {
4319 return offscreen_target_stencil_format_ != 0 ||
4320 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
4322 return back_buffer_has_stencil_;
4325 void GLES2DecoderImpl::ApplyDirtyState() {
4326 if (framebuffer_state_.clear_state_dirty) {
4327 bool have_alpha = BoundFramebufferHasColorAttachmentWithAlpha(true);
4328 state_.SetDeviceColorMask(state_.color_mask_red,
4329 state_.color_mask_green,
4330 state_.color_mask_blue,
4331 state_.color_mask_alpha && have_alpha);
4333 bool have_depth = BoundFramebufferHasDepthAttachment();
4334 state_.SetDeviceDepthMask(state_.depth_mask && have_depth);
4336 bool have_stencil = BoundFramebufferHasStencilAttachment();
4337 state_.SetDeviceStencilMaskSeparate(
4338 GL_FRONT, have_stencil ? state_.stencil_front_writemask : 0);
4339 state_.SetDeviceStencilMaskSeparate(
4340 GL_BACK, have_stencil ? state_.stencil_back_writemask : 0);
4342 state_.SetDeviceCapabilityState(
4343 GL_DEPTH_TEST, state_.enable_flags.depth_test && have_depth);
4344 state_.SetDeviceCapabilityState(
4345 GL_STENCIL_TEST, state_.enable_flags.stencil_test && have_stencil);
4346 framebuffer_state_.clear_state_dirty = false;
4350 GLuint GLES2DecoderImpl::GetBackbufferServiceId() const {
4351 return (offscreen_target_frame_buffer_.get())
4352 ? offscreen_target_frame_buffer_->id()
4353 : (surface_.get() ? surface_->GetBackingFrameBufferObject() : 0);
4356 void GLES2DecoderImpl::RestoreState(const ContextState* prev_state) {
4357 TRACE_EVENT1("gpu", "GLES2DecoderImpl::RestoreState",
4358 "context", logger_.GetLogPrefix());
4359 // Restore the Framebuffer first because of bugs in Intel drivers.
4360 // Intel drivers incorrectly clip the viewport settings to
4361 // the size of the current framebuffer object.
4362 RestoreFramebufferBindings();
4363 state_.RestoreState(prev_state);
4366 void GLES2DecoderImpl::RestoreFramebufferBindings() const {
4367 GLuint service_id =
4368 framebuffer_state_.bound_draw_framebuffer.get()
4369 ? framebuffer_state_.bound_draw_framebuffer->service_id()
4370 : GetBackbufferServiceId();
4371 if (!features().chromium_framebuffer_multisample) {
4372 glBindFramebufferEXT(GL_FRAMEBUFFER, service_id);
4373 } else {
4374 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, service_id);
4375 service_id = framebuffer_state_.bound_read_framebuffer.get()
4376 ? framebuffer_state_.bound_read_framebuffer->service_id()
4377 : GetBackbufferServiceId();
4378 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, service_id);
4380 OnFboChanged();
4383 void GLES2DecoderImpl::RestoreRenderbufferBindings() {
4384 state_.RestoreRenderbufferBindings();
4387 void GLES2DecoderImpl::RestoreTextureState(unsigned service_id) const {
4388 Texture* texture = texture_manager()->GetTextureForServiceId(service_id);
4389 if (texture) {
4390 GLenum target = texture->target();
4391 glBindTexture(target, service_id);
4392 glTexParameteri(
4393 target, GL_TEXTURE_WRAP_S, texture->wrap_s());
4394 glTexParameteri(
4395 target, GL_TEXTURE_WRAP_T, texture->wrap_t());
4396 glTexParameteri(
4397 target, GL_TEXTURE_MIN_FILTER, texture->min_filter());
4398 glTexParameteri(
4399 target, GL_TEXTURE_MAG_FILTER, texture->mag_filter());
4400 RestoreTextureUnitBindings(state_.active_texture_unit);
4404 void GLES2DecoderImpl::ClearAllAttributes() const {
4405 // Must use native VAO 0, as RestoreAllAttributes can't fully restore
4406 // other VAOs.
4407 if (feature_info_->feature_flags().native_vertex_array_object)
4408 glBindVertexArrayOES(0);
4410 for (uint32 i = 0; i < group_->max_vertex_attribs(); ++i) {
4411 if (i != 0) // Never disable attribute 0
4412 glDisableVertexAttribArray(i);
4413 if (features().angle_instanced_arrays)
4414 glVertexAttribDivisorANGLE(i, 0);
4418 void GLES2DecoderImpl::RestoreAllAttributes() const {
4419 state_.RestoreVertexAttribs();
4422 void GLES2DecoderImpl::SetIgnoreCachedStateForTest(bool ignore) {
4423 state_.SetIgnoreCachedStateForTest(ignore);
4426 void GLES2DecoderImpl::OnFboChanged() const {
4427 if (workarounds().restore_scissor_on_fbo_change)
4428 state_.fbo_binding_for_scissor_workaround_dirty = true;
4430 if (workarounds().gl_begin_gl_end_on_fbo_change_to_backbuffer) {
4431 GLint bound_fbo_unsigned = -1;
4432 glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &bound_fbo_unsigned);
4433 GLuint bound_fbo = static_cast<GLuint>(bound_fbo_unsigned);
4434 if (surface_ && surface_->GetBackingFrameBufferObject() == bound_fbo)
4435 surface_->NotifyWasBound();
4439 // Called after the FBO is checked for completeness.
4440 void GLES2DecoderImpl::OnUseFramebuffer() const {
4441 if (state_.fbo_binding_for_scissor_workaround_dirty) {
4442 state_.fbo_binding_for_scissor_workaround_dirty = false;
4443 // The driver forgets the correct scissor when modifying the FBO binding.
4444 glScissor(state_.scissor_x,
4445 state_.scissor_y,
4446 state_.scissor_width,
4447 state_.scissor_height);
4449 // crbug.com/222018 - Also on QualComm, the flush here avoids flicker,
4450 // it's unclear how this bug works.
4451 glFlush();
4455 void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
4456 Framebuffer* framebuffer = NULL;
4457 GLuint service_id = 0;
4458 if (client_id != 0) {
4459 framebuffer = GetFramebuffer(client_id);
4460 if (!framebuffer) {
4461 if (!group_->bind_generates_resource()) {
4462 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4463 "glBindFramebuffer",
4464 "id not generated by glGenFramebuffers");
4465 return;
4468 // It's a new id so make a framebuffer framebuffer for it.
4469 glGenFramebuffersEXT(1, &service_id);
4470 CreateFramebuffer(client_id, service_id);
4471 framebuffer = GetFramebuffer(client_id);
4472 } else {
4473 service_id = framebuffer->service_id();
4475 framebuffer->MarkAsValid();
4477 LogClientServiceForInfo(framebuffer, client_id, "glBindFramebuffer");
4479 if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) {
4480 framebuffer_state_.bound_draw_framebuffer = framebuffer;
4483 // vmiura: This looks like dup code
4484 if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) {
4485 framebuffer_state_.bound_read_framebuffer = framebuffer;
4488 framebuffer_state_.clear_state_dirty = true;
4490 // If we are rendering to the backbuffer get the FBO id for any simulated
4491 // backbuffer.
4492 if (framebuffer == NULL) {
4493 service_id = GetBackbufferServiceId();
4496 glBindFramebufferEXT(target, service_id);
4497 OnFboChanged();
4500 void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
4501 Renderbuffer* renderbuffer = NULL;
4502 GLuint service_id = 0;
4503 if (client_id != 0) {
4504 renderbuffer = GetRenderbuffer(client_id);
4505 if (!renderbuffer) {
4506 if (!group_->bind_generates_resource()) {
4507 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4508 "glBindRenderbuffer",
4509 "id not generated by glGenRenderbuffers");
4510 return;
4513 // It's a new id so make a renderbuffer for it.
4514 glGenRenderbuffersEXT(1, &service_id);
4515 CreateRenderbuffer(client_id, service_id);
4516 renderbuffer = GetRenderbuffer(client_id);
4517 } else {
4518 service_id = renderbuffer->service_id();
4520 renderbuffer->MarkAsValid();
4522 LogClientServiceForInfo(renderbuffer, client_id, "glBindRenderbuffer");
4523 state_.bound_renderbuffer = renderbuffer;
4524 state_.bound_renderbuffer_valid = true;
4525 glBindRenderbufferEXT(GL_RENDERBUFFER, service_id);
4528 void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
4529 TextureRef* texture_ref = NULL;
4530 GLuint service_id = 0;
4531 if (client_id != 0) {
4532 texture_ref = GetTexture(client_id);
4533 if (!texture_ref) {
4534 if (!group_->bind_generates_resource()) {
4535 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4536 "glBindTexture",
4537 "id not generated by glGenTextures");
4538 return;
4541 // It's a new id so make a texture texture for it.
4542 glGenTextures(1, &service_id);
4543 DCHECK_NE(0u, service_id);
4544 CreateTexture(client_id, service_id);
4545 texture_ref = GetTexture(client_id);
4547 } else {
4548 texture_ref = texture_manager()->GetDefaultTextureInfo(target);
4551 // Check the texture exists
4552 if (texture_ref) {
4553 Texture* texture = texture_ref->texture();
4554 // Check that we are not trying to bind it to a different target.
4555 if (texture->target() != 0 && texture->target() != target) {
4556 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4557 "glBindTexture",
4558 "texture bound to more than 1 target.");
4559 return;
4561 LogClientServiceForInfo(texture, client_id, "glBindTexture");
4562 if (texture->target() == 0) {
4563 texture_manager()->SetTarget(texture_ref, target);
4565 glBindTexture(target, texture->service_id());
4566 } else {
4567 glBindTexture(target, 0);
4570 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4571 unit.bind_target = target;
4572 switch (target) {
4573 case GL_TEXTURE_2D:
4574 unit.bound_texture_2d = texture_ref;
4575 break;
4576 case GL_TEXTURE_CUBE_MAP:
4577 unit.bound_texture_cube_map = texture_ref;
4578 break;
4579 case GL_TEXTURE_EXTERNAL_OES:
4580 unit.bound_texture_external_oes = texture_ref;
4581 break;
4582 case GL_TEXTURE_RECTANGLE_ARB:
4583 unit.bound_texture_rectangle_arb = texture_ref;
4584 break;
4585 case GL_TEXTURE_3D:
4586 unit.bound_texture_3d = texture_ref;
4587 break;
4588 case GL_TEXTURE_2D_ARRAY:
4589 unit.bound_texture_2d_array = texture_ref;
4590 break;
4591 default:
4592 NOTREACHED(); // Validation should prevent us getting here.
4593 break;
4597 void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
4598 if (state_.vertex_attrib_manager->Enable(index, false)) {
4599 if (index != 0 ||
4600 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
4601 glDisableVertexAttribArray(index);
4603 } else {
4604 LOCAL_SET_GL_ERROR(
4605 GL_INVALID_VALUE,
4606 "glDisableVertexAttribArray", "index out of range");
4610 void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target,
4611 GLsizei numAttachments,
4612 const GLenum* attachments) {
4613 if (workarounds().disable_discard_framebuffer)
4614 return;
4616 Framebuffer* framebuffer =
4617 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4619 // Validates the attachments. If one of them fails
4620 // the whole command fails.
4621 for (GLsizei i = 0; i < numAttachments; ++i) {
4622 if ((framebuffer &&
4623 !validators_->attachment.IsValid(attachments[i])) ||
4624 (!framebuffer &&
4625 !validators_->backbuffer_attachment.IsValid(attachments[i]))) {
4626 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4627 "glDiscardFramebufferEXT", attachments[i], "attachments");
4628 return;
4632 // Marks each one of them as not cleared
4633 for (GLsizei i = 0; i < numAttachments; ++i) {
4634 if (framebuffer) {
4635 framebuffer->MarkAttachmentAsCleared(renderbuffer_manager(),
4636 texture_manager(),
4637 attachments[i],
4638 false);
4639 } else {
4640 switch (attachments[i]) {
4641 case GL_COLOR_EXT:
4642 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
4643 break;
4644 case GL_DEPTH_EXT:
4645 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
4646 case GL_STENCIL_EXT:
4647 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
4648 break;
4649 default:
4650 NOTREACHED();
4651 break;
4656 // If the default framebuffer is bound but we are still rendering to an
4657 // FBO, translate attachment names that refer to default framebuffer
4658 // channels to corresponding framebuffer attachments.
4659 scoped_ptr<GLenum[]> translated_attachments(new GLenum[numAttachments]);
4660 for (GLsizei i = 0; i < numAttachments; ++i) {
4661 GLenum attachment = attachments[i];
4662 if (!framebuffer && GetBackbufferServiceId()) {
4663 switch (attachment) {
4664 case GL_COLOR_EXT:
4665 attachment = GL_COLOR_ATTACHMENT0;
4666 break;
4667 case GL_DEPTH_EXT:
4668 attachment = GL_DEPTH_ATTACHMENT;
4669 break;
4670 case GL_STENCIL_EXT:
4671 attachment = GL_STENCIL_ATTACHMENT;
4672 break;
4673 default:
4674 NOTREACHED();
4675 return;
4678 translated_attachments[i] = attachment;
4681 ScopedRenderTo do_render(framebuffer);
4682 if (feature_info_->gl_version_info().is_es3) {
4683 glInvalidateFramebuffer(
4684 target, numAttachments, translated_attachments.get());
4685 } else {
4686 glDiscardFramebufferEXT(
4687 target, numAttachments, translated_attachments.get());
4691 void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
4692 if (state_.vertex_attrib_manager->Enable(index, true)) {
4693 glEnableVertexAttribArray(index);
4694 } else {
4695 LOCAL_SET_GL_ERROR(
4696 GL_INVALID_VALUE, "glEnableVertexAttribArray", "index out of range");
4700 void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
4701 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
4702 &state_, target);
4703 if (!texture_ref ||
4704 !texture_manager()->CanGenerateMipmaps(texture_ref)) {
4705 LOCAL_SET_GL_ERROR(
4706 GL_INVALID_OPERATION, "glGenerateMipmap", "Can not generate mips");
4707 return;
4710 if (target == GL_TEXTURE_CUBE_MAP) {
4711 for (int i = 0; i < 6; ++i) {
4712 GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;
4713 if (!texture_manager()->ClearTextureLevel(this, texture_ref, face, 0)) {
4714 LOCAL_SET_GL_ERROR(
4715 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
4716 return;
4719 } else {
4720 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, 0)) {
4721 LOCAL_SET_GL_ERROR(
4722 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
4723 return;
4727 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glGenerateMipmap");
4728 // Workaround for Mac driver bug. In the large scheme of things setting
4729 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
4730 // hit so there's probably no need to make this conditional. The bug appears
4731 // to be that if the filtering mode is set to something that doesn't require
4732 // mipmaps for rendering, or is never set to something other than the default,
4733 // then glGenerateMipmap misbehaves.
4734 if (workarounds().set_texture_filter_before_generating_mipmap) {
4735 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
4737 glGenerateMipmapEXT(target);
4738 if (workarounds().set_texture_filter_before_generating_mipmap) {
4739 glTexParameteri(target, GL_TEXTURE_MIN_FILTER,
4740 texture_ref->texture()->min_filter());
4742 GLenum error = LOCAL_PEEK_GL_ERROR("glGenerateMipmap");
4743 if (error == GL_NO_ERROR) {
4744 texture_manager()->MarkMipmapsGenerated(texture_ref);
4748 bool GLES2DecoderImpl::GetHelper(
4749 GLenum pname, GLint* params, GLsizei* num_written) {
4750 DCHECK(num_written);
4751 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
4752 switch (pname) {
4753 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
4754 *num_written = 1;
4755 // Return the GL implementation's preferred format and (see below type)
4756 // if we have the GL extension that exposes this. This allows the GPU
4757 // client to use the implementation's preferred format for glReadPixels
4758 // for optimisation.
4760 // A conflicting extension (GL_ARB_ES2_compatibility) specifies an error
4761 // case when requested on integer/floating point buffers but which is
4762 // acceptable on GLES2 and with the GL_OES_read_format extension.
4764 // Therefore if an error occurs we swallow the error and use the
4765 // internal implementation.
4766 if (params) {
4767 if (context_->HasExtension("GL_OES_read_format")) {
4768 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper",
4769 GetErrorState());
4770 glGetIntegerv(pname, params);
4771 if (glGetError() == GL_NO_ERROR)
4772 return true;
4774 *params = GLES2Util::GetPreferredGLReadPixelsFormat(
4775 GetBoundReadFrameBufferInternalFormat());
4777 return true;
4778 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
4779 *num_written = 1;
4780 if (params) {
4781 if (context_->HasExtension("GL_OES_read_format")) {
4782 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper",
4783 GetErrorState());
4784 glGetIntegerv(pname, params);
4785 if (glGetError() == GL_NO_ERROR)
4786 return true;
4788 *params = GLES2Util::GetPreferredGLReadPixelsType(
4789 GetBoundReadFrameBufferInternalFormat(),
4790 GetBoundReadFrameBufferTextureType());
4792 return true;
4793 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
4794 *num_written = 1;
4795 if (params) {
4796 *params = group_->max_fragment_uniform_vectors();
4798 return true;
4799 case GL_MAX_VARYING_VECTORS:
4800 *num_written = 1;
4801 if (params) {
4802 *params = group_->max_varying_vectors();
4804 return true;
4805 case GL_MAX_VERTEX_UNIFORM_VECTORS:
4806 *num_written = 1;
4807 if (params) {
4808 *params = group_->max_vertex_uniform_vectors();
4810 return true;
4813 switch (pname) {
4814 case GL_MAX_VIEWPORT_DIMS:
4815 if (offscreen_target_frame_buffer_.get()) {
4816 *num_written = 2;
4817 if (params) {
4818 params[0] = renderbuffer_manager()->max_renderbuffer_size();
4819 params[1] = renderbuffer_manager()->max_renderbuffer_size();
4821 return true;
4823 return false;
4824 case GL_MAX_SAMPLES:
4825 *num_written = 1;
4826 if (params) {
4827 params[0] = renderbuffer_manager()->max_samples();
4829 return true;
4830 case GL_MAX_RENDERBUFFER_SIZE:
4831 *num_written = 1;
4832 if (params) {
4833 params[0] = renderbuffer_manager()->max_renderbuffer_size();
4835 return true;
4836 case GL_MAX_TEXTURE_SIZE:
4837 *num_written = 1;
4838 if (params) {
4839 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D);
4841 return true;
4842 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
4843 *num_written = 1;
4844 if (params) {
4845 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP);
4847 return true;
4848 case GL_MAX_COLOR_ATTACHMENTS_EXT:
4849 *num_written = 1;
4850 if (params) {
4851 params[0] = group_->max_color_attachments();
4853 return true;
4854 case GL_MAX_DRAW_BUFFERS_ARB:
4855 *num_written = 1;
4856 if (params) {
4857 params[0] = group_->max_draw_buffers();
4859 return true;
4860 case GL_ALPHA_BITS:
4861 *num_written = 1;
4862 if (params) {
4863 GLint v = 0;
4864 if (feature_info_->gl_version_info().is_desktop_core_profile) {
4865 Framebuffer* framebuffer =
4866 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4867 if (framebuffer) {
4868 glGetFramebufferAttachmentParameterivEXT(
4869 GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
4870 GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE, &v);
4871 } else {
4872 v = (back_buffer_color_format_ == GL_RGBA ? 8 : 0);
4874 } else {
4875 glGetIntegerv(GL_ALPHA_BITS, &v);
4877 params[0] =
4878 BoundFramebufferHasColorAttachmentWithAlpha(false) ? v : 0;
4880 return true;
4881 case GL_DEPTH_BITS:
4882 *num_written = 1;
4883 if (params) {
4884 GLint v = 0;
4885 if (feature_info_->gl_version_info().is_desktop_core_profile) {
4886 Framebuffer* framebuffer =
4887 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4888 if (framebuffer) {
4889 glGetFramebufferAttachmentParameterivEXT(
4890 GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
4891 GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE, &v);
4892 } else {
4893 v = (back_buffer_has_depth_ ? 24 : 0);
4895 } else {
4896 glGetIntegerv(GL_DEPTH_BITS, &v);
4898 params[0] = BoundFramebufferHasDepthAttachment() ? v : 0;
4900 return true;
4901 case GL_RED_BITS:
4902 case GL_GREEN_BITS:
4903 case GL_BLUE_BITS:
4904 *num_written = 1;
4905 if (params) {
4906 GLint v = 0;
4907 if (feature_info_->gl_version_info().is_desktop_core_profile) {
4908 Framebuffer* framebuffer =
4909 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4910 if (framebuffer) {
4911 GLenum framebuffer_enum = 0;
4912 switch (pname) {
4913 case GL_RED_BITS:
4914 framebuffer_enum = GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE;
4915 break;
4916 case GL_GREEN_BITS:
4917 framebuffer_enum = GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE;
4918 break;
4919 case GL_BLUE_BITS:
4920 framebuffer_enum = GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE;
4921 break;
4923 glGetFramebufferAttachmentParameterivEXT(
4924 GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, framebuffer_enum, &v);
4925 } else {
4926 v = 8;
4928 } else {
4929 glGetIntegerv(pname, &v);
4931 params[0] = v;
4933 return true;
4934 case GL_STENCIL_BITS:
4935 *num_written = 1;
4936 if (params) {
4937 GLint v = 0;
4938 if (feature_info_->gl_version_info().is_desktop_core_profile) {
4939 Framebuffer* framebuffer =
4940 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4941 if (framebuffer) {
4942 glGetFramebufferAttachmentParameterivEXT(
4943 GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
4944 GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE, &v);
4945 } else {
4946 v = (back_buffer_has_stencil_ ? 8 : 0);
4948 } else {
4949 glGetIntegerv(GL_STENCIL_BITS, &v);
4951 params[0] = BoundFramebufferHasStencilAttachment() ? v : 0;
4953 return true;
4954 case GL_COMPRESSED_TEXTURE_FORMATS:
4955 *num_written = validators_->compressed_texture_format.GetValues().size();
4956 if (params) {
4957 for (GLint ii = 0; ii < *num_written; ++ii) {
4958 params[ii] = validators_->compressed_texture_format.GetValues()[ii];
4961 return true;
4962 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
4963 *num_written = 1;
4964 if (params) {
4965 *params = validators_->compressed_texture_format.GetValues().size();
4967 return true;
4968 case GL_NUM_SHADER_BINARY_FORMATS:
4969 *num_written = 1;
4970 if (params) {
4971 *params = validators_->shader_binary_format.GetValues().size();
4973 return true;
4974 case GL_SHADER_BINARY_FORMATS:
4975 *num_written = validators_->shader_binary_format.GetValues().size();
4976 if (params) {
4977 for (GLint ii = 0; ii < *num_written; ++ii) {
4978 params[ii] = validators_->shader_binary_format.GetValues()[ii];
4981 return true;
4982 case GL_SHADER_COMPILER:
4983 *num_written = 1;
4984 if (params) {
4985 *params = GL_TRUE;
4987 return true;
4988 case GL_ARRAY_BUFFER_BINDING:
4989 *num_written = 1;
4990 if (params) {
4991 if (state_.bound_array_buffer.get()) {
4992 GLuint client_id = 0;
4993 buffer_manager()->GetClientId(state_.bound_array_buffer->service_id(),
4994 &client_id);
4995 *params = client_id;
4996 } else {
4997 *params = 0;
5000 return true;
5001 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
5002 *num_written = 1;
5003 if (params) {
5004 if (state_.vertex_attrib_manager->element_array_buffer()) {
5005 GLuint client_id = 0;
5006 buffer_manager()->GetClientId(
5007 state_.vertex_attrib_manager->element_array_buffer()->
5008 service_id(), &client_id);
5009 *params = client_id;
5010 } else {
5011 *params = 0;
5014 return true;
5015 case GL_FRAMEBUFFER_BINDING:
5016 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
5017 *num_written = 1;
5018 if (params) {
5019 Framebuffer* framebuffer =
5020 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
5021 if (framebuffer) {
5022 GLuint client_id = 0;
5023 framebuffer_manager()->GetClientId(
5024 framebuffer->service_id(), &client_id);
5025 *params = client_id;
5026 } else {
5027 *params = 0;
5030 return true;
5031 case GL_READ_FRAMEBUFFER_BINDING_EXT:
5032 *num_written = 1;
5033 if (params) {
5034 Framebuffer* framebuffer =
5035 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
5036 if (framebuffer) {
5037 GLuint client_id = 0;
5038 framebuffer_manager()->GetClientId(
5039 framebuffer->service_id(), &client_id);
5040 *params = client_id;
5041 } else {
5042 *params = 0;
5045 return true;
5046 case GL_RENDERBUFFER_BINDING:
5047 *num_written = 1;
5048 if (params) {
5049 Renderbuffer* renderbuffer =
5050 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5051 if (renderbuffer) {
5052 *params = renderbuffer->client_id();
5053 } else {
5054 *params = 0;
5057 return true;
5058 case GL_CURRENT_PROGRAM:
5059 *num_written = 1;
5060 if (params) {
5061 if (state_.current_program.get()) {
5062 GLuint client_id = 0;
5063 program_manager()->GetClientId(
5064 state_.current_program->service_id(), &client_id);
5065 *params = client_id;
5066 } else {
5067 *params = 0;
5070 return true;
5071 case GL_VERTEX_ARRAY_BINDING_OES:
5072 *num_written = 1;
5073 if (params) {
5074 if (state_.vertex_attrib_manager.get() !=
5075 state_.default_vertex_attrib_manager.get()) {
5076 GLuint client_id = 0;
5077 vertex_array_manager_->GetClientId(
5078 state_.vertex_attrib_manager->service_id(), &client_id);
5079 *params = client_id;
5080 } else {
5081 *params = 0;
5084 return true;
5085 case GL_TEXTURE_BINDING_2D:
5086 *num_written = 1;
5087 if (params) {
5088 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
5089 if (unit.bound_texture_2d.get()) {
5090 *params = unit.bound_texture_2d->client_id();
5091 } else {
5092 *params = 0;
5095 return true;
5096 case GL_TEXTURE_BINDING_CUBE_MAP:
5097 *num_written = 1;
5098 if (params) {
5099 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
5100 if (unit.bound_texture_cube_map.get()) {
5101 *params = unit.bound_texture_cube_map->client_id();
5102 } else {
5103 *params = 0;
5106 return true;
5107 case GL_TEXTURE_BINDING_EXTERNAL_OES:
5108 *num_written = 1;
5109 if (params) {
5110 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
5111 if (unit.bound_texture_external_oes.get()) {
5112 *params = unit.bound_texture_external_oes->client_id();
5113 } else {
5114 *params = 0;
5117 return true;
5118 case GL_TEXTURE_BINDING_RECTANGLE_ARB:
5119 *num_written = 1;
5120 if (params) {
5121 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
5122 if (unit.bound_texture_rectangle_arb.get()) {
5123 *params = unit.bound_texture_rectangle_arb->client_id();
5124 } else {
5125 *params = 0;
5128 return true;
5129 case GL_UNPACK_FLIP_Y_CHROMIUM:
5130 *num_written = 1;
5131 if (params) {
5132 params[0] = unpack_flip_y_;
5134 return true;
5135 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
5136 *num_written = 1;
5137 if (params) {
5138 params[0] = unpack_premultiply_alpha_;
5140 return true;
5141 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM:
5142 *num_written = 1;
5143 if (params) {
5144 params[0] = unpack_unpremultiply_alpha_;
5146 return true;
5147 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
5148 *num_written = 1;
5149 if (params) {
5150 params[0] = group_->bind_generates_resource() ? 1 : 0;
5152 return true;
5153 default:
5154 if (pname >= GL_DRAW_BUFFER0_ARB &&
5155 pname < GL_DRAW_BUFFER0_ARB + group_->max_draw_buffers()) {
5156 *num_written = 1;
5157 if (params) {
5158 Framebuffer* framebuffer =
5159 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
5160 if (framebuffer) {
5161 params[0] = framebuffer->GetDrawBuffer(pname);
5162 } else { // backbuffer
5163 if (pname == GL_DRAW_BUFFER0_ARB)
5164 params[0] = group_->draw_buffer();
5165 else
5166 params[0] = GL_NONE;
5169 return true;
5171 *num_written = util_.GLGetNumValuesReturned(pname);
5172 return false;
5176 bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
5177 GLenum pname, GLsizei* num_values) {
5178 if (state_.GetStateAsGLint(pname, NULL, num_values)) {
5179 return true;
5181 return GetHelper(pname, NULL, num_values);
5184 GLenum GLES2DecoderImpl::AdjustGetPname(GLenum pname) {
5185 if (GL_MAX_SAMPLES == pname &&
5186 features().use_img_for_multisampled_render_to_texture) {
5187 return GL_MAX_SAMPLES_IMG;
5189 return pname;
5192 void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
5193 DCHECK(params);
5194 GLsizei num_written = 0;
5195 if (GetNumValuesReturnedForGLGet(pname, &num_written)) {
5196 scoped_ptr<GLint[]> values(new GLint[num_written]);
5197 if (!state_.GetStateAsGLint(pname, values.get(), &num_written)) {
5198 GetHelper(pname, values.get(), &num_written);
5200 for (GLsizei ii = 0; ii < num_written; ++ii) {
5201 params[ii] = static_cast<GLboolean>(values[ii]);
5203 } else {
5204 pname = AdjustGetPname(pname);
5205 glGetBooleanv(pname, params);
5209 void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
5210 DCHECK(params);
5211 GLsizei num_written = 0;
5212 if (!state_.GetStateAsGLfloat(pname, params, &num_written)) {
5213 if (GetHelper(pname, NULL, &num_written)) {
5214 scoped_ptr<GLint[]> values(new GLint[num_written]);
5215 GetHelper(pname, values.get(), &num_written);
5216 for (GLsizei ii = 0; ii < num_written; ++ii) {
5217 params[ii] = static_cast<GLfloat>(values[ii]);
5219 } else {
5220 pname = AdjustGetPname(pname);
5221 glGetFloatv(pname, params);
5226 void GLES2DecoderImpl::DoGetInteger64v(GLenum pname, GLint64* params) {
5227 DCHECK(params);
5228 pname = AdjustGetPname(pname);
5229 glGetInteger64v(pname, params);
5232 void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
5233 DCHECK(params);
5234 GLsizei num_written;
5235 if (!state_.GetStateAsGLint(pname, params, &num_written) &&
5236 !GetHelper(pname, params, &num_written)) {
5237 pname = AdjustGetPname(pname);
5238 glGetIntegerv(pname, params);
5242 void GLES2DecoderImpl::DoGetProgramiv(
5243 GLuint program_id, GLenum pname, GLint* params) {
5244 Program* program = GetProgramInfoNotShader(program_id, "glGetProgramiv");
5245 if (!program) {
5246 return;
5248 program->GetProgramiv(pname, params);
5251 void GLES2DecoderImpl::DoGetBufferParameteriv(
5252 GLenum target, GLenum pname, GLint* params) {
5253 // Just delegate it. Some validation is actually done before this.
5254 buffer_manager()->ValidateAndDoGetBufferParameteriv(
5255 &state_, target, pname, params);
5258 void GLES2DecoderImpl::DoBindAttribLocation(
5259 GLuint program_id, GLuint index, const char* name) {
5260 if (!StringIsValidForGLES(name)) {
5261 LOCAL_SET_GL_ERROR(
5262 GL_INVALID_VALUE, "glBindAttribLocation", "Invalid character");
5263 return;
5265 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
5266 LOCAL_SET_GL_ERROR(
5267 GL_INVALID_OPERATION, "glBindAttribLocation", "reserved prefix");
5268 return;
5270 if (index >= group_->max_vertex_attribs()) {
5271 LOCAL_SET_GL_ERROR(
5272 GL_INVALID_VALUE, "glBindAttribLocation", "index out of range");
5273 return;
5275 Program* program = GetProgramInfoNotShader(
5276 program_id, "glBindAttribLocation");
5277 if (!program) {
5278 return;
5280 // At this point, the program's shaders may not be translated yet,
5281 // therefore, we may not find the hashed attribute name.
5282 // glBindAttribLocation call with original name is useless.
5283 // So instead, we should simply cache the binding, and then call
5284 // Program::ExecuteBindAttribLocationCalls() right before link.
5285 program->SetAttribLocationBinding(name, static_cast<GLint>(index));
5286 // TODO(zmo): Get rid of the following glBindAttribLocation call.
5287 glBindAttribLocation(program->service_id(), index, name);
5290 error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
5291 uint32 immediate_data_size,
5292 const void* cmd_data) {
5293 const gles2::cmds::BindAttribLocationBucket& c =
5294 *static_cast<const gles2::cmds::BindAttribLocationBucket*>(cmd_data);
5295 GLuint program = static_cast<GLuint>(c.program);
5296 GLuint index = static_cast<GLuint>(c.index);
5297 Bucket* bucket = GetBucket(c.name_bucket_id);
5298 if (!bucket || bucket->size() == 0) {
5299 return error::kInvalidArguments;
5301 std::string name_str;
5302 if (!bucket->GetAsString(&name_str)) {
5303 return error::kInvalidArguments;
5305 DoBindAttribLocation(program, index, name_str.c_str());
5306 return error::kNoError;
5309 void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM(
5310 GLuint program_id, GLint location, const char* name) {
5311 if (!StringIsValidForGLES(name)) {
5312 LOCAL_SET_GL_ERROR(
5313 GL_INVALID_VALUE,
5314 "glBindUniformLocationCHROMIUM", "Invalid character");
5315 return;
5317 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
5318 LOCAL_SET_GL_ERROR(
5319 GL_INVALID_OPERATION,
5320 "glBindUniformLocationCHROMIUM", "reserved prefix");
5321 return;
5323 if (location < 0 || static_cast<uint32>(location) >=
5324 (group_->max_fragment_uniform_vectors() +
5325 group_->max_vertex_uniform_vectors()) * 4) {
5326 LOCAL_SET_GL_ERROR(
5327 GL_INVALID_VALUE,
5328 "glBindUniformLocationCHROMIUM", "location out of range");
5329 return;
5331 Program* program = GetProgramInfoNotShader(
5332 program_id, "glBindUniformLocationCHROMIUM");
5333 if (!program) {
5334 return;
5336 if (!program->SetUniformLocationBinding(name, location)) {
5337 LOCAL_SET_GL_ERROR(
5338 GL_INVALID_VALUE,
5339 "glBindUniformLocationCHROMIUM", "location out of range");
5343 error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMBucket(
5344 uint32 immediate_data_size,
5345 const void* cmd_data) {
5346 const gles2::cmds::BindUniformLocationCHROMIUMBucket& c =
5347 *static_cast<const gles2::cmds::BindUniformLocationCHROMIUMBucket*>(
5348 cmd_data);
5349 GLuint program = static_cast<GLuint>(c.program);
5350 GLint location = static_cast<GLint>(c.location);
5351 Bucket* bucket = GetBucket(c.name_bucket_id);
5352 if (!bucket || bucket->size() == 0) {
5353 return error::kInvalidArguments;
5355 std::string name_str;
5356 if (!bucket->GetAsString(&name_str)) {
5357 return error::kInvalidArguments;
5359 DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
5360 return error::kNoError;
5363 error::Error GLES2DecoderImpl::HandleDeleteShader(uint32 immediate_data_size,
5364 const void* cmd_data) {
5365 const gles2::cmds::DeleteShader& c =
5366 *static_cast<const gles2::cmds::DeleteShader*>(cmd_data);
5367 GLuint client_id = c.shader;
5368 if (client_id) {
5369 Shader* shader = GetShader(client_id);
5370 if (shader) {
5371 if (!shader->IsDeleted()) {
5372 shader_manager()->Delete(shader);
5374 } else {
5375 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glDeleteShader", "unknown shader");
5378 return error::kNoError;
5381 error::Error GLES2DecoderImpl::HandleDeleteProgram(uint32 immediate_data_size,
5382 const void* cmd_data) {
5383 const gles2::cmds::DeleteProgram& c =
5384 *static_cast<const gles2::cmds::DeleteProgram*>(cmd_data);
5385 GLuint client_id = c.program;
5386 if (client_id) {
5387 Program* program = GetProgram(client_id);
5388 if (program) {
5389 if (!program->IsDeleted()) {
5390 program_manager()->MarkAsDeleted(shader_manager(), program);
5392 } else {
5393 LOCAL_SET_GL_ERROR(
5394 GL_INVALID_VALUE, "glDeleteProgram", "unknown program");
5397 return error::kNoError;
5400 error::Error GLES2DecoderImpl::DoClear(GLbitfield mask) {
5401 DCHECK(!ShouldDeferDraws());
5402 if (CheckBoundFramebuffersValid("glClear")) {
5403 ApplyDirtyState();
5404 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
5405 if (workarounds().gl_clear_broken) {
5406 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::ClearWorkaround",
5407 GetErrorState());
5408 if (!BoundFramebufferHasDepthAttachment())
5409 mask &= ~GL_DEPTH_BUFFER_BIT;
5410 if (!BoundFramebufferHasStencilAttachment())
5411 mask &= ~GL_STENCIL_BUFFER_BIT;
5412 clear_framebuffer_blit_->ClearFramebuffer(
5413 this, GetBoundReadFrameBufferSize(), mask, state_.color_clear_red,
5414 state_.color_clear_green, state_.color_clear_blue,
5415 state_.color_clear_alpha, state_.depth_clear, state_.stencil_clear);
5416 return error::kNoError;
5418 glClear(mask);
5420 return error::kNoError;
5423 void GLES2DecoderImpl::DoFramebufferRenderbuffer(
5424 GLenum target, GLenum attachment, GLenum renderbuffertarget,
5425 GLuint client_renderbuffer_id) {
5426 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5427 if (!framebuffer) {
5428 LOCAL_SET_GL_ERROR(
5429 GL_INVALID_OPERATION,
5430 "glFramebufferRenderbuffer", "no framebuffer bound");
5431 return;
5433 GLuint service_id = 0;
5434 Renderbuffer* renderbuffer = NULL;
5435 if (client_renderbuffer_id) {
5436 renderbuffer = GetRenderbuffer(client_renderbuffer_id);
5437 if (!renderbuffer) {
5438 LOCAL_SET_GL_ERROR(
5439 GL_INVALID_OPERATION,
5440 "glFramebufferRenderbuffer", "unknown renderbuffer");
5441 return;
5443 service_id = renderbuffer->service_id();
5445 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glFramebufferRenderbuffer");
5446 glFramebufferRenderbufferEXT(
5447 target, attachment, renderbuffertarget, service_id);
5448 GLenum error = LOCAL_PEEK_GL_ERROR("glFramebufferRenderbuffer");
5449 if (error == GL_NO_ERROR) {
5450 framebuffer->AttachRenderbuffer(attachment, renderbuffer);
5452 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
5453 framebuffer_state_.clear_state_dirty = true;
5455 OnFboChanged();
5458 void GLES2DecoderImpl::DoDisable(GLenum cap) {
5459 if (SetCapabilityState(cap, false)) {
5460 glDisable(cap);
5464 void GLES2DecoderImpl::DoEnable(GLenum cap) {
5465 if (SetCapabilityState(cap, true)) {
5466 glEnable(cap);
5470 void GLES2DecoderImpl::DoDepthRangef(GLclampf znear, GLclampf zfar) {
5471 state_.z_near = std::min(1.0f, std::max(0.0f, znear));
5472 state_.z_far = std::min(1.0f, std::max(0.0f, zfar));
5473 glDepthRange(znear, zfar);
5476 void GLES2DecoderImpl::DoSampleCoverage(GLclampf value, GLboolean invert) {
5477 state_.sample_coverage_value = std::min(1.0f, std::max(0.0f, value));
5478 state_.sample_coverage_invert = (invert != 0);
5479 glSampleCoverage(state_.sample_coverage_value, invert);
5482 // Assumes framebuffer is complete.
5483 void GLES2DecoderImpl::ClearUnclearedAttachments(
5484 GLenum target, Framebuffer* framebuffer) {
5485 if (target == GL_READ_FRAMEBUFFER_EXT) {
5486 // bind this to the DRAW point, clear then bind back to READ
5487 // TODO(gman): I don't think there is any guarantee that an FBO that
5488 // is complete on the READ attachment will be complete as a DRAW
5489 // attachment.
5490 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
5491 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, framebuffer->service_id());
5493 GLbitfield clear_bits = 0;
5494 if (framebuffer->HasUnclearedColorAttachments()) {
5495 glClearColor(
5496 0.0f, 0.0f, 0.0f,
5497 (GLES2Util::GetChannelsForFormat(
5498 framebuffer->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0.0f :
5499 1.0f);
5500 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
5501 clear_bits |= GL_COLOR_BUFFER_BIT;
5502 if (feature_info_->feature_flags().ext_draw_buffers)
5503 framebuffer->PrepareDrawBuffersForClear();
5506 if (framebuffer->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) ||
5507 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
5508 glClearStencil(0);
5509 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
5510 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
5511 clear_bits |= GL_STENCIL_BUFFER_BIT;
5514 if (framebuffer->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
5515 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
5516 glClearDepth(1.0f);
5517 state_.SetDeviceDepthMask(GL_TRUE);
5518 clear_bits |= GL_DEPTH_BUFFER_BIT;
5521 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
5522 glClear(clear_bits);
5524 if ((clear_bits & GL_COLOR_BUFFER_BIT) != 0 &&
5525 feature_info_->feature_flags().ext_draw_buffers)
5526 framebuffer->RestoreDrawBuffersAfterClear();
5528 framebuffer_manager()->MarkAttachmentsAsCleared(
5529 framebuffer, renderbuffer_manager(), texture_manager());
5531 RestoreClearState();
5533 if (target == GL_READ_FRAMEBUFFER_EXT) {
5534 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, framebuffer->service_id());
5535 Framebuffer* draw_framebuffer =
5536 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
5537 GLuint service_id = draw_framebuffer ? draw_framebuffer->service_id() :
5538 GetBackbufferServiceId();
5539 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, service_id);
5543 void GLES2DecoderImpl::RestoreClearState() {
5544 framebuffer_state_.clear_state_dirty = true;
5545 glClearColor(
5546 state_.color_clear_red, state_.color_clear_green, state_.color_clear_blue,
5547 state_.color_clear_alpha);
5548 glClearStencil(state_.stencil_clear);
5549 glClearDepth(state_.depth_clear);
5550 if (state_.enable_flags.scissor_test) {
5551 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
5555 GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
5556 Framebuffer* framebuffer =
5557 GetFramebufferInfoForTarget(target);
5558 if (!framebuffer) {
5559 return GL_FRAMEBUFFER_COMPLETE;
5561 GLenum completeness = framebuffer->IsPossiblyComplete();
5562 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
5563 return completeness;
5565 return framebuffer->GetStatus(texture_manager(), target);
5568 void GLES2DecoderImpl::DoFramebufferTexture2D(
5569 GLenum target, GLenum attachment, GLenum textarget,
5570 GLuint client_texture_id, GLint level) {
5571 DoFramebufferTexture2DCommon(
5572 "glFramebufferTexture2D", target, attachment,
5573 textarget, client_texture_id, level, 0);
5576 void GLES2DecoderImpl::DoFramebufferTexture2DMultisample(
5577 GLenum target, GLenum attachment, GLenum textarget,
5578 GLuint client_texture_id, GLint level, GLsizei samples) {
5579 DoFramebufferTexture2DCommon(
5580 "glFramebufferTexture2DMultisample", target, attachment,
5581 textarget, client_texture_id, level, samples);
5584 void GLES2DecoderImpl::DoFramebufferTexture2DCommon(
5585 const char* name, GLenum target, GLenum attachment, GLenum textarget,
5586 GLuint client_texture_id, GLint level, GLsizei samples) {
5587 if (samples > renderbuffer_manager()->max_samples()) {
5588 LOCAL_SET_GL_ERROR(
5589 GL_INVALID_VALUE,
5590 "glFramebufferTexture2DMultisample", "samples too large");
5591 return;
5593 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5594 if (!framebuffer) {
5595 LOCAL_SET_GL_ERROR(
5596 GL_INVALID_OPERATION,
5597 name, "no framebuffer bound.");
5598 return;
5600 GLuint service_id = 0;
5601 TextureRef* texture_ref = NULL;
5602 if (client_texture_id) {
5603 texture_ref = GetTexture(client_texture_id);
5604 if (!texture_ref) {
5605 LOCAL_SET_GL_ERROR(
5606 GL_INVALID_OPERATION,
5607 name, "unknown texture_ref");
5608 return;
5610 service_id = texture_ref->service_id();
5613 if (!texture_manager()->ValidForTarget(textarget, level, 0, 0, 1)) {
5614 LOCAL_SET_GL_ERROR(
5615 GL_INVALID_VALUE,
5616 name, "level out of range");
5617 return;
5620 if (texture_ref)
5621 DoWillUseTexImageIfNeeded(texture_ref->texture(), textarget);
5623 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(name);
5624 if (0 == samples) {
5625 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
5626 } else {
5627 if (features().use_img_for_multisampled_render_to_texture) {
5628 glFramebufferTexture2DMultisampleIMG(target, attachment, textarget,
5629 service_id, level, samples);
5630 } else {
5631 glFramebufferTexture2DMultisampleEXT(target, attachment, textarget,
5632 service_id, level, samples);
5635 GLenum error = LOCAL_PEEK_GL_ERROR(name);
5636 if (error == GL_NO_ERROR) {
5637 framebuffer->AttachTexture(attachment, texture_ref, textarget, level,
5638 samples);
5640 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
5641 framebuffer_state_.clear_state_dirty = true;
5644 if (texture_ref)
5645 DoDidUseTexImageIfNeeded(texture_ref->texture(), textarget);
5647 OnFboChanged();
5650 void GLES2DecoderImpl::DoFramebufferTextureLayer(
5651 GLenum target, GLenum attachment, GLuint client_texture_id,
5652 GLint level, GLint layer) {
5653 // TODO(zmo): Unsafe ES3 API, missing states update.
5654 GLuint service_id = 0;
5655 TextureRef* texture_ref = NULL;
5656 if (client_texture_id) {
5657 texture_ref = GetTexture(client_texture_id);
5658 if (!texture_ref) {
5659 LOCAL_SET_GL_ERROR(
5660 GL_INVALID_OPERATION,
5661 "glFramebufferTextureLayer", "unknown texture_ref");
5662 return;
5664 service_id = texture_ref->service_id();
5666 glFramebufferTextureLayer(target, attachment, service_id, level, layer);
5669 void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
5670 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
5671 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5672 if (!framebuffer) {
5673 LOCAL_SET_GL_ERROR(
5674 GL_INVALID_OPERATION,
5675 "glGetFramebufferAttachmentParameteriv", "no framebuffer bound");
5676 return;
5678 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
5679 const Framebuffer::Attachment* attachment_object =
5680 framebuffer->GetAttachment(attachment);
5681 *params = attachment_object ? attachment_object->object_name() : 0;
5682 } else {
5683 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT &&
5684 features().use_img_for_multisampled_render_to_texture) {
5685 pname = GL_TEXTURE_SAMPLES_IMG;
5687 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
5691 void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
5692 GLenum target, GLenum pname, GLint* params) {
5693 Renderbuffer* renderbuffer =
5694 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5695 if (!renderbuffer) {
5696 LOCAL_SET_GL_ERROR(
5697 GL_INVALID_OPERATION,
5698 "glGetRenderbufferParameteriv", "no renderbuffer bound");
5699 return;
5702 EnsureRenderbufferBound();
5703 switch (pname) {
5704 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5705 *params = renderbuffer->internal_format();
5706 break;
5707 case GL_RENDERBUFFER_WIDTH:
5708 *params = renderbuffer->width();
5709 break;
5710 case GL_RENDERBUFFER_HEIGHT:
5711 *params = renderbuffer->height();
5712 break;
5713 case GL_RENDERBUFFER_SAMPLES_EXT:
5714 if (features().use_img_for_multisampled_render_to_texture) {
5715 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_IMG,
5716 params);
5717 } else {
5718 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_EXT,
5719 params);
5721 default:
5722 glGetRenderbufferParameterivEXT(target, pname, params);
5723 break;
5727 void GLES2DecoderImpl::DoBlitFramebufferCHROMIUM(
5728 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
5729 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
5730 GLbitfield mask, GLenum filter) {
5731 DCHECK(!ShouldDeferReads() && !ShouldDeferDraws());
5733 if (!CheckBoundFramebuffersValid("glBlitFramebufferCHROMIUM")) {
5734 return;
5737 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
5738 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
5739 BlitFramebufferHelper(
5740 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5741 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST,
5742 state_.enable_flags.scissor_test);
5745 void GLES2DecoderImpl::EnsureRenderbufferBound() {
5746 if (!state_.bound_renderbuffer_valid) {
5747 state_.bound_renderbuffer_valid = true;
5748 glBindRenderbufferEXT(GL_RENDERBUFFER,
5749 state_.bound_renderbuffer.get()
5750 ? state_.bound_renderbuffer->service_id()
5751 : 0);
5755 void GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(
5756 const FeatureInfo* feature_info,
5757 GLenum target,
5758 GLsizei samples,
5759 GLenum internal_format,
5760 GLsizei width,
5761 GLsizei height) {
5762 // TODO(sievers): This could be resolved at the GL binding level, but the
5763 // binding process is currently a bit too 'brute force'.
5764 if (feature_info->gl_version_info().is_angle) {
5765 glRenderbufferStorageMultisampleANGLE(
5766 target, samples, internal_format, width, height);
5767 } else if (feature_info->feature_flags().use_core_framebuffer_multisample) {
5768 glRenderbufferStorageMultisample(
5769 target, samples, internal_format, width, height);
5770 } else {
5771 glRenderbufferStorageMultisampleEXT(
5772 target, samples, internal_format, width, height);
5776 void GLES2DecoderImpl::BlitFramebufferHelper(GLint srcX0,
5777 GLint srcY0,
5778 GLint srcX1,
5779 GLint srcY1,
5780 GLint dstX0,
5781 GLint dstY0,
5782 GLint dstX1,
5783 GLint dstY1,
5784 GLbitfield mask,
5785 GLenum filter) {
5786 // TODO(sievers): This could be resolved at the GL binding level, but the
5787 // binding process is currently a bit too 'brute force'.
5788 if (feature_info_->gl_version_info().is_angle) {
5789 glBlitFramebufferANGLE(
5790 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5791 } else if (feature_info_->feature_flags().use_core_framebuffer_multisample) {
5792 glBlitFramebuffer(
5793 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5794 } else {
5795 glBlitFramebufferEXT(
5796 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5800 bool GLES2DecoderImpl::ValidateRenderbufferStorageMultisample(
5801 GLsizei samples,
5802 GLenum internalformat,
5803 GLsizei width,
5804 GLsizei height) {
5805 if (samples > renderbuffer_manager()->max_samples()) {
5806 LOCAL_SET_GL_ERROR(
5807 GL_INVALID_VALUE,
5808 "glRenderbufferStorageMultisample", "samples too large");
5809 return false;
5812 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
5813 height > renderbuffer_manager()->max_renderbuffer_size()) {
5814 LOCAL_SET_GL_ERROR(
5815 GL_INVALID_VALUE,
5816 "glRenderbufferStorageMultisample", "dimensions too large");
5817 return false;
5820 uint32 estimated_size = 0;
5821 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
5822 width, height, samples, internalformat, &estimated_size)) {
5823 LOCAL_SET_GL_ERROR(
5824 GL_OUT_OF_MEMORY,
5825 "glRenderbufferStorageMultisample", "dimensions too large");
5826 return false;
5829 if (!EnsureGPUMemoryAvailable(estimated_size)) {
5830 LOCAL_SET_GL_ERROR(
5831 GL_OUT_OF_MEMORY,
5832 "glRenderbufferStorageMultisample", "out of memory");
5833 return false;
5836 return true;
5839 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleCHROMIUM(
5840 GLenum target, GLsizei samples, GLenum internalformat,
5841 GLsizei width, GLsizei height) {
5842 Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5843 if (!renderbuffer) {
5844 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
5845 "glRenderbufferStorageMultisampleCHROMIUM",
5846 "no renderbuffer bound");
5847 return;
5850 if (!ValidateRenderbufferStorageMultisample(
5851 samples, internalformat, width, height)) {
5852 return;
5855 EnsureRenderbufferBound();
5856 GLenum impl_format =
5857 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5858 internalformat);
5859 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(
5860 "glRenderbufferStorageMultisampleCHROMIUM");
5861 RenderbufferStorageMultisampleHelper(
5862 feature_info_.get(), target, samples, impl_format, width, height);
5863 GLenum error =
5864 LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleCHROMIUM");
5865 if (error == GL_NO_ERROR) {
5866 if (workarounds().validate_multisample_buffer_allocation) {
5867 if (!VerifyMultisampleRenderbufferIntegrity(
5868 renderbuffer->service_id(), impl_format)) {
5869 LOCAL_SET_GL_ERROR(
5870 GL_OUT_OF_MEMORY,
5871 "glRenderbufferStorageMultisampleCHROMIUM", "out of memory");
5872 return;
5876 // TODO(gman): If renderbuffers tracked which framebuffers they were
5877 // attached to we could just mark those framebuffers as not complete.
5878 framebuffer_manager()->IncFramebufferStateChangeCount();
5879 renderbuffer_manager()->SetInfo(
5880 renderbuffer, samples, internalformat, width, height);
5884 // This is the handler for multisampled_render_to_texture extensions.
5885 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleEXT(
5886 GLenum target, GLsizei samples, GLenum internalformat,
5887 GLsizei width, GLsizei height) {
5888 Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5889 if (!renderbuffer) {
5890 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
5891 "glRenderbufferStorageMultisampleEXT",
5892 "no renderbuffer bound");
5893 return;
5896 if (!ValidateRenderbufferStorageMultisample(
5897 samples, internalformat, width, height)) {
5898 return;
5901 EnsureRenderbufferBound();
5902 GLenum impl_format =
5903 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5904 internalformat);
5905 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorageMultisampleEXT");
5906 if (features().use_img_for_multisampled_render_to_texture) {
5907 glRenderbufferStorageMultisampleIMG(
5908 target, samples, impl_format, width, height);
5909 } else {
5910 glRenderbufferStorageMultisampleEXT(
5911 target, samples, impl_format, width, height);
5913 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleEXT");
5914 if (error == GL_NO_ERROR) {
5915 // TODO(gman): If renderbuffers tracked which framebuffers they were
5916 // attached to we could just mark those framebuffers as not complete.
5917 framebuffer_manager()->IncFramebufferStateChangeCount();
5918 renderbuffer_manager()->SetInfo(
5919 renderbuffer, samples, internalformat, width, height);
5923 // This function validates the allocation of a multisampled renderbuffer
5924 // by clearing it to a key color, blitting the contents to a texture, and
5925 // reading back the color to ensure it matches the key.
5926 bool GLES2DecoderImpl::VerifyMultisampleRenderbufferIntegrity(
5927 GLuint renderbuffer, GLenum format) {
5929 // Only validate color buffers.
5930 // These formats have been selected because they are very common or are known
5931 // to be used by the WebGL backbuffer. If problems are observed with other
5932 // color formats they can be added here.
5933 switch (format) {
5934 case GL_RGB:
5935 case GL_RGB8:
5936 case GL_RGBA:
5937 case GL_RGBA8:
5938 break;
5939 default:
5940 return true;
5943 GLint draw_framebuffer, read_framebuffer;
5945 // Cache framebuffer and texture bindings.
5946 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &draw_framebuffer);
5947 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &read_framebuffer);
5949 if (!validation_texture_) {
5950 GLint bound_texture;
5951 glGetIntegerv(GL_TEXTURE_BINDING_2D, &bound_texture);
5953 // Create additional resources needed for the verification.
5954 glGenTextures(1, &validation_texture_);
5955 glGenFramebuffersEXT(1, &validation_fbo_multisample_);
5956 glGenFramebuffersEXT(1, &validation_fbo_);
5958 // Texture only needs to be 1x1.
5959 glBindTexture(GL_TEXTURE_2D, validation_texture_);
5960 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB,
5961 GL_UNSIGNED_BYTE, NULL);
5963 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
5964 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5965 GL_TEXTURE_2D, validation_texture_, 0);
5967 glBindTexture(GL_TEXTURE_2D, bound_texture);
5970 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
5971 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5972 GL_RENDERBUFFER, renderbuffer);
5974 // Cache current state and reset it to the values we require.
5975 GLboolean scissor_enabled = false;
5976 glGetBooleanv(GL_SCISSOR_TEST, &scissor_enabled);
5977 if (scissor_enabled)
5978 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
5980 GLboolean color_mask[4] = {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE};
5981 glGetBooleanv(GL_COLOR_WRITEMASK, color_mask);
5982 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
5984 GLfloat clear_color[4] = {0.0f, 0.0f, 0.0f, 0.0f};
5985 glGetFloatv(GL_COLOR_CLEAR_VALUE, clear_color);
5986 glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
5988 // Clear the buffer to the desired key color.
5989 glClear(GL_COLOR_BUFFER_BIT);
5991 // Blit from the multisample buffer to a standard texture.
5992 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, validation_fbo_multisample_);
5993 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, validation_fbo_);
5995 BlitFramebufferHelper(
5996 0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
5998 // Read a pixel from the buffer.
5999 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
6001 unsigned char pixel[3] = {0, 0, 0};
6002 glReadPixels(0, 0, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &pixel);
6004 // Detach the renderbuffer.
6005 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
6006 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
6007 GL_RENDERBUFFER, 0);
6009 // Restore cached state.
6010 if (scissor_enabled)
6011 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
6013 state_.SetDeviceColorMask(
6014 color_mask[0], color_mask[1], color_mask[2], color_mask[3]);
6015 glClearColor(clear_color[0], clear_color[1], clear_color[2], clear_color[3]);
6016 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, draw_framebuffer);
6017 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, read_framebuffer);
6019 // Return true if the pixel matched the desired key color.
6020 return (pixel[0] == 0xFF &&
6021 pixel[1] == 0x00 &&
6022 pixel[2] == 0xFF);
6025 void GLES2DecoderImpl::DoRenderbufferStorage(
6026 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
6027 Renderbuffer* renderbuffer =
6028 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
6029 if (!renderbuffer) {
6030 LOCAL_SET_GL_ERROR(
6031 GL_INVALID_OPERATION,
6032 "glRenderbufferStorage", "no renderbuffer bound");
6033 return;
6036 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
6037 height > renderbuffer_manager()->max_renderbuffer_size()) {
6038 LOCAL_SET_GL_ERROR(
6039 GL_INVALID_VALUE, "glRenderbufferStorage", "dimensions too large");
6040 return;
6043 uint32 estimated_size = 0;
6044 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
6045 width, height, 1, internalformat, &estimated_size)) {
6046 LOCAL_SET_GL_ERROR(
6047 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "dimensions too large");
6048 return;
6051 if (!EnsureGPUMemoryAvailable(estimated_size)) {
6052 LOCAL_SET_GL_ERROR(
6053 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "out of memory");
6054 return;
6057 EnsureRenderbufferBound();
6058 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorage");
6059 glRenderbufferStorageEXT(
6060 target,
6061 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
6062 internalformat),
6063 width,
6064 height);
6065 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorage");
6066 if (error == GL_NO_ERROR) {
6067 // TODO(gman): If tetxures tracked which framebuffers they were attached to
6068 // we could just mark those framebuffers as not complete.
6069 framebuffer_manager()->IncFramebufferStateChangeCount();
6070 renderbuffer_manager()->SetInfo(
6071 renderbuffer, 1, internalformat, width, height);
6075 void GLES2DecoderImpl::DoLinkProgram(GLuint program_id) {
6076 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
6077 Program* program = GetProgramInfoNotShader(
6078 program_id, "glLinkProgram");
6079 if (!program) {
6080 return;
6083 LogClientServiceForInfo(program, program_id, "glLinkProgram");
6084 if (program->Link(shader_manager(),
6085 workarounds().count_all_in_varyings_packing ?
6086 Program::kCountAll : Program::kCountOnlyStaticallyUsed,
6087 shader_cache_callback_)) {
6088 if (program == state_.current_program.get()) {
6089 if (workarounds().use_current_program_after_successful_link)
6090 glUseProgram(program->service_id());
6091 if (workarounds().clear_uniforms_before_first_program_use)
6092 program_manager()->ClearUniforms(program);
6096 // LinkProgram can be very slow. Exit command processing to allow for
6097 // context preemption and GPU watchdog checks.
6098 ExitCommandProcessingEarly();
6101 void GLES2DecoderImpl::DoSamplerParameterfv(
6102 GLuint sampler, GLenum pname, const GLfloat* params) {
6103 DCHECK(params);
6104 glSamplerParameterf(sampler, pname, params[0]);
6107 void GLES2DecoderImpl::DoSamplerParameteriv(
6108 GLuint sampler, GLenum pname, const GLint* params) {
6109 DCHECK(params);
6110 glSamplerParameteri(sampler, pname, params[0]);
6113 void GLES2DecoderImpl::DoTexParameterf(
6114 GLenum target, GLenum pname, GLfloat param) {
6115 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
6116 &state_, target);
6117 if (!texture) {
6118 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterf", "unknown texture");
6119 return;
6122 texture_manager()->SetParameterf(
6123 "glTexParameterf", GetErrorState(), texture, pname, param);
6126 void GLES2DecoderImpl::DoTexParameteri(
6127 GLenum target, GLenum pname, GLint param) {
6128 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
6129 &state_, target);
6130 if (!texture) {
6131 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameteri", "unknown texture");
6132 return;
6135 texture_manager()->SetParameteri(
6136 "glTexParameteri", GetErrorState(), texture, pname, param);
6139 void GLES2DecoderImpl::DoTexParameterfv(
6140 GLenum target, GLenum pname, const GLfloat* params) {
6141 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
6142 &state_, target);
6143 if (!texture) {
6144 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterfv", "unknown texture");
6145 return;
6148 texture_manager()->SetParameterf(
6149 "glTexParameterfv", GetErrorState(), texture, pname, *params);
6152 void GLES2DecoderImpl::DoTexParameteriv(
6153 GLenum target, GLenum pname, const GLint* params) {
6154 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
6155 &state_, target);
6156 if (!texture) {
6157 LOCAL_SET_GL_ERROR(
6158 GL_INVALID_VALUE, "glTexParameteriv", "unknown texture");
6159 return;
6162 texture_manager()->SetParameteri(
6163 "glTexParameteriv", GetErrorState(), texture, pname, *params);
6166 bool GLES2DecoderImpl::CheckCurrentValuebuffer(const char* function_name) {
6167 if (!state_.bound_valuebuffer.get()) {
6168 // There is no valuebuffer bound
6169 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
6170 "no valuebuffer in use");
6171 return false;
6173 return true;
6176 bool GLES2DecoderImpl::CheckCurrentValuebufferForSubscription(
6177 GLenum subscription,
6178 const char* function_name) {
6179 if (!CheckCurrentValuebuffer(function_name)) {
6180 return false;
6182 if (!state_.bound_valuebuffer.get()->IsSubscribed(subscription)) {
6183 // The valuebuffer is not subscribed to the target
6184 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
6185 "valuebuffer is not subscribed");
6186 return false;
6188 return true;
6191 bool GLES2DecoderImpl::CheckSubscriptionTarget(GLint location,
6192 GLenum subscription,
6193 const char* function_name) {
6194 if (!CheckCurrentProgramForUniform(location, function_name)) {
6195 return false;
6197 GLint real_location = -1;
6198 GLint array_index = -1;
6199 const Program::UniformInfo* info =
6200 state_.current_program->GetUniformInfoByFakeLocation(
6201 location, &real_location, &array_index);
6202 if (!info) {
6203 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, "unknown location");
6204 return false;
6206 if ((ValuebufferManager::ApiTypeForSubscriptionTarget(subscription) &
6207 info->accepts_api_type) == 0) {
6208 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
6209 "wrong type for subscription");
6210 return false;
6212 return true;
6215 bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
6216 if (!state_.current_program.get()) {
6217 // The program does not exist.
6218 LOCAL_SET_GL_ERROR(
6219 GL_INVALID_OPERATION, function_name, "no program in use");
6220 return false;
6222 if (!state_.current_program->InUse()) {
6223 LOCAL_SET_GL_ERROR(
6224 GL_INVALID_OPERATION, function_name, "program not linked");
6225 return false;
6227 return true;
6230 bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
6231 GLint location, const char* function_name) {
6232 if (!CheckCurrentProgram(function_name)) {
6233 return false;
6235 return location != -1;
6238 bool GLES2DecoderImpl::CheckDrawingFeedbackLoops() {
6239 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
6240 if (!framebuffer)
6241 return false;
6242 const Framebuffer::Attachment* attachment =
6243 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
6244 if (!attachment)
6245 return false;
6247 DCHECK(state_.current_program.get());
6248 const Program::SamplerIndices& sampler_indices =
6249 state_.current_program->sampler_indices();
6250 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6251 const Program::UniformInfo* uniform_info =
6252 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6253 DCHECK(uniform_info);
6254 if (uniform_info->type != GL_SAMPLER_2D)
6255 continue;
6256 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6257 GLuint texture_unit_index = uniform_info->texture_units[jj];
6258 if (texture_unit_index >= state_.texture_units.size())
6259 continue;
6260 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6261 TextureRef* texture_ref =
6262 texture_unit.GetInfoForSamplerType(GL_SAMPLER_2D).get();
6263 if (attachment->IsTexture(texture_ref))
6264 return true;
6267 return false;
6270 bool GLES2DecoderImpl::CheckUniformForApiType(
6271 const Program::UniformInfo* info,
6272 const char* function_name,
6273 Program::UniformApiType api_type) {
6274 DCHECK(info);
6275 if ((api_type & info->accepts_api_type) == 0) {
6276 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
6277 "wrong uniform function for type");
6278 return false;
6280 return true;
6283 bool GLES2DecoderImpl::PrepForSetUniformByLocation(
6284 GLint fake_location,
6285 const char* function_name,
6286 Program::UniformApiType api_type,
6287 GLint* real_location,
6288 GLenum* type,
6289 GLsizei* count) {
6290 DCHECK(type);
6291 DCHECK(count);
6292 DCHECK(real_location);
6294 if (!CheckCurrentProgramForUniform(fake_location, function_name)) {
6295 return false;
6297 GLint array_index = -1;
6298 const Program::UniformInfo* info =
6299 state_.current_program->GetUniformInfoByFakeLocation(
6300 fake_location, real_location, &array_index);
6301 if (!info) {
6302 LOCAL_SET_GL_ERROR(
6303 GL_INVALID_OPERATION, function_name, "unknown location");
6304 return false;
6306 if (!CheckUniformForApiType(info, function_name, api_type)) {
6307 return false;
6309 if (*count > 1 && !info->is_array) {
6310 LOCAL_SET_GL_ERROR(
6311 GL_INVALID_OPERATION, function_name, "count > 1 for non-array");
6312 return false;
6314 *count = std::min(info->size - array_index, *count);
6315 if (*count <= 0) {
6316 return false;
6318 *type = info->type;
6319 return true;
6322 void GLES2DecoderImpl::DoUniform1i(GLint fake_location, GLint v0) {
6323 GLenum type = 0;
6324 GLsizei count = 1;
6325 GLint real_location = -1;
6326 if (!PrepForSetUniformByLocation(fake_location,
6327 "glUniform1i",
6328 Program::kUniform1i,
6329 &real_location,
6330 &type,
6331 &count)) {
6332 return;
6334 if (!state_.current_program->SetSamplers(
6335 state_.texture_units.size(), fake_location, 1, &v0)) {
6336 LOCAL_SET_GL_ERROR(
6337 GL_INVALID_VALUE, "glUniform1i", "texture unit out of range");
6338 return;
6340 glUniform1i(real_location, v0);
6343 void GLES2DecoderImpl::DoUniform1iv(
6344 GLint fake_location, GLsizei count, const GLint *value) {
6345 GLenum type = 0;
6346 GLint real_location = -1;
6347 if (!PrepForSetUniformByLocation(fake_location,
6348 "glUniform1iv",
6349 Program::kUniform1i,
6350 &real_location,
6351 &type,
6352 &count)) {
6353 return;
6355 if (type == GL_SAMPLER_2D || type == GL_SAMPLER_2D_RECT_ARB ||
6356 type == GL_SAMPLER_CUBE || type == GL_SAMPLER_EXTERNAL_OES) {
6357 if (!state_.current_program->SetSamplers(
6358 state_.texture_units.size(), fake_location, count, value)) {
6359 LOCAL_SET_GL_ERROR(
6360 GL_INVALID_VALUE, "glUniform1iv", "texture unit out of range");
6361 return;
6364 glUniform1iv(real_location, count, value);
6367 void GLES2DecoderImpl::DoUniform1fv(
6368 GLint fake_location, GLsizei count, const GLfloat* value) {
6369 GLenum type = 0;
6370 GLint real_location = -1;
6371 if (!PrepForSetUniformByLocation(fake_location,
6372 "glUniform1fv",
6373 Program::kUniform1f,
6374 &real_location,
6375 &type,
6376 &count)) {
6377 return;
6379 if (type == GL_BOOL) {
6380 scoped_ptr<GLint[]> temp(new GLint[count]);
6381 for (GLsizei ii = 0; ii < count; ++ii) {
6382 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6384 DoUniform1iv(real_location, count, temp.get());
6385 } else {
6386 glUniform1fv(real_location, count, value);
6390 void GLES2DecoderImpl::DoUniform2fv(
6391 GLint fake_location, GLsizei count, const GLfloat* value) {
6392 GLenum type = 0;
6393 GLint real_location = -1;
6394 if (!PrepForSetUniformByLocation(fake_location,
6395 "glUniform2fv",
6396 Program::kUniform2f,
6397 &real_location,
6398 &type,
6399 &count)) {
6400 return;
6402 if (type == GL_BOOL_VEC2) {
6403 GLsizei num_values = count * 2;
6404 scoped_ptr<GLint[]> temp(new GLint[num_values]);
6405 for (GLsizei ii = 0; ii < num_values; ++ii) {
6406 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6408 glUniform2iv(real_location, count, temp.get());
6409 } else {
6410 glUniform2fv(real_location, count, value);
6414 void GLES2DecoderImpl::DoUniform3fv(
6415 GLint fake_location, GLsizei count, const GLfloat* value) {
6416 GLenum type = 0;
6417 GLint real_location = -1;
6418 if (!PrepForSetUniformByLocation(fake_location,
6419 "glUniform3fv",
6420 Program::kUniform3f,
6421 &real_location,
6422 &type,
6423 &count)) {
6424 return;
6426 if (type == GL_BOOL_VEC3) {
6427 GLsizei num_values = count * 3;
6428 scoped_ptr<GLint[]> temp(new GLint[num_values]);
6429 for (GLsizei ii = 0; ii < num_values; ++ii) {
6430 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6432 glUniform3iv(real_location, count, temp.get());
6433 } else {
6434 glUniform3fv(real_location, count, value);
6438 void GLES2DecoderImpl::DoUniform4fv(
6439 GLint fake_location, GLsizei count, const GLfloat* value) {
6440 GLenum type = 0;
6441 GLint real_location = -1;
6442 if (!PrepForSetUniformByLocation(fake_location,
6443 "glUniform4fv",
6444 Program::kUniform4f,
6445 &real_location,
6446 &type,
6447 &count)) {
6448 return;
6450 if (type == GL_BOOL_VEC4) {
6451 GLsizei num_values = count * 4;
6452 scoped_ptr<GLint[]> temp(new GLint[num_values]);
6453 for (GLsizei ii = 0; ii < num_values; ++ii) {
6454 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6456 glUniform4iv(real_location, count, temp.get());
6457 } else {
6458 glUniform4fv(real_location, count, value);
6462 void GLES2DecoderImpl::DoUniform2iv(
6463 GLint fake_location, GLsizei count, const GLint* value) {
6464 GLenum type = 0;
6465 GLint real_location = -1;
6466 if (!PrepForSetUniformByLocation(fake_location,
6467 "glUniform2iv",
6468 Program::kUniform2i,
6469 &real_location,
6470 &type,
6471 &count)) {
6472 return;
6474 glUniform2iv(real_location, count, value);
6477 void GLES2DecoderImpl::DoUniform3iv(
6478 GLint fake_location, GLsizei count, const GLint* value) {
6479 GLenum type = 0;
6480 GLint real_location = -1;
6481 if (!PrepForSetUniformByLocation(fake_location,
6482 "glUniform3iv",
6483 Program::kUniform3i,
6484 &real_location,
6485 &type,
6486 &count)) {
6487 return;
6489 glUniform3iv(real_location, count, value);
6492 void GLES2DecoderImpl::DoUniform4iv(
6493 GLint fake_location, GLsizei count, const GLint* value) {
6494 GLenum type = 0;
6495 GLint real_location = -1;
6496 if (!PrepForSetUniformByLocation(fake_location,
6497 "glUniform4iv",
6498 Program::kUniform4i,
6499 &real_location,
6500 &type,
6501 &count)) {
6502 return;
6504 glUniform4iv(real_location, count, value);
6507 void GLES2DecoderImpl::DoUniformMatrix2fv(
6508 GLint fake_location, GLsizei count, GLboolean transpose,
6509 const GLfloat* value) {
6510 GLenum type = 0;
6511 GLint real_location = -1;
6512 if (!PrepForSetUniformByLocation(fake_location,
6513 "glUniformMatrix2fv",
6514 Program::kUniformMatrix2f,
6515 &real_location,
6516 &type,
6517 &count)) {
6518 return;
6520 glUniformMatrix2fv(real_location, count, transpose, value);
6523 void GLES2DecoderImpl::DoUniformMatrix3fv(
6524 GLint fake_location, GLsizei count, GLboolean transpose,
6525 const GLfloat* value) {
6526 GLenum type = 0;
6527 GLint real_location = -1;
6528 if (!PrepForSetUniformByLocation(fake_location,
6529 "glUniformMatrix3fv",
6530 Program::kUniformMatrix3f,
6531 &real_location,
6532 &type,
6533 &count)) {
6534 return;
6536 glUniformMatrix3fv(real_location, count, transpose, value);
6539 void GLES2DecoderImpl::DoUniformMatrix4fv(
6540 GLint fake_location, GLsizei count, GLboolean transpose,
6541 const GLfloat* value) {
6542 GLenum type = 0;
6543 GLint real_location = -1;
6544 if (!PrepForSetUniformByLocation(fake_location,
6545 "glUniformMatrix4fv",
6546 Program::kUniformMatrix4f,
6547 &real_location,
6548 &type,
6549 &count)) {
6550 return;
6552 glUniformMatrix4fv(real_location, count, transpose, value);
6555 void GLES2DecoderImpl::DoUseProgram(GLuint program_id) {
6556 GLuint service_id = 0;
6557 Program* program = NULL;
6558 if (program_id) {
6559 program = GetProgramInfoNotShader(program_id, "glUseProgram");
6560 if (!program) {
6561 return;
6563 if (!program->IsValid()) {
6564 // Program was not linked successfully. (ie, glLinkProgram)
6565 LOCAL_SET_GL_ERROR(
6566 GL_INVALID_OPERATION, "glUseProgram", "program not linked");
6567 return;
6569 service_id = program->service_id();
6571 if (state_.current_program.get()) {
6572 program_manager()->UnuseProgram(shader_manager(),
6573 state_.current_program.get());
6575 state_.current_program = program;
6576 LogClientServiceMapping("glUseProgram", program_id, service_id);
6577 glUseProgram(service_id);
6578 if (state_.current_program.get()) {
6579 program_manager()->UseProgram(state_.current_program.get());
6580 if (workarounds().clear_uniforms_before_first_program_use)
6581 program_manager()->ClearUniforms(program);
6585 void GLES2DecoderImpl::RenderWarning(
6586 const char* filename, int line, const std::string& msg) {
6587 logger_.LogMessage(filename, line, std::string("RENDER WARNING: ") + msg);
6590 void GLES2DecoderImpl::PerformanceWarning(
6591 const char* filename, int line, const std::string& msg) {
6592 logger_.LogMessage(filename, line,
6593 std::string("PERFORMANCE WARNING: ") + msg);
6596 void GLES2DecoderImpl::DoWillUseTexImageIfNeeded(
6597 Texture* texture, GLenum textarget) {
6598 // Image is already in use if texture is attached to a framebuffer.
6599 if (texture && !texture->IsAttachedToFramebuffer()) {
6600 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6601 if (image) {
6602 ScopedGLErrorSuppressor suppressor(
6603 "GLES2DecoderImpl::DoWillUseTexImageIfNeeded",
6604 GetErrorState());
6605 glBindTexture(textarget, texture->service_id());
6606 image->WillUseTexImage();
6607 RestoreCurrentTextureBindings(&state_, textarget);
6612 void GLES2DecoderImpl::DoDidUseTexImageIfNeeded(
6613 Texture* texture, GLenum textarget) {
6614 // Image is still in use if texture is attached to a framebuffer.
6615 if (texture && !texture->IsAttachedToFramebuffer()) {
6616 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6617 if (image) {
6618 ScopedGLErrorSuppressor suppressor(
6619 "GLES2DecoderImpl::DoDidUseTexImageIfNeeded",
6620 GetErrorState());
6621 glBindTexture(textarget, texture->service_id());
6622 image->DidUseTexImage();
6623 RestoreCurrentTextureBindings(&state_, textarget);
6628 bool GLES2DecoderImpl::PrepareTexturesForRender() {
6629 DCHECK(state_.current_program.get());
6630 if (!texture_manager()->HaveUnrenderableTextures() &&
6631 !texture_manager()->HaveImages()) {
6632 return true;
6635 bool textures_set = false;
6636 const Program::SamplerIndices& sampler_indices =
6637 state_.current_program->sampler_indices();
6638 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6639 const Program::UniformInfo* uniform_info =
6640 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6641 DCHECK(uniform_info);
6642 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6643 GLuint texture_unit_index = uniform_info->texture_units[jj];
6644 if (texture_unit_index < state_.texture_units.size()) {
6645 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6646 TextureRef* texture_ref =
6647 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6648 GLenum textarget = GetBindTargetForSamplerType(uniform_info->type);
6649 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
6650 textures_set = true;
6651 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6652 glBindTexture(
6653 textarget,
6654 texture_manager()->black_texture_id(uniform_info->type));
6655 if (!texture_ref) {
6656 LOCAL_RENDER_WARNING(
6657 std::string("there is no texture bound to the unit ") +
6658 base::IntToString(texture_unit_index));
6659 } else {
6660 LOCAL_RENDER_WARNING(
6661 std::string("texture bound to texture unit ") +
6662 base::IntToString(texture_unit_index) +
6663 " is not renderable. It maybe non-power-of-2 and have"
6664 " incompatible texture filtering.");
6666 continue;
6669 if (textarget != GL_TEXTURE_CUBE_MAP) {
6670 Texture* texture = texture_ref->texture();
6671 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6672 if (image && !texture->IsAttachedToFramebuffer()) {
6673 ScopedGLErrorSuppressor suppressor(
6674 "GLES2DecoderImpl::PrepareTexturesForRender", GetErrorState());
6675 textures_set = true;
6676 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6677 image->WillUseTexImage();
6678 continue;
6682 // else: should this be an error?
6685 return !textures_set;
6688 void GLES2DecoderImpl::RestoreStateForTextures() {
6689 DCHECK(state_.current_program.get());
6690 const Program::SamplerIndices& sampler_indices =
6691 state_.current_program->sampler_indices();
6692 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6693 const Program::UniformInfo* uniform_info =
6694 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6695 DCHECK(uniform_info);
6696 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6697 GLuint texture_unit_index = uniform_info->texture_units[jj];
6698 if (texture_unit_index < state_.texture_units.size()) {
6699 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6700 TextureRef* texture_ref =
6701 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6702 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
6703 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6704 // Get the texture_ref info that was previously bound here.
6705 texture_ref = texture_unit.bind_target == GL_TEXTURE_2D
6706 ? texture_unit.bound_texture_2d.get()
6707 : texture_unit.bound_texture_cube_map.get();
6708 glBindTexture(texture_unit.bind_target,
6709 texture_ref ? texture_ref->service_id() : 0);
6710 continue;
6713 if (texture_unit.bind_target != GL_TEXTURE_CUBE_MAP) {
6714 Texture* texture = texture_ref->texture();
6715 gfx::GLImage* image =
6716 texture->GetLevelImage(texture_unit.bind_target, 0);
6717 if (image && !texture->IsAttachedToFramebuffer()) {
6718 ScopedGLErrorSuppressor suppressor(
6719 "GLES2DecoderImpl::RestoreStateForTextures", GetErrorState());
6720 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6721 image->DidUseTexImage();
6722 continue;
6728 // Set the active texture back to whatever the user had it as.
6729 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
6732 bool GLES2DecoderImpl::ClearUnclearedTextures() {
6733 // Only check if there are some uncleared textures.
6734 if (!texture_manager()->HaveUnsafeTextures()) {
6735 return true;
6738 // 1: Check all textures we are about to render with.
6739 if (state_.current_program.get()) {
6740 const Program::SamplerIndices& sampler_indices =
6741 state_.current_program->sampler_indices();
6742 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6743 const Program::UniformInfo* uniform_info =
6744 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6745 DCHECK(uniform_info);
6746 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6747 GLuint texture_unit_index = uniform_info->texture_units[jj];
6748 if (texture_unit_index < state_.texture_units.size()) {
6749 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6750 TextureRef* texture_ref =
6751 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6752 if (texture_ref && !texture_ref->texture()->SafeToRenderFrom()) {
6753 if (!texture_manager()->ClearRenderableLevels(this, texture_ref)) {
6754 return false;
6761 return true;
6764 bool GLES2DecoderImpl::IsDrawValid(
6765 const char* function_name, GLuint max_vertex_accessed, bool instanced,
6766 GLsizei primcount) {
6767 DCHECK(instanced || primcount == 1);
6769 // NOTE: We specifically do not check current_program->IsValid() because
6770 // it could never be invalid since glUseProgram would have failed. While
6771 // glLinkProgram could later mark the program as invalid the previous
6772 // valid program will still function if it is still the current program.
6773 if (!state_.current_program.get()) {
6774 // The program does not exist.
6775 // But GL says no ERROR.
6776 LOCAL_RENDER_WARNING("Drawing with no current shader program.");
6777 return false;
6780 if (CheckDrawingFeedbackLoops()) {
6781 LOCAL_SET_GL_ERROR(
6782 GL_INVALID_OPERATION, function_name,
6783 "Source and destination textures of the draw are the same.");
6784 return false;
6787 return state_.vertex_attrib_manager
6788 ->ValidateBindings(function_name,
6789 this,
6790 feature_info_.get(),
6791 state_.current_program.get(),
6792 max_vertex_accessed,
6793 instanced,
6794 primcount);
6797 bool GLES2DecoderImpl::SimulateAttrib0(
6798 const char* function_name, GLuint max_vertex_accessed, bool* simulated) {
6799 DCHECK(simulated);
6800 *simulated = false;
6802 if (feature_info_->gl_version_info().BehavesLikeGLES())
6803 return true;
6805 const VertexAttrib* attrib =
6806 state_.vertex_attrib_manager->GetVertexAttrib(0);
6807 // If it's enabled or it's not used then we don't need to do anything.
6808 bool attrib_0_used =
6809 state_.current_program->GetAttribInfoByLocation(0) != NULL;
6810 if (attrib->enabled() && attrib_0_used) {
6811 return true;
6814 // Make a buffer with a single repeated vec4 value enough to
6815 // simulate the constant value that is supposed to be here.
6816 // This is required to emulate GLES2 on GL.
6817 GLuint num_vertices = max_vertex_accessed + 1;
6818 uint32 size_needed = 0;
6820 if (num_vertices == 0 ||
6821 !SafeMultiplyUint32(num_vertices, sizeof(Vec4), &size_needed) ||
6822 size_needed > 0x7FFFFFFFU) {
6823 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6824 return false;
6827 LOCAL_PERFORMANCE_WARNING(
6828 "Attribute 0 is disabled. This has signficant performance penalty");
6830 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
6831 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
6833 bool new_buffer = static_cast<GLsizei>(size_needed) > attrib_0_size_;
6834 if (new_buffer) {
6835 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
6836 GLenum error = glGetError();
6837 if (error != GL_NO_ERROR) {
6838 LOCAL_SET_GL_ERROR(
6839 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6840 return false;
6844 const Vec4& value = state_.attrib_values[0];
6845 if (new_buffer ||
6846 (attrib_0_used &&
6847 (!attrib_0_buffer_matches_value_ ||
6848 (value.v[0] != attrib_0_value_.v[0] ||
6849 value.v[1] != attrib_0_value_.v[1] ||
6850 value.v[2] != attrib_0_value_.v[2] ||
6851 value.v[3] != attrib_0_value_.v[3])))) {
6852 std::vector<Vec4> temp(num_vertices, value);
6853 glBufferSubData(GL_ARRAY_BUFFER, 0, size_needed, &temp[0].v[0]);
6854 attrib_0_buffer_matches_value_ = true;
6855 attrib_0_value_ = value;
6856 attrib_0_size_ = size_needed;
6859 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
6861 if (attrib->divisor())
6862 glVertexAttribDivisorANGLE(0, 0);
6864 *simulated = true;
6865 return true;
6868 void GLES2DecoderImpl::RestoreStateForAttrib(
6869 GLuint attrib_index, bool restore_array_binding) {
6870 const VertexAttrib* attrib =
6871 state_.vertex_attrib_manager->GetVertexAttrib(attrib_index);
6872 if (restore_array_binding) {
6873 const void* ptr = reinterpret_cast<const void*>(attrib->offset());
6874 Buffer* buffer = attrib->buffer();
6875 glBindBuffer(GL_ARRAY_BUFFER, buffer ? buffer->service_id() : 0);
6876 glVertexAttribPointer(
6877 attrib_index, attrib->size(), attrib->type(), attrib->normalized(),
6878 attrib->gl_stride(), ptr);
6880 if (attrib->divisor())
6881 glVertexAttribDivisorANGLE(attrib_index, attrib->divisor());
6882 glBindBuffer(
6883 GL_ARRAY_BUFFER, state_.bound_array_buffer.get() ?
6884 state_.bound_array_buffer->service_id() : 0);
6886 // Never touch vertex attribute 0's state (in particular, never
6887 // disable it) when running on desktop GL because it will never be
6888 // re-enabled.
6889 if (attrib_index != 0 ||
6890 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
6891 if (attrib->enabled()) {
6892 glEnableVertexAttribArray(attrib_index);
6893 } else {
6894 glDisableVertexAttribArray(attrib_index);
6899 bool GLES2DecoderImpl::SimulateFixedAttribs(
6900 const char* function_name,
6901 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount) {
6902 DCHECK(simulated);
6903 *simulated = false;
6904 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
6905 return true;
6907 if (!state_.vertex_attrib_manager->HaveFixedAttribs()) {
6908 return true;
6911 LOCAL_PERFORMANCE_WARNING(
6912 "GL_FIXED attributes have a signficant performance penalty");
6914 // NOTE: we could be smart and try to check if a buffer is used
6915 // twice in 2 different attribs, find the overlapping parts and therefore
6916 // duplicate the minimum amount of data but this whole code path is not meant
6917 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
6918 // tests so we just add to the buffer attrib used.
6920 GLuint elements_needed = 0;
6921 const VertexAttribManager::VertexAttribList& enabled_attribs =
6922 state_.vertex_attrib_manager->GetEnabledVertexAttribs();
6923 for (VertexAttribManager::VertexAttribList::const_iterator it =
6924 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
6925 const VertexAttrib* attrib = *it;
6926 const Program::VertexAttrib* attrib_info =
6927 state_.current_program->GetAttribInfoByLocation(attrib->index());
6928 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
6929 max_vertex_accessed);
6930 GLuint num_vertices = max_accessed + 1;
6931 if (num_vertices == 0) {
6932 LOCAL_SET_GL_ERROR(
6933 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6934 return false;
6936 if (attrib_info &&
6937 attrib->CanAccess(max_accessed) &&
6938 attrib->type() == GL_FIXED) {
6939 uint32 elements_used = 0;
6940 if (!SafeMultiplyUint32(num_vertices, attrib->size(), &elements_used) ||
6941 !SafeAddUint32(elements_needed, elements_used, &elements_needed)) {
6942 LOCAL_SET_GL_ERROR(
6943 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
6944 return false;
6949 const uint32 kSizeOfFloat = sizeof(float); // NOLINT
6950 uint32 size_needed = 0;
6951 if (!SafeMultiplyUint32(elements_needed, kSizeOfFloat, &size_needed) ||
6952 size_needed > 0x7FFFFFFFU) {
6953 LOCAL_SET_GL_ERROR(
6954 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
6955 return false;
6958 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
6960 glBindBuffer(GL_ARRAY_BUFFER, fixed_attrib_buffer_id_);
6961 if (static_cast<GLsizei>(size_needed) > fixed_attrib_buffer_size_) {
6962 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
6963 GLenum error = glGetError();
6964 if (error != GL_NO_ERROR) {
6965 LOCAL_SET_GL_ERROR(
6966 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
6967 return false;
6971 // Copy the elements and convert to float
6972 GLintptr offset = 0;
6973 for (VertexAttribManager::VertexAttribList::const_iterator it =
6974 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
6975 const VertexAttrib* attrib = *it;
6976 const Program::VertexAttrib* attrib_info =
6977 state_.current_program->GetAttribInfoByLocation(attrib->index());
6978 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
6979 max_vertex_accessed);
6980 GLuint num_vertices = max_accessed + 1;
6981 if (num_vertices == 0) {
6982 LOCAL_SET_GL_ERROR(
6983 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6984 return false;
6986 if (attrib_info &&
6987 attrib->CanAccess(max_accessed) &&
6988 attrib->type() == GL_FIXED) {
6989 int num_elements = attrib->size() * num_vertices;
6990 const int src_size = num_elements * sizeof(int32);
6991 const int dst_size = num_elements * sizeof(float);
6992 scoped_ptr<float[]> data(new float[num_elements]);
6993 const int32* src = reinterpret_cast<const int32 *>(
6994 attrib->buffer()->GetRange(attrib->offset(), src_size));
6995 const int32* end = src + num_elements;
6996 float* dst = data.get();
6997 while (src != end) {
6998 *dst++ = static_cast<float>(*src++) / 65536.0f;
7000 glBufferSubData(GL_ARRAY_BUFFER, offset, dst_size, data.get());
7001 glVertexAttribPointer(
7002 attrib->index(), attrib->size(), GL_FLOAT, false, 0,
7003 reinterpret_cast<GLvoid*>(offset));
7004 offset += dst_size;
7007 *simulated = true;
7008 return true;
7011 void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
7012 // There's no need to call glVertexAttribPointer because we shadow all the
7013 // settings and passing GL_FIXED to it will not work.
7014 glBindBuffer(
7015 GL_ARRAY_BUFFER,
7016 state_.bound_array_buffer.get() ? state_.bound_array_buffer->service_id()
7017 : 0);
7020 error::Error GLES2DecoderImpl::DoDrawArrays(
7021 const char* function_name,
7022 bool instanced,
7023 GLenum mode,
7024 GLint first,
7025 GLsizei count,
7026 GLsizei primcount) {
7027 error::Error error = WillAccessBoundFramebufferForDraw();
7028 if (error != error::kNoError)
7029 return error;
7030 if (!validators_->draw_mode.IsValid(mode)) {
7031 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
7032 return error::kNoError;
7034 if (count < 0) {
7035 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
7036 return error::kNoError;
7038 if (primcount < 0) {
7039 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
7040 return error::kNoError;
7042 if (!CheckBoundFramebuffersValid(function_name)) {
7043 return error::kNoError;
7045 // We have to check this here because the prototype for glDrawArrays
7046 // is GLint not GLsizei.
7047 if (first < 0) {
7048 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "first < 0");
7049 return error::kNoError;
7052 if (count == 0 || primcount == 0) {
7053 LOCAL_RENDER_WARNING("Render count or primcount is 0.");
7054 return error::kNoError;
7057 GLuint max_vertex_accessed = first + count - 1;
7058 if (IsDrawValid(function_name, max_vertex_accessed, instanced, primcount)) {
7059 if (!ClearUnclearedTextures()) {
7060 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
7061 return error::kNoError;
7063 bool simulated_attrib_0 = false;
7064 if (!SimulateAttrib0(
7065 function_name, max_vertex_accessed, &simulated_attrib_0)) {
7066 return error::kNoError;
7068 bool simulated_fixed_attribs = false;
7069 if (SimulateFixedAttribs(
7070 function_name, max_vertex_accessed, &simulated_fixed_attribs,
7071 primcount)) {
7072 bool textures_set = !PrepareTexturesForRender();
7073 ApplyDirtyState();
7074 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
7075 if (!instanced) {
7076 glDrawArrays(mode, first, count);
7077 } else {
7078 glDrawArraysInstancedANGLE(mode, first, count, primcount);
7080 if (textures_set) {
7081 RestoreStateForTextures();
7083 if (simulated_fixed_attribs) {
7084 RestoreStateForSimulatedFixedAttribs();
7087 if (simulated_attrib_0) {
7088 // We don't have to restore attrib 0 generic data at the end of this
7089 // function even if it is simulated. This is because we will simulate
7090 // it in each draw call, and attrib 0 generic data queries use cached
7091 // values instead of passing down to the underlying driver.
7092 RestoreStateForAttrib(0, false);
7095 return error::kNoError;
7098 error::Error GLES2DecoderImpl::HandleDrawArrays(uint32 immediate_data_size,
7099 const void* cmd_data) {
7100 // TODO(zmo): crbug.com/481184
7101 // On Desktop GL with versions lower than 4.3, we need to emulate
7102 // GL_PRIMITIVE_RESTART_FIXED_INDEX using glPrimitiveRestartIndex().
7103 const cmds::DrawArrays& c = *static_cast<const cmds::DrawArrays*>(cmd_data);
7104 return DoDrawArrays("glDrawArrays",
7105 false,
7106 static_cast<GLenum>(c.mode),
7107 static_cast<GLint>(c.first),
7108 static_cast<GLsizei>(c.count),
7112 error::Error GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
7113 uint32 immediate_data_size,
7114 const void* cmd_data) {
7115 const gles2::cmds::DrawArraysInstancedANGLE& c =
7116 *static_cast<const gles2::cmds::DrawArraysInstancedANGLE*>(cmd_data);
7117 if (!features().angle_instanced_arrays) {
7118 LOCAL_SET_GL_ERROR(
7119 GL_INVALID_OPERATION,
7120 "glDrawArraysInstancedANGLE", "function not available");
7121 return error::kNoError;
7123 return DoDrawArrays("glDrawArraysIntancedANGLE",
7124 true,
7125 static_cast<GLenum>(c.mode),
7126 static_cast<GLint>(c.first),
7127 static_cast<GLsizei>(c.count),
7128 static_cast<GLsizei>(c.primcount));
7131 error::Error GLES2DecoderImpl::DoDrawElements(
7132 const char* function_name,
7133 bool instanced,
7134 GLenum mode,
7135 GLsizei count,
7136 GLenum type,
7137 int32 offset,
7138 GLsizei primcount) {
7139 error::Error error = WillAccessBoundFramebufferForDraw();
7140 if (error != error::kNoError)
7141 return error;
7142 if (!state_.vertex_attrib_manager->element_array_buffer()) {
7143 LOCAL_SET_GL_ERROR(
7144 GL_INVALID_OPERATION, function_name, "No element array buffer bound");
7145 return error::kNoError;
7148 if (count < 0) {
7149 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
7150 return error::kNoError;
7152 if (offset < 0) {
7153 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "offset < 0");
7154 return error::kNoError;
7156 if (!validators_->draw_mode.IsValid(mode)) {
7157 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
7158 return error::kNoError;
7160 if (!validators_->index_type.IsValid(type)) {
7161 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, type, "type");
7162 return error::kNoError;
7164 if (primcount < 0) {
7165 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
7166 return error::kNoError;
7169 if (!CheckBoundFramebuffersValid(function_name)) {
7170 return error::kNoError;
7173 if (count == 0 || primcount == 0) {
7174 return error::kNoError;
7177 GLuint max_vertex_accessed;
7178 Buffer* element_array_buffer =
7179 state_.vertex_attrib_manager->element_array_buffer();
7181 if (!element_array_buffer->GetMaxValueForRange(
7182 offset, count, type, &max_vertex_accessed)) {
7183 LOCAL_SET_GL_ERROR(
7184 GL_INVALID_OPERATION, function_name, "range out of bounds for buffer");
7185 return error::kNoError;
7188 if (IsDrawValid(function_name, max_vertex_accessed, instanced, primcount)) {
7189 if (!ClearUnclearedTextures()) {
7190 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
7191 return error::kNoError;
7193 bool simulated_attrib_0 = false;
7194 if (!SimulateAttrib0(
7195 function_name, max_vertex_accessed, &simulated_attrib_0)) {
7196 return error::kNoError;
7198 bool simulated_fixed_attribs = false;
7199 if (SimulateFixedAttribs(
7200 function_name, max_vertex_accessed, &simulated_fixed_attribs,
7201 primcount)) {
7202 bool textures_set = !PrepareTexturesForRender();
7203 ApplyDirtyState();
7204 // TODO(gman): Refactor to hide these details in BufferManager or
7205 // VertexAttribManager.
7206 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
7207 bool used_client_side_array = false;
7208 if (element_array_buffer->IsClientSideArray()) {
7209 used_client_side_array = true;
7210 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
7211 indices = element_array_buffer->GetRange(offset, 0);
7214 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
7215 if (!instanced) {
7216 glDrawElements(mode, count, type, indices);
7217 } else {
7218 glDrawElementsInstancedANGLE(mode, count, type, indices, primcount);
7221 if (used_client_side_array) {
7222 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
7223 element_array_buffer->service_id());
7226 if (textures_set) {
7227 RestoreStateForTextures();
7229 if (simulated_fixed_attribs) {
7230 RestoreStateForSimulatedFixedAttribs();
7233 if (simulated_attrib_0) {
7234 // We don't have to restore attrib 0 generic data at the end of this
7235 // function even if it is simulated. This is because we will simulate
7236 // it in each draw call, and attrib 0 generic data queries use cached
7237 // values instead of passing down to the underlying driver.
7238 RestoreStateForAttrib(0, false);
7241 return error::kNoError;
7244 error::Error GLES2DecoderImpl::HandleDrawElements(uint32 immediate_data_size,
7245 const void* cmd_data) {
7246 // TODO(zmo): crbug.com/481184
7247 // On Desktop GL with versions lower than 4.3, we need to emulate
7248 // GL_PRIMITIVE_RESTART_FIXED_INDEX using glPrimitiveRestartIndex().
7249 const gles2::cmds::DrawElements& c =
7250 *static_cast<const gles2::cmds::DrawElements*>(cmd_data);
7251 return DoDrawElements("glDrawElements",
7252 false,
7253 static_cast<GLenum>(c.mode),
7254 static_cast<GLsizei>(c.count),
7255 static_cast<GLenum>(c.type),
7256 static_cast<int32>(c.index_offset),
7260 error::Error GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
7261 uint32 immediate_data_size,
7262 const void* cmd_data) {
7263 const gles2::cmds::DrawElementsInstancedANGLE& c =
7264 *static_cast<const gles2::cmds::DrawElementsInstancedANGLE*>(cmd_data);
7265 if (!features().angle_instanced_arrays) {
7266 LOCAL_SET_GL_ERROR(
7267 GL_INVALID_OPERATION,
7268 "glDrawElementsInstancedANGLE", "function not available");
7269 return error::kNoError;
7271 return DoDrawElements("glDrawElementsInstancedANGLE",
7272 true,
7273 static_cast<GLenum>(c.mode),
7274 static_cast<GLsizei>(c.count),
7275 static_cast<GLenum>(c.type),
7276 static_cast<int32>(c.index_offset),
7277 static_cast<GLsizei>(c.primcount));
7280 GLuint GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
7281 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
7282 GLuint max_vertex_accessed = 0;
7283 Buffer* buffer = GetBuffer(buffer_id);
7284 if (!buffer) {
7285 // TODO(gman): Should this be a GL error or a command buffer error?
7286 LOCAL_SET_GL_ERROR(
7287 GL_INVALID_VALUE, "GetMaxValueInBufferCHROMIUM", "unknown buffer");
7288 } else {
7289 if (!buffer->GetMaxValueForRange(
7290 offset, count, type, &max_vertex_accessed)) {
7291 // TODO(gman): Should this be a GL error or a command buffer error?
7292 LOCAL_SET_GL_ERROR(
7293 GL_INVALID_OPERATION,
7294 "GetMaxValueInBufferCHROMIUM", "range out of bounds for buffer");
7297 return max_vertex_accessed;
7300 void GLES2DecoderImpl::DoShaderSource(
7301 GLuint client_id, GLsizei count, const char** data, const GLint* length) {
7302 std::string str;
7303 for (GLsizei ii = 0; ii < count; ++ii) {
7304 if (length && length[ii] > 0)
7305 str.append(data[ii], length[ii]);
7306 else
7307 str.append(data[ii]);
7309 Shader* shader = GetShaderInfoNotProgram(client_id, "glShaderSource");
7310 if (!shader) {
7311 return;
7313 // Note: We don't actually call glShaderSource here. We wait until
7314 // we actually compile the shader.
7315 shader->set_source(str);
7318 void GLES2DecoderImpl::DoTransformFeedbackVaryings(
7319 GLuint client_program_id, GLsizei count, const char* const* varyings,
7320 GLenum buffer_mode) {
7321 Program* program = GetProgramInfoNotShader(
7322 client_program_id, "glTransformFeedbackVaryings");
7323 if (!program) {
7324 return;
7326 program->TransformFeedbackVaryings(count, varyings, buffer_mode);
7327 glTransformFeedbackVaryings(
7328 program->service_id(), count, varyings, buffer_mode);
7331 void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
7332 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
7333 Shader* shader = GetShaderInfoNotProgram(client_id, "glCompileShader");
7334 if (!shader) {
7335 return;
7338 scoped_refptr<ShaderTranslatorInterface> translator;
7339 if (use_shader_translator_) {
7340 translator = shader->shader_type() == GL_VERTEX_SHADER ?
7341 vertex_translator_ : fragment_translator_;
7344 const Shader::TranslatedShaderSourceType source_type =
7345 feature_info_->feature_flags().angle_translated_shader_source ?
7346 Shader::kANGLE : Shader::kGL;
7347 shader->RequestCompile(translator, source_type);
7350 void GLES2DecoderImpl::DoGetShaderiv(
7351 GLuint shader_id, GLenum pname, GLint* params) {
7352 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderiv");
7353 if (!shader) {
7354 return;
7357 // Compile now for statuses that require it.
7358 switch (pname) {
7359 case GL_COMPILE_STATUS:
7360 case GL_INFO_LOG_LENGTH:
7361 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
7362 shader->DoCompile();
7363 break;
7365 default:
7366 break;
7369 switch (pname) {
7370 case GL_SHADER_SOURCE_LENGTH:
7371 *params = shader->source().size();
7372 if (*params)
7373 ++(*params);
7374 return;
7375 case GL_COMPILE_STATUS:
7376 *params = compile_shader_always_succeeds_ ? true : shader->valid();
7377 return;
7378 case GL_INFO_LOG_LENGTH:
7379 *params = shader->log_info().size();
7380 if (*params)
7381 ++(*params);
7382 return;
7383 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
7384 *params = shader->translated_source().size();
7385 if (*params)
7386 ++(*params);
7387 return;
7388 default:
7389 break;
7391 glGetShaderiv(shader->service_id(), pname, params);
7394 error::Error GLES2DecoderImpl::HandleGetShaderSource(uint32 immediate_data_size,
7395 const void* cmd_data) {
7396 const gles2::cmds::GetShaderSource& c =
7397 *static_cast<const gles2::cmds::GetShaderSource*>(cmd_data);
7398 GLuint shader_id = c.shader;
7399 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
7400 Bucket* bucket = CreateBucket(bucket_id);
7401 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderSource");
7402 if (!shader || shader->source().empty()) {
7403 bucket->SetSize(0);
7404 return error::kNoError;
7406 bucket->SetFromString(shader->source().c_str());
7407 return error::kNoError;
7410 error::Error GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
7411 uint32 immediate_data_size,
7412 const void* cmd_data) {
7413 const gles2::cmds::GetTranslatedShaderSourceANGLE& c =
7414 *static_cast<const gles2::cmds::GetTranslatedShaderSourceANGLE*>(
7415 cmd_data);
7416 GLuint shader_id = c.shader;
7417 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
7418 Bucket* bucket = CreateBucket(bucket_id);
7419 Shader* shader = GetShaderInfoNotProgram(
7420 shader_id, "glGetTranslatedShaderSourceANGLE");
7421 if (!shader) {
7422 bucket->SetSize(0);
7423 return error::kNoError;
7426 // Make sure translator has been utilized in compile.
7427 shader->DoCompile();
7429 bucket->SetFromString(shader->translated_source().c_str());
7430 return error::kNoError;
7433 error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
7434 uint32 immediate_data_size,
7435 const void* cmd_data) {
7436 const gles2::cmds::GetProgramInfoLog& c =
7437 *static_cast<const gles2::cmds::GetProgramInfoLog*>(cmd_data);
7438 GLuint program_id = c.program;
7439 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
7440 Bucket* bucket = CreateBucket(bucket_id);
7441 Program* program = GetProgramInfoNotShader(
7442 program_id, "glGetProgramInfoLog");
7443 if (!program || !program->log_info()) {
7444 bucket->SetFromString("");
7445 return error::kNoError;
7447 bucket->SetFromString(program->log_info()->c_str());
7448 return error::kNoError;
7451 error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
7452 uint32 immediate_data_size,
7453 const void* cmd_data) {
7454 const gles2::cmds::GetShaderInfoLog& c =
7455 *static_cast<const gles2::cmds::GetShaderInfoLog*>(cmd_data);
7456 GLuint shader_id = c.shader;
7457 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
7458 Bucket* bucket = CreateBucket(bucket_id);
7459 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderInfoLog");
7460 if (!shader) {
7461 bucket->SetFromString("");
7462 return error::kNoError;
7465 // Shader must be compiled in order to get the info log.
7466 shader->DoCompile();
7468 bucket->SetFromString(shader->log_info().c_str());
7469 return error::kNoError;
7472 bool GLES2DecoderImpl::DoIsEnabled(GLenum cap) {
7473 return state_.GetEnabled(cap);
7476 bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
7477 const Buffer* buffer = GetBuffer(client_id);
7478 return buffer && buffer->IsValid() && !buffer->IsDeleted();
7481 bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
7482 const Framebuffer* framebuffer =
7483 GetFramebuffer(client_id);
7484 return framebuffer && framebuffer->IsValid() && !framebuffer->IsDeleted();
7487 bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
7488 // IsProgram is true for programs as soon as they are created, until they are
7489 // deleted and no longer in use.
7490 const Program* program = GetProgram(client_id);
7491 return program != NULL && !program->IsDeleted();
7494 bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
7495 const Renderbuffer* renderbuffer =
7496 GetRenderbuffer(client_id);
7497 return renderbuffer && renderbuffer->IsValid() && !renderbuffer->IsDeleted();
7500 bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
7501 // IsShader is true for shaders as soon as they are created, until they
7502 // are deleted and not attached to any programs.
7503 const Shader* shader = GetShader(client_id);
7504 return shader != NULL && !shader->IsDeleted();
7507 bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
7508 const TextureRef* texture_ref = GetTexture(client_id);
7509 return texture_ref && texture_ref->texture()->IsValid();
7512 void GLES2DecoderImpl::DoAttachShader(
7513 GLuint program_client_id, GLint shader_client_id) {
7514 Program* program = GetProgramInfoNotShader(
7515 program_client_id, "glAttachShader");
7516 if (!program) {
7517 return;
7519 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glAttachShader");
7520 if (!shader) {
7521 return;
7523 if (!program->AttachShader(shader_manager(), shader)) {
7524 LOCAL_SET_GL_ERROR(
7525 GL_INVALID_OPERATION,
7526 "glAttachShader",
7527 "can not attach more than one shader of the same type.");
7528 return;
7530 glAttachShader(program->service_id(), shader->service_id());
7533 void GLES2DecoderImpl::DoDetachShader(
7534 GLuint program_client_id, GLint shader_client_id) {
7535 Program* program = GetProgramInfoNotShader(
7536 program_client_id, "glDetachShader");
7537 if (!program) {
7538 return;
7540 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glDetachShader");
7541 if (!shader) {
7542 return;
7544 if (!program->DetachShader(shader_manager(), shader)) {
7545 LOCAL_SET_GL_ERROR(
7546 GL_INVALID_OPERATION,
7547 "glDetachShader", "shader not attached to program");
7548 return;
7550 glDetachShader(program->service_id(), shader->service_id());
7553 void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
7554 Program* program = GetProgramInfoNotShader(
7555 program_client_id, "glValidateProgram");
7556 if (!program) {
7557 return;
7559 program->Validate();
7562 void GLES2DecoderImpl::GetVertexAttribHelper(
7563 const VertexAttrib* attrib, GLenum pname, GLint* params) {
7564 switch (pname) {
7565 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
7566 Buffer* buffer = attrib->buffer();
7567 if (buffer && !buffer->IsDeleted()) {
7568 GLuint client_id;
7569 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
7570 *params = client_id;
7572 break;
7574 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
7575 *params = attrib->enabled();
7576 break;
7577 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
7578 *params = attrib->size();
7579 break;
7580 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
7581 *params = attrib->gl_stride();
7582 break;
7583 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
7584 *params = attrib->type();
7585 break;
7586 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
7587 *params = attrib->normalized();
7588 break;
7589 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE:
7590 *params = attrib->divisor();
7591 break;
7592 default:
7593 NOTREACHED();
7594 break;
7598 void GLES2DecoderImpl::DoGetTexParameterfv(
7599 GLenum target, GLenum pname, GLfloat* params) {
7600 InitTextureMaxAnisotropyIfNeeded(target, pname);
7601 glGetTexParameterfv(target, pname, params);
7604 void GLES2DecoderImpl::DoGetTexParameteriv(
7605 GLenum target, GLenum pname, GLint* params) {
7606 InitTextureMaxAnisotropyIfNeeded(target, pname);
7607 glGetTexParameteriv(target, pname, params);
7610 void GLES2DecoderImpl::InitTextureMaxAnisotropyIfNeeded(
7611 GLenum target, GLenum pname) {
7612 if (!workarounds().init_texture_max_anisotropy)
7613 return;
7614 if (pname != GL_TEXTURE_MAX_ANISOTROPY_EXT ||
7615 !validators_->texture_parameter.IsValid(pname)) {
7616 return;
7619 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
7620 &state_, target);
7621 if (!texture_ref) {
7622 LOCAL_SET_GL_ERROR(
7623 GL_INVALID_OPERATION,
7624 "glGetTexParamter{fi}v", "unknown texture for target");
7625 return;
7627 Texture* texture = texture_ref->texture();
7628 texture->InitTextureMaxAnisotropyIfNeeded(target);
7631 void GLES2DecoderImpl::DoGetVertexAttribfv(
7632 GLuint index, GLenum pname, GLfloat* params) {
7633 VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(index);
7634 if (!attrib) {
7635 LOCAL_SET_GL_ERROR(
7636 GL_INVALID_VALUE, "glGetVertexAttribfv", "index out of range");
7637 return;
7639 switch (pname) {
7640 case GL_CURRENT_VERTEX_ATTRIB: {
7641 const Vec4& value = state_.attrib_values[index];
7642 params[0] = value.v[0];
7643 params[1] = value.v[1];
7644 params[2] = value.v[2];
7645 params[3] = value.v[3];
7646 break;
7648 default: {
7649 GLint value = 0;
7650 GetVertexAttribHelper(attrib, pname, &value);
7651 *params = static_cast<GLfloat>(value);
7652 break;
7657 void GLES2DecoderImpl::DoGetVertexAttribiv(
7658 GLuint index, GLenum pname, GLint* params) {
7659 VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(index);
7660 if (!attrib) {
7661 LOCAL_SET_GL_ERROR(
7662 GL_INVALID_VALUE, "glGetVertexAttribiv", "index out of range");
7663 return;
7665 switch (pname) {
7666 case GL_CURRENT_VERTEX_ATTRIB: {
7667 const Vec4& value = state_.attrib_values[index];
7668 params[0] = static_cast<GLint>(value.v[0]);
7669 params[1] = static_cast<GLint>(value.v[1]);
7670 params[2] = static_cast<GLint>(value.v[2]);
7671 params[3] = static_cast<GLint>(value.v[3]);
7672 break;
7674 default:
7675 GetVertexAttribHelper(attrib, pname, params);
7676 break;
7680 bool GLES2DecoderImpl::SetVertexAttribValue(
7681 const char* function_name, GLuint index, const GLfloat* value) {
7682 if (index >= state_.attrib_values.size()) {
7683 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "index out of range");
7684 return false;
7686 Vec4& v = state_.attrib_values[index];
7687 v.v[0] = value[0];
7688 v.v[1] = value[1];
7689 v.v[2] = value[2];
7690 v.v[3] = value[3];
7691 return true;
7694 void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
7695 GLfloat v[4] = { v0, 0.0f, 0.0f, 1.0f, };
7696 if (SetVertexAttribValue("glVertexAttrib1f", index, v)) {
7697 glVertexAttrib1f(index, v0);
7701 void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
7702 GLfloat v[4] = { v0, v1, 0.0f, 1.0f, };
7703 if (SetVertexAttribValue("glVertexAttrib2f", index, v)) {
7704 glVertexAttrib2f(index, v0, v1);
7708 void GLES2DecoderImpl::DoVertexAttrib3f(
7709 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
7710 GLfloat v[4] = { v0, v1, v2, 1.0f, };
7711 if (SetVertexAttribValue("glVertexAttrib3f", index, v)) {
7712 glVertexAttrib3f(index, v0, v1, v2);
7716 void GLES2DecoderImpl::DoVertexAttrib4f(
7717 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
7718 GLfloat v[4] = { v0, v1, v2, v3, };
7719 if (SetVertexAttribValue("glVertexAttrib4f", index, v)) {
7720 glVertexAttrib4f(index, v0, v1, v2, v3);
7724 void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
7725 GLfloat t[4] = { v[0], 0.0f, 0.0f, 1.0f, };
7726 if (SetVertexAttribValue("glVertexAttrib1fv", index, t)) {
7727 glVertexAttrib1fv(index, v);
7731 void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
7732 GLfloat t[4] = { v[0], v[1], 0.0f, 1.0f, };
7733 if (SetVertexAttribValue("glVertexAttrib2fv", index, t)) {
7734 glVertexAttrib2fv(index, v);
7738 void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
7739 GLfloat t[4] = { v[0], v[1], v[2], 1.0f, };
7740 if (SetVertexAttribValue("glVertexAttrib3fv", index, t)) {
7741 glVertexAttrib3fv(index, v);
7745 void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
7746 if (SetVertexAttribValue("glVertexAttrib4fv", index, v)) {
7747 glVertexAttrib4fv(index, v);
7751 error::Error GLES2DecoderImpl::HandleVertexAttribIPointer(
7752 uint32 immediate_data_size,
7753 const void* cmd_data) {
7754 if (!unsafe_es3_apis_enabled())
7755 return error::kUnknownCommand;
7756 const gles2::cmds::VertexAttribIPointer& c =
7757 *static_cast<const gles2::cmds::VertexAttribIPointer*>(cmd_data);
7759 if (!state_.bound_array_buffer.get() ||
7760 state_.bound_array_buffer->IsDeleted()) {
7761 if (state_.vertex_attrib_manager.get() ==
7762 state_.default_vertex_attrib_manager.get()) {
7763 LOCAL_SET_GL_ERROR(
7764 GL_INVALID_VALUE, "glVertexAttribIPointer", "no array buffer bound");
7765 return error::kNoError;
7766 } else if (c.offset != 0) {
7767 LOCAL_SET_GL_ERROR(
7768 GL_INVALID_VALUE,
7769 "glVertexAttribIPointer", "client side arrays are not allowed");
7770 return error::kNoError;
7774 GLuint indx = c.indx;
7775 GLint size = c.size;
7776 GLenum type = c.type;
7777 GLsizei stride = c.stride;
7778 GLsizei offset = c.offset;
7779 const void* ptr = reinterpret_cast<const void*>(offset);
7780 if (!validators_->vertex_attrib_i_type.IsValid(type)) {
7781 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribIPointer", type, "type");
7782 return error::kNoError;
7784 if (!validators_->vertex_attrib_size.IsValid(size)) {
7785 LOCAL_SET_GL_ERROR(
7786 GL_INVALID_VALUE, "glVertexAttribIPointer", "size GL_INVALID_VALUE");
7787 return error::kNoError;
7789 if (indx >= group_->max_vertex_attribs()) {
7790 LOCAL_SET_GL_ERROR(
7791 GL_INVALID_VALUE, "glVertexAttribIPointer", "index out of range");
7792 return error::kNoError;
7794 if (stride < 0) {
7795 LOCAL_SET_GL_ERROR(
7796 GL_INVALID_VALUE, "glVertexAttribIPointer", "stride < 0");
7797 return error::kNoError;
7799 if (stride > 255) {
7800 LOCAL_SET_GL_ERROR(
7801 GL_INVALID_VALUE, "glVertexAttribIPointer", "stride > 255");
7802 return error::kNoError;
7804 if (offset < 0) {
7805 LOCAL_SET_GL_ERROR(
7806 GL_INVALID_VALUE, "glVertexAttribIPointer", "offset < 0");
7807 return error::kNoError;
7809 GLsizei component_size =
7810 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
7811 // component_size must be a power of two to use & as optimized modulo.
7812 DCHECK(GLES2Util::IsPOT(component_size));
7813 if (offset & (component_size - 1)) {
7814 LOCAL_SET_GL_ERROR(
7815 GL_INVALID_OPERATION,
7816 "glVertexAttribIPointer", "offset not valid for type");
7817 return error::kNoError;
7819 if (stride & (component_size - 1)) {
7820 LOCAL_SET_GL_ERROR(
7821 GL_INVALID_OPERATION,
7822 "glVertexAttribIPointer", "stride not valid for type");
7823 return error::kNoError;
7825 state_.vertex_attrib_manager
7826 ->SetAttribInfo(indx,
7827 state_.bound_array_buffer.get(),
7828 size,
7829 type,
7830 GL_FALSE,
7831 stride,
7832 stride != 0 ? stride : component_size * size,
7833 offset);
7834 glVertexAttribIPointer(indx, size, type, stride, ptr);
7835 return error::kNoError;
7838 error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
7839 uint32 immediate_data_size,
7840 const void* cmd_data) {
7841 const gles2::cmds::VertexAttribPointer& c =
7842 *static_cast<const gles2::cmds::VertexAttribPointer*>(cmd_data);
7844 if (!state_.bound_array_buffer.get() ||
7845 state_.bound_array_buffer->IsDeleted()) {
7846 if (state_.vertex_attrib_manager.get() ==
7847 state_.default_vertex_attrib_manager.get()) {
7848 LOCAL_SET_GL_ERROR(
7849 GL_INVALID_VALUE, "glVertexAttribPointer", "no array buffer bound");
7850 return error::kNoError;
7851 } else if (c.offset != 0) {
7852 LOCAL_SET_GL_ERROR(
7853 GL_INVALID_VALUE,
7854 "glVertexAttribPointer", "client side arrays are not allowed");
7855 return error::kNoError;
7859 GLuint indx = c.indx;
7860 GLint size = c.size;
7861 GLenum type = c.type;
7862 GLboolean normalized = static_cast<GLboolean>(c.normalized);
7863 GLsizei stride = c.stride;
7864 GLsizei offset = c.offset;
7865 const void* ptr = reinterpret_cast<const void*>(offset);
7866 if (!validators_->vertex_attrib_type.IsValid(type)) {
7867 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribPointer", type, "type");
7868 return error::kNoError;
7870 if (!validators_->vertex_attrib_size.IsValid(size)) {
7871 LOCAL_SET_GL_ERROR(
7872 GL_INVALID_VALUE, "glVertexAttribPointer", "size GL_INVALID_VALUE");
7873 return error::kNoError;
7875 if (indx >= group_->max_vertex_attribs()) {
7876 LOCAL_SET_GL_ERROR(
7877 GL_INVALID_VALUE, "glVertexAttribPointer", "index out of range");
7878 return error::kNoError;
7880 if (stride < 0) {
7881 LOCAL_SET_GL_ERROR(
7882 GL_INVALID_VALUE, "glVertexAttribPointer", "stride < 0");
7883 return error::kNoError;
7885 if (stride > 255) {
7886 LOCAL_SET_GL_ERROR(
7887 GL_INVALID_VALUE, "glVertexAttribPointer", "stride > 255");
7888 return error::kNoError;
7890 if (offset < 0) {
7891 LOCAL_SET_GL_ERROR(
7892 GL_INVALID_VALUE, "glVertexAttribPointer", "offset < 0");
7893 return error::kNoError;
7895 GLsizei component_size =
7896 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
7897 // component_size must be a power of two to use & as optimized modulo.
7898 DCHECK(GLES2Util::IsPOT(component_size));
7899 if (offset & (component_size - 1)) {
7900 LOCAL_SET_GL_ERROR(
7901 GL_INVALID_OPERATION,
7902 "glVertexAttribPointer", "offset not valid for type");
7903 return error::kNoError;
7905 if (stride & (component_size - 1)) {
7906 LOCAL_SET_GL_ERROR(
7907 GL_INVALID_OPERATION,
7908 "glVertexAttribPointer", "stride not valid for type");
7909 return error::kNoError;
7911 state_.vertex_attrib_manager
7912 ->SetAttribInfo(indx,
7913 state_.bound_array_buffer.get(),
7914 size,
7915 type,
7916 normalized,
7917 stride,
7918 stride != 0 ? stride : component_size * size,
7919 offset);
7920 if (type != GL_FIXED) {
7921 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
7923 return error::kNoError;
7926 void GLES2DecoderImpl::DoViewport(GLint x, GLint y, GLsizei width,
7927 GLsizei height) {
7928 state_.viewport_x = x;
7929 state_.viewport_y = y;
7930 state_.viewport_width = std::min(width, viewport_max_width_);
7931 state_.viewport_height = std::min(height, viewport_max_height_);
7932 glViewport(x, y, width, height);
7935 error::Error GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
7936 uint32 immediate_data_size,
7937 const void* cmd_data) {
7938 const gles2::cmds::VertexAttribDivisorANGLE& c =
7939 *static_cast<const gles2::cmds::VertexAttribDivisorANGLE*>(cmd_data);
7940 if (!features().angle_instanced_arrays) {
7941 LOCAL_SET_GL_ERROR(
7942 GL_INVALID_OPERATION,
7943 "glVertexAttribDivisorANGLE", "function not available");
7944 return error::kNoError;
7946 GLuint index = c.index;
7947 GLuint divisor = c.divisor;
7948 if (index >= group_->max_vertex_attribs()) {
7949 LOCAL_SET_GL_ERROR(
7950 GL_INVALID_VALUE,
7951 "glVertexAttribDivisorANGLE", "index out of range");
7952 return error::kNoError;
7955 state_.vertex_attrib_manager->SetDivisor(
7956 index,
7957 divisor);
7958 glVertexAttribDivisorANGLE(index, divisor);
7959 return error::kNoError;
7962 template <typename pixel_data_type>
7963 static void WriteAlphaData(
7964 void* pixels, uint32 row_count, uint32 channel_count,
7965 uint32 alpha_channel_index, uint32 unpadded_row_size,
7966 uint32 padded_row_size, pixel_data_type alpha_value) {
7967 DCHECK_GT(channel_count, 0U);
7968 DCHECK_EQ(unpadded_row_size % sizeof(pixel_data_type), 0U);
7969 uint32 unpadded_row_size_in_elements =
7970 unpadded_row_size / sizeof(pixel_data_type);
7971 DCHECK_EQ(padded_row_size % sizeof(pixel_data_type), 0U);
7972 uint32 padded_row_size_in_elements =
7973 padded_row_size / sizeof(pixel_data_type);
7974 pixel_data_type* dst =
7975 static_cast<pixel_data_type*>(pixels) + alpha_channel_index;
7976 for (uint32 yy = 0; yy < row_count; ++yy) {
7977 pixel_data_type* end = dst + unpadded_row_size_in_elements;
7978 for (pixel_data_type* d = dst; d < end; d += channel_count) {
7979 *d = alpha_value;
7981 dst += padded_row_size_in_elements;
7985 void GLES2DecoderImpl::FinishReadPixels(
7986 const cmds::ReadPixels& c,
7987 GLuint buffer) {
7988 TRACE_EVENT0("gpu", "GLES2DecoderImpl::FinishReadPixels");
7989 GLsizei width = c.width;
7990 GLsizei height = c.height;
7991 GLenum format = c.format;
7992 GLenum type = c.type;
7993 typedef cmds::ReadPixels::Result Result;
7994 uint32 pixels_size;
7995 Result* result = NULL;
7996 if (c.result_shm_id != 0) {
7997 result = GetSharedMemoryAs<Result*>(
7998 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7999 if (!result) {
8000 if (buffer != 0) {
8001 glDeleteBuffersARB(1, &buffer);
8003 return;
8006 GLES2Util::ComputeImageDataSizes(
8007 width, height, 1, format, type, state_.pack_alignment, &pixels_size,
8008 NULL, NULL);
8009 void* pixels = GetSharedMemoryAs<void*>(
8010 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
8011 if (!pixels) {
8012 if (buffer != 0) {
8013 glDeleteBuffersARB(1, &buffer);
8015 return;
8018 if (buffer != 0) {
8019 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
8020 void* data;
8021 if (features().map_buffer_range) {
8022 data = glMapBufferRange(
8023 GL_PIXEL_PACK_BUFFER_ARB, 0, pixels_size, GL_MAP_READ_BIT);
8024 } else {
8025 data = glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
8027 if (!data) {
8028 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glMapBuffer",
8029 "Unable to map memory for readback.");
8030 return;
8032 memcpy(pixels, data, pixels_size);
8033 // GL_PIXEL_PACK_BUFFER_ARB is currently unused, so we don't
8034 // have to restore the state.
8035 glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB);
8036 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
8037 glDeleteBuffersARB(1, &buffer);
8040 if (result != NULL) {
8041 *result = true;
8044 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
8045 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
8046 if ((channels_exist & 0x0008) == 0 &&
8047 workarounds().clear_alpha_in_readpixels) {
8048 // Set the alpha to 255 because some drivers are buggy in this regard.
8049 uint32 temp_size;
8051 uint32 unpadded_row_size;
8052 uint32 padded_row_size;
8053 if (!GLES2Util::ComputeImageDataSizes(
8054 width, 2, 1, format, type, state_.pack_alignment, &temp_size,
8055 &unpadded_row_size, &padded_row_size)) {
8056 return;
8059 uint32 channel_count = 0;
8060 uint32 alpha_channel = 0;
8061 switch (format) {
8062 case GL_RGBA:
8063 case GL_BGRA_EXT:
8064 channel_count = 4;
8065 alpha_channel = 3;
8066 break;
8067 case GL_ALPHA:
8068 channel_count = 1;
8069 alpha_channel = 0;
8070 break;
8073 if (channel_count > 0) {
8074 switch (type) {
8075 case GL_UNSIGNED_BYTE:
8076 WriteAlphaData<uint8>(
8077 pixels, height, channel_count, alpha_channel, unpadded_row_size,
8078 padded_row_size, 0xFF);
8079 break;
8080 case GL_FLOAT:
8081 WriteAlphaData<float>(
8082 pixels, height, channel_count, alpha_channel, unpadded_row_size,
8083 padded_row_size, 1.0f);
8084 break;
8085 case GL_HALF_FLOAT:
8086 WriteAlphaData<uint16>(
8087 pixels, height, channel_count, alpha_channel, unpadded_row_size,
8088 padded_row_size, 0x3C00);
8089 break;
8095 error::Error GLES2DecoderImpl::HandleReadPixels(uint32 immediate_data_size,
8096 const void* cmd_data) {
8097 const gles2::cmds::ReadPixels& c =
8098 *static_cast<const gles2::cmds::ReadPixels*>(cmd_data);
8099 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleReadPixels");
8100 error::Error fbo_error = WillAccessBoundFramebufferForRead();
8101 if (fbo_error != error::kNoError)
8102 return fbo_error;
8103 GLint x = c.x;
8104 GLint y = c.y;
8105 GLsizei width = c.width;
8106 GLsizei height = c.height;
8107 GLenum format = c.format;
8108 GLenum type = c.type;
8109 GLboolean async = static_cast<GLboolean>(c.async);
8110 if (width < 0 || height < 0) {
8111 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glReadPixels", "dimensions < 0");
8112 return error::kNoError;
8114 typedef cmds::ReadPixels::Result Result;
8115 uint32 pixels_size;
8116 if (!GLES2Util::ComputeImageDataSizes(
8117 width, height, 1, format, type, state_.pack_alignment, &pixels_size,
8118 NULL, NULL)) {
8119 return error::kOutOfBounds;
8121 void* pixels = GetSharedMemoryAs<void*>(
8122 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
8123 if (!pixels) {
8124 return error::kOutOfBounds;
8126 Result* result = NULL;
8127 if (c.result_shm_id != 0) {
8128 result = GetSharedMemoryAs<Result*>(
8129 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8130 if (!result) {
8131 return error::kOutOfBounds;
8135 if (!validators_->read_pixel_format.IsValid(format)) {
8136 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", format, "format");
8137 return error::kNoError;
8139 if (!validators_->read_pixel_type.IsValid(type)) {
8140 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", type, "type");
8141 return error::kNoError;
8143 if ((format != GL_RGBA && format != GL_BGRA_EXT && format != GL_RGB &&
8144 format != GL_ALPHA) || type != GL_UNSIGNED_BYTE) {
8145 // format and type are acceptable enums but not guaranteed to be supported
8146 // for this framebuffer. Have to ask gl if they are valid.
8147 GLint preferred_format = 0;
8148 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &preferred_format);
8149 GLint preferred_type = 0;
8150 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &preferred_type);
8151 if (format != static_cast<GLenum>(preferred_format) ||
8152 type != static_cast<GLenum>(preferred_type)) {
8153 LOCAL_SET_GL_ERROR(
8154 GL_INVALID_OPERATION, "glReadPixels", "format and type incompatible "
8155 "with the current read framebuffer");
8156 return error::kNoError;
8159 if (width == 0 || height == 0) {
8160 return error::kNoError;
8163 // Get the size of the current fbo or backbuffer.
8164 gfx::Size max_size = GetBoundReadFrameBufferSize();
8166 int32 max_x;
8167 int32 max_y;
8168 if (!SafeAddInt32(x, width, &max_x) || !SafeAddInt32(y, height, &max_y)) {
8169 LOCAL_SET_GL_ERROR(
8170 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
8171 return error::kNoError;
8174 if (!CheckBoundReadFramebufferColorAttachment("glReadPixels")) {
8175 return error::kNoError;
8178 if (!CheckBoundFramebuffersValid("glReadPixels")) {
8179 return error::kNoError;
8182 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixels");
8184 ScopedResolvedFrameBufferBinder binder(this, false, true);
8186 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
8187 // The user requested an out of range area. Get the results 1 line
8188 // at a time.
8189 uint32 temp_size;
8190 uint32 unpadded_row_size;
8191 uint32 padded_row_size;
8192 if (!GLES2Util::ComputeImageDataSizes(
8193 width, 2, 1, format, type, state_.pack_alignment, &temp_size,
8194 &unpadded_row_size, &padded_row_size)) {
8195 LOCAL_SET_GL_ERROR(
8196 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
8197 return error::kNoError;
8200 GLint dest_x_offset = std::max(-x, 0);
8201 uint32 dest_row_offset;
8202 if (!GLES2Util::ComputeImageDataSizes(
8203 dest_x_offset, 1, 1, format, type, state_.pack_alignment,
8204 &dest_row_offset, NULL, NULL)) {
8205 LOCAL_SET_GL_ERROR(
8206 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
8207 return error::kNoError;
8210 // Copy each row into the larger dest rect.
8211 int8* dst = static_cast<int8*>(pixels);
8212 GLint read_x = std::max(0, x);
8213 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
8214 GLint read_width = read_end_x - read_x;
8215 for (GLint yy = 0; yy < height; ++yy) {
8216 GLint ry = y + yy;
8218 // Clear the row.
8219 memset(dst, 0, unpadded_row_size);
8221 // If the row is in range, copy it.
8222 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
8223 glReadPixels(
8224 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
8226 dst += padded_row_size;
8228 } else {
8229 if (async && features().use_async_readpixels) {
8230 GLuint buffer = 0;
8231 glGenBuffersARB(1, &buffer);
8232 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
8233 // For ANGLE client version 2, GL_STREAM_READ is not available.
8234 const GLenum usage_hint = feature_info_->gl_version_info().is_angle ?
8235 GL_STATIC_DRAW : GL_STREAM_READ;
8236 glBufferData(GL_PIXEL_PACK_BUFFER_ARB, pixels_size, NULL, usage_hint);
8237 GLenum error = glGetError();
8238 if (error == GL_NO_ERROR) {
8239 glReadPixels(x, y, width, height, format, type, 0);
8240 pending_readpixel_fences_.push(linked_ptr<FenceCallback>(
8241 new FenceCallback()));
8242 WaitForReadPixels(base::Bind(
8243 &GLES2DecoderImpl::FinishReadPixels,
8244 base::internal::SupportsWeakPtrBase::StaticAsWeakPtr
8245 <GLES2DecoderImpl>(this),
8246 c, buffer));
8247 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
8248 return error::kNoError;
8249 } else {
8250 // On error, unbind pack buffer and fall through to sync readpixels
8251 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
8252 glDeleteBuffersARB(1, &buffer);
8255 glReadPixels(x, y, width, height, format, type, pixels);
8257 GLenum error = LOCAL_PEEK_GL_ERROR("glReadPixels");
8258 if (error == GL_NO_ERROR) {
8259 if (result != NULL) {
8260 *result = true;
8262 FinishReadPixels(c, 0);
8265 return error::kNoError;
8268 error::Error GLES2DecoderImpl::HandlePixelStorei(uint32 immediate_data_size,
8269 const void* cmd_data) {
8270 const gles2::cmds::PixelStorei& c =
8271 *static_cast<const gles2::cmds::PixelStorei*>(cmd_data);
8272 GLenum pname = c.pname;
8273 GLenum param = c.param;
8274 if (!validators_->pixel_store.IsValid(pname)) {
8275 LOCAL_SET_GL_ERROR_INVALID_ENUM("glPixelStorei", pname, "pname");
8276 return error::kNoError;
8278 switch (pname) {
8279 case GL_PACK_ALIGNMENT:
8280 case GL_UNPACK_ALIGNMENT:
8281 if (!validators_->pixel_store_alignment.IsValid(param)) {
8282 LOCAL_SET_GL_ERROR(
8283 GL_INVALID_VALUE, "glPixelStorei", "param GL_INVALID_VALUE");
8284 return error::kNoError;
8286 break;
8287 case GL_UNPACK_FLIP_Y_CHROMIUM:
8288 unpack_flip_y_ = (param != 0);
8289 return error::kNoError;
8290 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
8291 unpack_premultiply_alpha_ = (param != 0);
8292 return error::kNoError;
8293 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM:
8294 unpack_unpremultiply_alpha_ = (param != 0);
8295 return error::kNoError;
8296 default:
8297 break;
8299 glPixelStorei(pname, param);
8300 switch (pname) {
8301 case GL_PACK_ALIGNMENT:
8302 state_.pack_alignment = param;
8303 break;
8304 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
8305 state_.pack_reverse_row_order = (param != 0);
8306 break;
8307 case GL_UNPACK_ALIGNMENT:
8308 state_.unpack_alignment = param;
8309 break;
8310 default:
8311 // Validation should have prevented us from getting here.
8312 NOTREACHED();
8313 break;
8315 return error::kNoError;
8318 error::Error GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
8319 uint32 immediate_data_size,
8320 const void* cmd_data) {
8321 const gles2::cmds::PostSubBufferCHROMIUM& c =
8322 *static_cast<const gles2::cmds::PostSubBufferCHROMIUM*>(cmd_data);
8323 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
8325 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
8327 if (!supports_post_sub_buffer_) {
8328 LOCAL_SET_GL_ERROR(
8329 GL_INVALID_OPERATION,
8330 "glPostSubBufferCHROMIUM", "command not supported by surface");
8331 return error::kNoError;
8333 bool is_tracing;
8334 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
8335 &is_tracing);
8336 if (is_tracing) {
8337 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
8338 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
8339 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
8340 is_offscreen ? offscreen_size_ : surface_->GetSize());
8342 if (surface_->PostSubBuffer(c.x, c.y, c.width, c.height)) {
8343 return error::kNoError;
8344 } else {
8345 LOG(ERROR) << "Context lost because PostSubBuffer failed.";
8346 return error::kLostContext;
8350 error::Error GLES2DecoderImpl::HandleScheduleOverlayPlaneCHROMIUM(
8351 uint32 immediate_data_size,
8352 const void* cmd_data) {
8353 const gles2::cmds::ScheduleOverlayPlaneCHROMIUM& c =
8354 *static_cast<const gles2::cmds::ScheduleOverlayPlaneCHROMIUM*>(cmd_data);
8355 TextureRef* ref = texture_manager()->GetTexture(c.overlay_texture_id);
8356 if (!ref) {
8357 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
8358 "glScheduleOverlayPlaneCHROMIUM",
8359 "unknown texture");
8360 return error::kNoError;
8362 gfx::GLImage* image =
8363 ref->texture()->GetLevelImage(ref->texture()->target(), 0);
8364 if (!image) {
8365 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
8366 "glScheduleOverlayPlaneCHROMIUM",
8367 "unsupported texture format");
8368 return error::kNoError;
8370 gfx::OverlayTransform transform = GetGFXOverlayTransform(c.plane_transform);
8371 if (transform == gfx::OVERLAY_TRANSFORM_INVALID) {
8372 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM,
8373 "glScheduleOverlayPlaneCHROMIUM",
8374 "invalid transform enum");
8375 return error::kNoError;
8377 if (!surface_->ScheduleOverlayPlane(
8378 c.plane_z_order,
8379 transform,
8380 image,
8381 gfx::Rect(c.bounds_x, c.bounds_y, c.bounds_width, c.bounds_height),
8382 gfx::RectF(c.uv_x, c.uv_y, c.uv_width, c.uv_height))) {
8383 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
8384 "glScheduleOverlayPlaneCHROMIUM",
8385 "failed to schedule overlay");
8387 return error::kNoError;
8390 error::Error GLES2DecoderImpl::GetAttribLocationHelper(
8391 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
8392 const std::string& name_str) {
8393 if (!StringIsValidForGLES(name_str.c_str())) {
8394 LOCAL_SET_GL_ERROR(
8395 GL_INVALID_VALUE, "glGetAttribLocation", "Invalid character");
8396 return error::kNoError;
8398 Program* program = GetProgramInfoNotShader(
8399 client_id, "glGetAttribLocation");
8400 if (!program) {
8401 return error::kNoError;
8403 if (!program->IsValid()) {
8404 LOCAL_SET_GL_ERROR(
8405 GL_INVALID_OPERATION, "glGetAttribLocation", "program not linked");
8406 return error::kNoError;
8408 GLint* location = GetSharedMemoryAs<GLint*>(
8409 location_shm_id, location_shm_offset, sizeof(GLint));
8410 if (!location) {
8411 return error::kOutOfBounds;
8413 // Require the client to init this incase the context is lost and we are no
8414 // longer executing commands.
8415 if (*location != -1) {
8416 return error::kGenericError;
8418 *location = program->GetAttribLocation(name_str);
8419 return error::kNoError;
8422 error::Error GLES2DecoderImpl::HandleGetAttribLocation(
8423 uint32 immediate_data_size,
8424 const void* cmd_data) {
8425 const gles2::cmds::GetAttribLocation& c =
8426 *static_cast<const gles2::cmds::GetAttribLocation*>(cmd_data);
8427 Bucket* bucket = GetBucket(c.name_bucket_id);
8428 if (!bucket) {
8429 return error::kInvalidArguments;
8431 std::string name_str;
8432 if (!bucket->GetAsString(&name_str)) {
8433 return error::kInvalidArguments;
8435 return GetAttribLocationHelper(
8436 c.program, c.location_shm_id, c.location_shm_offset, name_str);
8439 error::Error GLES2DecoderImpl::GetUniformLocationHelper(
8440 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
8441 const std::string& name_str) {
8442 if (!StringIsValidForGLES(name_str.c_str())) {
8443 LOCAL_SET_GL_ERROR(
8444 GL_INVALID_VALUE, "glGetUniformLocation", "Invalid character");
8445 return error::kNoError;
8447 Program* program = GetProgramInfoNotShader(
8448 client_id, "glGetUniformLocation");
8449 if (!program) {
8450 return error::kNoError;
8452 if (!program->IsValid()) {
8453 LOCAL_SET_GL_ERROR(
8454 GL_INVALID_OPERATION, "glGetUniformLocation", "program not linked");
8455 return error::kNoError;
8457 GLint* location = GetSharedMemoryAs<GLint*>(
8458 location_shm_id, location_shm_offset, sizeof(GLint));
8459 if (!location) {
8460 return error::kOutOfBounds;
8462 // Require the client to init this incase the context is lost an we are no
8463 // longer executing commands.
8464 if (*location != -1) {
8465 return error::kGenericError;
8467 *location = program->GetUniformFakeLocation(name_str);
8468 return error::kNoError;
8471 error::Error GLES2DecoderImpl::HandleGetUniformLocation(
8472 uint32 immediate_data_size,
8473 const void* cmd_data) {
8474 const gles2::cmds::GetUniformLocation& c =
8475 *static_cast<const gles2::cmds::GetUniformLocation*>(cmd_data);
8476 Bucket* bucket = GetBucket(c.name_bucket_id);
8477 if (!bucket) {
8478 return error::kInvalidArguments;
8480 std::string name_str;
8481 if (!bucket->GetAsString(&name_str)) {
8482 return error::kInvalidArguments;
8484 return GetUniformLocationHelper(
8485 c.program, c.location_shm_id, c.location_shm_offset, name_str);
8488 error::Error GLES2DecoderImpl::HandleGetUniformIndices(
8489 uint32 immediate_data_size,
8490 const void* cmd_data) {
8491 if (!unsafe_es3_apis_enabled())
8492 return error::kUnknownCommand;
8493 const gles2::cmds::GetUniformIndices& c =
8494 *static_cast<const gles2::cmds::GetUniformIndices*>(cmd_data);
8495 Bucket* bucket = GetBucket(c.names_bucket_id);
8496 if (!bucket) {
8497 return error::kInvalidArguments;
8499 GLsizei count = 0;
8500 std::vector<char*> names;
8501 std::vector<GLint> len;
8502 if (!bucket->GetAsStrings(&count, &names, &len) || count <= 0) {
8503 return error::kInvalidArguments;
8505 typedef cmds::GetUniformIndices::Result Result;
8506 Result* result = GetSharedMemoryAs<Result*>(
8507 c.indices_shm_id, c.indices_shm_offset,
8508 Result::ComputeSize(static_cast<size_t>(count)));
8509 GLuint* indices = result ? result->GetData() : NULL;
8510 if (indices == NULL) {
8511 return error::kOutOfBounds;
8513 // Check that the client initialized the result.
8514 if (result->size != 0) {
8515 return error::kInvalidArguments;
8517 Program* program = GetProgramInfoNotShader(c.program, "glGetUniformIndices");
8518 if (!program) {
8519 return error::kNoError;
8521 GLuint service_id = program->service_id();
8522 GLint link_status = GL_FALSE;
8523 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
8524 if (link_status != GL_TRUE) {
8525 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
8526 "glGetUniformIndices", "program not linked");
8527 return error::kNoError;
8529 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetUniformIndices");
8530 glGetUniformIndices(service_id, count, &names[0], indices);
8531 GLenum error = glGetError();
8532 if (error == GL_NO_ERROR) {
8533 result->SetNumResults(count);
8534 } else {
8535 LOCAL_SET_GL_ERROR(error, "GetUniformIndices", "");
8537 return error::kNoError;
8540 error::Error GLES2DecoderImpl::GetFragDataLocationHelper(
8541 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
8542 const std::string& name_str) {
8543 GLint* location = GetSharedMemoryAs<GLint*>(
8544 location_shm_id, location_shm_offset, sizeof(GLint));
8545 if (!location) {
8546 return error::kOutOfBounds;
8548 // Require the client to init this incase the context is lost and we are no
8549 // longer executing commands.
8550 if (*location != -1) {
8551 return error::kGenericError;
8553 Program* program = GetProgramInfoNotShader(
8554 client_id, "glGetFragDataLocation");
8555 if (!program) {
8556 return error::kNoError;
8558 *location = glGetFragDataLocation(program->service_id(), name_str.c_str());
8559 return error::kNoError;
8562 error::Error GLES2DecoderImpl::HandleGetFragDataLocation(
8563 uint32 immediate_data_size,
8564 const void* cmd_data) {
8565 if (!unsafe_es3_apis_enabled())
8566 return error::kUnknownCommand;
8567 const gles2::cmds::GetFragDataLocation& c =
8568 *static_cast<const gles2::cmds::GetFragDataLocation*>(cmd_data);
8569 Bucket* bucket = GetBucket(c.name_bucket_id);
8570 if (!bucket) {
8571 return error::kInvalidArguments;
8573 std::string name_str;
8574 if (!bucket->GetAsString(&name_str)) {
8575 return error::kInvalidArguments;
8577 return GetFragDataLocationHelper(
8578 c.program, c.location_shm_id, c.location_shm_offset, name_str);
8581 error::Error GLES2DecoderImpl::HandleGetUniformBlockIndex(
8582 uint32 immediate_data_size, const void* cmd_data) {
8583 if (!unsafe_es3_apis_enabled())
8584 return error::kUnknownCommand;
8585 const gles2::cmds::GetUniformBlockIndex& c =
8586 *static_cast<const gles2::cmds::GetUniformBlockIndex*>(cmd_data);
8587 Bucket* bucket = GetBucket(c.name_bucket_id);
8588 if (!bucket) {
8589 return error::kInvalidArguments;
8591 std::string name_str;
8592 if (!bucket->GetAsString(&name_str)) {
8593 return error::kInvalidArguments;
8595 GLuint* index = GetSharedMemoryAs<GLuint*>(
8596 c.index_shm_id, c.index_shm_offset, sizeof(GLuint));
8597 if (!index) {
8598 return error::kOutOfBounds;
8600 // Require the client to init this in case the context is lost and we are no
8601 // longer executing commands.
8602 if (*index != GL_INVALID_INDEX) {
8603 return error::kGenericError;
8605 Program* program = GetProgramInfoNotShader(
8606 c.program, "glGetUniformBlockIndex");
8607 if (!program) {
8608 return error::kNoError;
8610 *index = glGetUniformBlockIndex(program->service_id(), name_str.c_str());
8611 return error::kNoError;
8614 error::Error GLES2DecoderImpl::HandleGetString(uint32 immediate_data_size,
8615 const void* cmd_data) {
8616 const gles2::cmds::GetString& c =
8617 *static_cast<const gles2::cmds::GetString*>(cmd_data);
8618 GLenum name = static_cast<GLenum>(c.name);
8619 if (!validators_->string_type.IsValid(name)) {
8620 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetString", name, "name");
8621 return error::kNoError;
8624 const char* str = nullptr;
8625 std::string extensions;
8626 switch (name) {
8627 case GL_VERSION:
8628 str = "OpenGL ES 2.0 Chromium";
8629 break;
8630 case GL_SHADING_LANGUAGE_VERSION:
8631 str = "OpenGL ES GLSL ES 1.0 Chromium";
8632 break;
8633 case GL_RENDERER:
8634 case GL_VENDOR:
8635 // Return the unmasked VENDOR/RENDERER string for WebGL contexts.
8636 // They are used by WEBGL_debug_renderer_info.
8637 if (!force_webgl_glsl_validation_)
8638 str = "Chromium";
8639 else
8640 str = reinterpret_cast<const char*>(glGetString(name));
8641 break;
8642 case GL_EXTENSIONS:
8644 // For WebGL contexts, strip out the OES derivatives and
8645 // EXT frag depth extensions if they have not been enabled.
8646 if (force_webgl_glsl_validation_) {
8647 extensions = feature_info_->extensions();
8648 if (!derivatives_explicitly_enabled_) {
8649 size_t offset = extensions.find(kOESDerivativeExtension);
8650 if (std::string::npos != offset) {
8651 extensions.replace(offset, arraysize(kOESDerivativeExtension),
8652 std::string());
8655 if (!frag_depth_explicitly_enabled_) {
8656 size_t offset = extensions.find(kEXTFragDepthExtension);
8657 if (std::string::npos != offset) {
8658 extensions.replace(offset, arraysize(kEXTFragDepthExtension),
8659 std::string());
8662 if (!draw_buffers_explicitly_enabled_) {
8663 size_t offset = extensions.find(kEXTDrawBuffersExtension);
8664 if (std::string::npos != offset) {
8665 extensions.replace(offset, arraysize(kEXTDrawBuffersExtension),
8666 std::string());
8669 if (!shader_texture_lod_explicitly_enabled_) {
8670 size_t offset = extensions.find(kEXTShaderTextureLodExtension);
8671 if (std::string::npos != offset) {
8672 extensions.replace(offset,
8673 arraysize(kEXTShaderTextureLodExtension),
8674 std::string());
8677 } else {
8678 extensions = feature_info_->extensions().c_str();
8680 if (supports_post_sub_buffer_)
8681 extensions += " GL_CHROMIUM_post_sub_buffer";
8682 str = extensions.c_str();
8684 break;
8685 default:
8686 str = reinterpret_cast<const char*>(glGetString(name));
8687 break;
8689 Bucket* bucket = CreateBucket(c.bucket_id);
8690 bucket->SetFromString(str);
8691 return error::kNoError;
8694 error::Error GLES2DecoderImpl::HandleBufferData(uint32 immediate_data_size,
8695 const void* cmd_data) {
8696 const gles2::cmds::BufferData& c =
8697 *static_cast<const gles2::cmds::BufferData*>(cmd_data);
8698 GLenum target = static_cast<GLenum>(c.target);
8699 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
8700 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
8701 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
8702 GLenum usage = static_cast<GLenum>(c.usage);
8703 const void* data = NULL;
8704 if (data_shm_id != 0 || data_shm_offset != 0) {
8705 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
8706 if (!data) {
8707 return error::kOutOfBounds;
8710 buffer_manager()->ValidateAndDoBufferData(&state_, target, size, data, usage);
8711 return error::kNoError;
8714 void GLES2DecoderImpl::DoBufferSubData(
8715 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
8716 // Just delegate it. Some validation is actually done before this.
8717 buffer_manager()->ValidateAndDoBufferSubData(
8718 &state_, target, offset, size, data);
8721 bool GLES2DecoderImpl::ClearLevel(
8722 Texture* texture,
8723 unsigned target,
8724 int level,
8725 unsigned internal_format,
8726 unsigned format,
8727 unsigned type,
8728 int width,
8729 int height,
8730 bool is_texture_immutable) {
8731 uint32 channels = GLES2Util::GetChannelsForFormat(format);
8732 if (feature_info_->feature_flags().angle_depth_texture &&
8733 (channels & GLES2Util::kDepth) != 0) {
8734 // It's a depth format and ANGLE doesn't allow texImage2D or texSubImage2D
8735 // on depth formats.
8736 GLuint fb = 0;
8737 glGenFramebuffersEXT(1, &fb);
8738 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb);
8740 bool have_stencil = (channels & GLES2Util::kStencil) != 0;
8741 GLenum attachment = have_stencil ? GL_DEPTH_STENCIL_ATTACHMENT :
8742 GL_DEPTH_ATTACHMENT;
8744 glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, attachment, target,
8745 texture->service_id(), level);
8746 // ANGLE promises a depth only attachment ok.
8747 if (glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT) !=
8748 GL_FRAMEBUFFER_COMPLETE) {
8749 return false;
8751 glClearStencil(0);
8752 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
8753 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
8754 glClearDepth(1.0f);
8755 state_.SetDeviceDepthMask(GL_TRUE);
8756 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
8757 glClear(GL_DEPTH_BUFFER_BIT | (have_stencil ? GL_STENCIL_BUFFER_BIT : 0));
8759 RestoreClearState();
8761 glDeleteFramebuffersEXT(1, &fb);
8762 Framebuffer* framebuffer =
8763 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
8764 GLuint fb_service_id =
8765 framebuffer ? framebuffer->service_id() : GetBackbufferServiceId();
8766 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb_service_id);
8767 return true;
8770 static const uint32 kMaxZeroSize = 1024 * 1024 * 4;
8772 uint32 size;
8773 uint32 padded_row_size;
8774 if (!GLES2Util::ComputeImageDataSizes(
8775 width, height, 1, format, type, state_.unpack_alignment, &size,
8776 NULL, &padded_row_size)) {
8777 return false;
8780 TRACE_EVENT1("gpu", "GLES2DecoderImpl::ClearLevel", "size", size);
8782 int tile_height;
8784 if (size > kMaxZeroSize) {
8785 if (kMaxZeroSize < padded_row_size) {
8786 // That'd be an awfully large texture.
8787 return false;
8789 // We should never have a large total size with a zero row size.
8790 DCHECK_GT(padded_row_size, 0U);
8791 tile_height = kMaxZeroSize / padded_row_size;
8792 if (!GLES2Util::ComputeImageDataSizes(
8793 width, tile_height, 1, format, type, state_.unpack_alignment, &size,
8794 NULL, NULL)) {
8795 return false;
8797 } else {
8798 tile_height = height;
8801 // Assumes the size has already been checked.
8802 scoped_ptr<char[]> zero(new char[size]);
8803 memset(zero.get(), 0, size);
8804 glBindTexture(texture->target(), texture->service_id());
8806 bool has_images = texture->HasImages();
8807 GLint y = 0;
8808 while (y < height) {
8809 GLint h = y + tile_height > height ? height - y : tile_height;
8810 if (is_texture_immutable || h != height || has_images) {
8811 glTexSubImage2D(target, level, 0, y, width, h, format, type, zero.get());
8812 } else {
8813 glTexImage2D(
8814 target, level, internal_format, width, h, 0, format, type,
8815 zero.get());
8817 y += tile_height;
8819 TextureRef* bound_texture =
8820 texture_manager()->GetTextureInfoForTarget(&state_, texture->target());
8821 glBindTexture(texture->target(),
8822 bound_texture ? bound_texture->service_id() : 0);
8823 return true;
8826 namespace {
8828 const int kS3TCBlockWidth = 4;
8829 const int kS3TCBlockHeight = 4;
8830 const int kS3TCDXT1BlockSize = 8;
8831 const int kS3TCDXT3AndDXT5BlockSize = 16;
8832 const int kEACAndETC2BlockSize = 4;
8834 bool IsValidDXTSize(GLint level, GLsizei size) {
8835 return (size == 1) ||
8836 (size == 2) || !(size % kS3TCBlockWidth);
8839 bool IsValidPVRTCSize(GLint level, GLsizei size) {
8840 return GLES2Util::IsPOT(size);
8843 } // anonymous namespace.
8845 bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
8846 const char* function_name, GLsizei width, GLsizei height, GLsizei depth,
8847 GLenum format, GLsizei size) {
8848 base::CheckedNumeric<GLsizei> bytes_required(0);
8850 switch (format) {
8851 case GL_ATC_RGB_AMD:
8852 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
8853 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
8854 case GL_ETC1_RGB8_OES:
8855 bytes_required =
8856 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
8857 bytes_required *=
8858 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
8859 bytes_required *= kS3TCDXT1BlockSize;
8860 break;
8861 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
8862 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
8863 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
8864 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
8865 bytes_required =
8866 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
8867 bytes_required *=
8868 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
8869 bytes_required *= kS3TCDXT3AndDXT5BlockSize;
8870 break;
8871 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
8872 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
8873 bytes_required = std::max(width, 8);
8874 bytes_required *= std::max(height, 8);
8875 bytes_required *= 4;
8876 bytes_required += 7;
8877 bytes_required /= 8;
8878 break;
8879 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
8880 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
8881 bytes_required = std::max(width, 16);
8882 bytes_required *= std::max(height, 8);
8883 bytes_required *= 2;
8884 bytes_required += 7;
8885 bytes_required /= 8;
8886 break;
8888 // ES3 formats.
8889 case GL_COMPRESSED_R11_EAC:
8890 case GL_COMPRESSED_SIGNED_R11_EAC:
8891 case GL_COMPRESSED_RGB8_ETC2:
8892 case GL_COMPRESSED_SRGB8_ETC2:
8893 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
8894 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
8895 bytes_required =
8896 (width + kEACAndETC2BlockSize - 1) / kEACAndETC2BlockSize;
8897 bytes_required *=
8898 (height + kEACAndETC2BlockSize - 1) / kEACAndETC2BlockSize;
8899 bytes_required *= 8;
8900 bytes_required *= depth;
8901 break;
8902 case GL_COMPRESSED_RG11_EAC:
8903 case GL_COMPRESSED_SIGNED_RG11_EAC:
8904 case GL_COMPRESSED_RGBA8_ETC2_EAC:
8905 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
8906 bytes_required =
8907 (width + kEACAndETC2BlockSize - 1) / kEACAndETC2BlockSize;
8908 bytes_required *=
8909 (height + kEACAndETC2BlockSize - 1) / kEACAndETC2BlockSize;
8910 bytes_required *= 16;
8911 bytes_required *= depth;
8912 break;
8913 default:
8914 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, format, "format");
8915 return false;
8918 if (!bytes_required.IsValid() || size != bytes_required.ValueOrDefault(0)) {
8919 LOCAL_SET_GL_ERROR(
8920 GL_INVALID_VALUE, function_name, "size is not correct for dimensions");
8921 return false;
8924 return true;
8927 bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
8928 const char* function_name, GLenum target, GLint level,
8929 GLsizei width, GLsizei height, GLsizei depth, GLenum format) {
8930 switch (format) {
8931 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
8932 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
8933 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
8934 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
8935 DCHECK_EQ(1, depth); // 2D formats.
8936 if (!IsValidDXTSize(level, width) || !IsValidDXTSize(level, height)) {
8937 LOCAL_SET_GL_ERROR(
8938 GL_INVALID_OPERATION, function_name,
8939 "width or height invalid for level");
8940 return false;
8942 return true;
8943 case GL_ATC_RGB_AMD:
8944 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
8945 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
8946 case GL_ETC1_RGB8_OES:
8947 DCHECK_EQ(1, depth); // 2D formats.
8948 if (width <= 0 || height <= 0) {
8949 LOCAL_SET_GL_ERROR(
8950 GL_INVALID_OPERATION, function_name,
8951 "width or height invalid for level");
8952 return false;
8954 return true;
8955 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
8956 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
8957 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
8958 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
8959 DCHECK_EQ(1, depth); // 2D formats.
8960 if (!IsValidPVRTCSize(level, width) ||
8961 !IsValidPVRTCSize(level, height)) {
8962 LOCAL_SET_GL_ERROR(
8963 GL_INVALID_OPERATION, function_name,
8964 "width or height invalid for level");
8965 return false;
8967 return true;
8969 // ES3 formats.
8970 case GL_COMPRESSED_R11_EAC:
8971 case GL_COMPRESSED_SIGNED_R11_EAC:
8972 case GL_COMPRESSED_RG11_EAC:
8973 case GL_COMPRESSED_SIGNED_RG11_EAC:
8974 case GL_COMPRESSED_RGB8_ETC2:
8975 case GL_COMPRESSED_SRGB8_ETC2:
8976 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
8977 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
8978 case GL_COMPRESSED_RGBA8_ETC2_EAC:
8979 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
8980 if (width <= 0 || height <= 0 || depth <= 0) {
8981 LOCAL_SET_GL_ERROR(
8982 GL_INVALID_OPERATION, function_name,
8983 "width, height, or depth invalid");
8984 return false;
8986 if (target != GL_TEXTURE_2D_ARRAY) {
8987 LOCAL_SET_GL_ERROR(
8988 GL_INVALID_OPERATION, function_name,
8989 "target invalid for format");
8990 return false;
8992 return true;
8993 default:
8994 return false;
8998 bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
8999 const char* function_name,
9000 GLenum target, GLint level, GLint xoffset, GLint yoffset,
9001 GLsizei width, GLsizei height, GLenum format,
9002 Texture* texture) {
9003 if (xoffset < 0 || yoffset < 0) {
9004 LOCAL_SET_GL_ERROR(
9005 GL_INVALID_VALUE, function_name, "xoffset or yoffset < 0");
9006 return false;
9009 switch (format) {
9010 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
9011 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
9012 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
9013 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
9014 const int kBlockWidth = 4;
9015 const int kBlockHeight = 4;
9016 if ((xoffset % kBlockWidth) || (yoffset % kBlockHeight)) {
9017 LOCAL_SET_GL_ERROR(
9018 GL_INVALID_OPERATION, function_name,
9019 "xoffset or yoffset not multiple of 4");
9020 return false;
9022 GLsizei tex_width = 0;
9023 GLsizei tex_height = 0;
9024 if (!texture->GetLevelSize(target, level, &tex_width, &tex_height) ||
9025 width - xoffset > tex_width ||
9026 height - yoffset > tex_height) {
9027 LOCAL_SET_GL_ERROR(
9028 GL_INVALID_OPERATION, function_name, "dimensions out of range");
9029 return false;
9031 return ValidateCompressedTexDimensions(
9032 function_name, target, level, width, height, 1, format);
9034 case GL_ATC_RGB_AMD:
9035 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
9036 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD: {
9037 LOCAL_SET_GL_ERROR(
9038 GL_INVALID_OPERATION, function_name,
9039 "not supported for ATC textures");
9040 return false;
9042 case GL_ETC1_RGB8_OES: {
9043 LOCAL_SET_GL_ERROR(
9044 GL_INVALID_OPERATION, function_name,
9045 "not supported for ECT1_RGB8_OES textures");
9046 return false;
9048 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
9049 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
9050 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
9051 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
9052 if ((xoffset != 0) || (yoffset != 0)) {
9053 LOCAL_SET_GL_ERROR(
9054 GL_INVALID_OPERATION, function_name,
9055 "xoffset and yoffset must be zero");
9056 return false;
9058 GLsizei tex_width = 0;
9059 GLsizei tex_height = 0;
9060 if (!texture->GetLevelSize(target, level, &tex_width, &tex_height) ||
9061 width != tex_width ||
9062 height != tex_height) {
9063 LOCAL_SET_GL_ERROR(
9064 GL_INVALID_OPERATION, function_name,
9065 "dimensions must match existing texture level dimensions");
9066 return false;
9068 return ValidateCompressedTexDimensions(
9069 function_name, target, level, width, height, 1, format);
9071 default:
9072 return false;
9076 error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
9077 GLenum target,
9078 GLint level,
9079 GLenum internal_format,
9080 GLsizei width,
9081 GLsizei height,
9082 GLint border,
9083 GLsizei image_size,
9084 const void* data) {
9085 if (!validators_->texture_target.IsValid(target)) {
9086 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9087 "glCompressedTexImage2D", target, "target");
9088 return error::kNoError;
9090 if (!validators_->compressed_texture_format.IsValid(
9091 internal_format)) {
9092 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9093 "glCompressedTexImage2D", internal_format, "internal_format");
9094 return error::kNoError;
9096 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
9097 border != 0) {
9098 LOCAL_SET_GL_ERROR(
9099 GL_INVALID_VALUE,
9100 "glCompressedTexImage2D", "dimensions out of range");
9101 return error::kNoError;
9103 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9104 &state_, target);
9105 if (!texture_ref) {
9106 LOCAL_SET_GL_ERROR(
9107 GL_INVALID_VALUE,
9108 "glCompressedTexImage2D", "unknown texture target");
9109 return error::kNoError;
9111 Texture* texture = texture_ref->texture();
9112 if (texture->IsImmutable()) {
9113 LOCAL_SET_GL_ERROR(
9114 GL_INVALID_OPERATION,
9115 "glCompressedTexImage2D", "texture is immutable");
9116 return error::kNoError;
9119 if (!ValidateCompressedTexDimensions("glCompressedTexImage2D", target, level,
9120 width, height, 1, internal_format) ||
9121 !ValidateCompressedTexFuncData("glCompressedTexImage2D", width, height,
9122 1, internal_format, image_size)) {
9123 return error::kNoError;
9126 if (!EnsureGPUMemoryAvailable(image_size)) {
9127 LOCAL_SET_GL_ERROR(
9128 GL_OUT_OF_MEMORY, "glCompressedTexImage2D", "out of memory");
9129 return error::kNoError;
9132 if (texture->IsAttachedToFramebuffer()) {
9133 framebuffer_state_.clear_state_dirty = true;
9136 scoped_ptr<int8[]> zero;
9137 if (!data) {
9138 zero.reset(new int8[image_size]);
9139 memset(zero.get(), 0, image_size);
9140 data = zero.get();
9142 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage2D");
9143 glCompressedTexImage2D(
9144 target, level, internal_format, width, height, border, image_size, data);
9145 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedTexImage2D");
9146 if (error == GL_NO_ERROR) {
9147 texture_manager()->SetLevelInfo(
9148 texture_ref, target, level, internal_format,
9149 width, height, 1, border, 0, 0, true);
9152 // This may be a slow command. Exit command processing to allow for
9153 // context preemption and GPU watchdog checks.
9154 ExitCommandProcessingEarly();
9155 return error::kNoError;
9158 error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
9159 uint32 immediate_data_size,
9160 const void* cmd_data) {
9161 const gles2::cmds::CompressedTexImage2D& c =
9162 *static_cast<const gles2::cmds::CompressedTexImage2D*>(cmd_data);
9163 GLenum target = static_cast<GLenum>(c.target);
9164 GLint level = static_cast<GLint>(c.level);
9165 GLenum internal_format = static_cast<GLenum>(c.internalformat);
9166 GLsizei width = static_cast<GLsizei>(c.width);
9167 GLsizei height = static_cast<GLsizei>(c.height);
9168 GLint border = static_cast<GLint>(c.border);
9169 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
9170 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
9171 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
9172 const void* data = NULL;
9173 if (data_shm_id != 0 || data_shm_offset != 0) {
9174 data = GetSharedMemoryAs<const void*>(
9175 data_shm_id, data_shm_offset, image_size);
9176 if (!data) {
9177 return error::kOutOfBounds;
9180 return DoCompressedTexImage2D(
9181 target, level, internal_format, width, height, border, image_size, data);
9184 error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
9185 uint32 immediate_data_size,
9186 const void* cmd_data) {
9187 const gles2::cmds::CompressedTexImage2DBucket& c =
9188 *static_cast<const gles2::cmds::CompressedTexImage2DBucket*>(cmd_data);
9189 GLenum target = static_cast<GLenum>(c.target);
9190 GLint level = static_cast<GLint>(c.level);
9191 GLenum internal_format = static_cast<GLenum>(c.internalformat);
9192 GLsizei width = static_cast<GLsizei>(c.width);
9193 GLsizei height = static_cast<GLsizei>(c.height);
9194 GLint border = static_cast<GLint>(c.border);
9195 Bucket* bucket = GetBucket(c.bucket_id);
9196 if (!bucket) {
9197 return error::kInvalidArguments;
9199 uint32 data_size = bucket->size();
9200 GLsizei imageSize = data_size;
9201 const void* data = bucket->GetData(0, data_size);
9202 if (!data) {
9203 return error::kInvalidArguments;
9205 return DoCompressedTexImage2D(
9206 target, level, internal_format, width, height, border,
9207 imageSize, data);
9210 error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
9211 uint32 immediate_data_size,
9212 const void* cmd_data) {
9213 const gles2::cmds::CompressedTexSubImage2DBucket& c =
9214 *static_cast<const gles2::cmds::CompressedTexSubImage2DBucket*>(cmd_data);
9215 GLenum target = static_cast<GLenum>(c.target);
9216 GLint level = static_cast<GLint>(c.level);
9217 GLint xoffset = static_cast<GLint>(c.xoffset);
9218 GLint yoffset = static_cast<GLint>(c.yoffset);
9219 GLsizei width = static_cast<GLsizei>(c.width);
9220 GLsizei height = static_cast<GLsizei>(c.height);
9221 GLenum format = static_cast<GLenum>(c.format);
9222 Bucket* bucket = GetBucket(c.bucket_id);
9223 if (!bucket) {
9224 return error::kInvalidArguments;
9226 uint32 data_size = bucket->size();
9227 GLsizei imageSize = data_size;
9228 const void* data = bucket->GetData(0, data_size);
9229 if (!data) {
9230 return error::kInvalidArguments;
9232 if (!validators_->texture_target.IsValid(target)) {
9233 LOCAL_SET_GL_ERROR(
9234 GL_INVALID_ENUM, "glCompressedTexSubImage2D", "target");
9235 return error::kNoError;
9237 if (!validators_->compressed_texture_format.IsValid(format)) {
9238 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9239 "glCompressedTexSubImage2D", format, "format");
9240 return error::kNoError;
9242 if (width < 0) {
9243 LOCAL_SET_GL_ERROR(
9244 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "width < 0");
9245 return error::kNoError;
9247 if (height < 0) {
9248 LOCAL_SET_GL_ERROR(
9249 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "height < 0");
9250 return error::kNoError;
9252 if (imageSize < 0) {
9253 LOCAL_SET_GL_ERROR(
9254 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "imageSize < 0");
9255 return error::kNoError;
9257 DoCompressedTexSubImage2D(
9258 target, level, xoffset, yoffset, width, height, format, imageSize, data);
9259 return error::kNoError;
9262 error::Error GLES2DecoderImpl::DoCompressedTexImage3D(
9263 GLenum target,
9264 GLint level,
9265 GLenum internal_format,
9266 GLsizei width,
9267 GLsizei height,
9268 GLsizei depth,
9269 GLint border,
9270 GLsizei image_size,
9271 const void* data) {
9272 if (!validators_->texture_3_d_target.IsValid(target)) {
9273 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9274 "glCompressedTexImage3D", target, "target");
9275 return error::kNoError;
9277 if (!validators_->compressed_texture_format.IsValid(
9278 internal_format)) {
9279 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9280 "glCompressedTexImage3D", internal_format, "internal_format");
9281 return error::kNoError;
9283 if (!texture_manager()->ValidForTarget(target, level, width, height, depth) ||
9284 border != 0) {
9285 LOCAL_SET_GL_ERROR(
9286 GL_INVALID_VALUE,
9287 "glCompressedTexImage3D", "dimensions out of range");
9288 return error::kNoError;
9290 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9291 &state_, target);
9292 if (!texture_ref) {
9293 LOCAL_SET_GL_ERROR(
9294 GL_INVALID_VALUE,
9295 "glCompressedTexImage3D", "unknown texture target");
9296 return error::kNoError;
9298 Texture* texture = texture_ref->texture();
9299 if (texture->IsImmutable()) {
9300 LOCAL_SET_GL_ERROR(
9301 GL_INVALID_OPERATION,
9302 "glCompressedTexImage3D", "texture is immutable");
9303 return error::kNoError;
9306 if (!ValidateCompressedTexDimensions("glCompressedTexImage3D", target, level,
9307 width, height, depth, internal_format) ||
9308 !ValidateCompressedTexFuncData("glCompressedTexImage3D", width, height,
9309 depth, internal_format, image_size)) {
9310 return error::kNoError;
9313 if (!EnsureGPUMemoryAvailable(image_size)) {
9314 LOCAL_SET_GL_ERROR(
9315 GL_OUT_OF_MEMORY, "glCompressedTexImage3D", "out of memory");
9316 return error::kNoError;
9319 if (texture->IsAttachedToFramebuffer()) {
9320 framebuffer_state_.clear_state_dirty = true;
9323 scoped_ptr<int8[]> zero;
9324 if (!data) {
9325 zero.reset(new int8[image_size]);
9326 memset(zero.get(), 0, image_size);
9327 data = zero.get();
9329 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage3D");
9330 glCompressedTexImage3D(target, level, internal_format, width, height, depth,
9331 border, image_size, data);
9332 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedTexImage3D");
9333 if (error == GL_NO_ERROR) {
9334 texture_manager()->SetLevelInfo(
9335 texture_ref, target, level, internal_format,
9336 width, height, depth, border, 0, 0, true);
9339 // This may be a slow command. Exit command processing to allow for
9340 // context preemption and GPU watchdog checks.
9341 ExitCommandProcessingEarly();
9342 return error::kNoError;
9345 error::Error GLES2DecoderImpl::HandleCompressedTexImage3D(
9346 uint32 immediate_data_size, const void* cmd_data) {
9347 if (!unsafe_es3_apis_enabled())
9348 return error::kUnknownCommand;
9350 const gles2::cmds::CompressedTexImage3D& c =
9351 *static_cast<const gles2::cmds::CompressedTexImage3D*>(cmd_data);
9352 GLenum target = static_cast<GLenum>(c.target);
9353 GLint level = static_cast<GLint>(c.level);
9354 GLenum internal_format = static_cast<GLenum>(c.internalformat);
9355 GLsizei width = static_cast<GLsizei>(c.width);
9356 GLsizei height = static_cast<GLsizei>(c.height);
9357 GLsizei depth = static_cast<GLsizei>(c.depth);
9358 GLint border = static_cast<GLint>(c.border);
9359 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
9360 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
9361 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
9362 const void* data = NULL;
9363 if (data_shm_id != 0 || data_shm_offset != 0) {
9364 data = GetSharedMemoryAs<const void*>(
9365 data_shm_id, data_shm_offset, image_size);
9366 if (!data) {
9367 return error::kOutOfBounds;
9370 return DoCompressedTexImage3D(target, level, internal_format, width, height,
9371 depth, border, image_size, data);
9374 error::Error GLES2DecoderImpl::HandleCompressedTexImage3DBucket(
9375 uint32 immediate_data_size, const void* cmd_data) {
9376 if (!unsafe_es3_apis_enabled())
9377 return error::kUnknownCommand;
9379 const gles2::cmds::CompressedTexImage3DBucket& c =
9380 *static_cast<const gles2::cmds::CompressedTexImage3DBucket*>(cmd_data);
9381 GLenum target = static_cast<GLenum>(c.target);
9382 GLint level = static_cast<GLint>(c.level);
9383 GLenum internal_format = static_cast<GLenum>(c.internalformat);
9384 GLsizei width = static_cast<GLsizei>(c.width);
9385 GLsizei height = static_cast<GLsizei>(c.height);
9386 GLsizei depth = static_cast<GLsizei>(c.depth);
9387 GLint border = static_cast<GLint>(c.border);
9388 Bucket* bucket = GetBucket(c.bucket_id);
9389 if (!bucket) {
9390 return error::kInvalidArguments;
9392 uint32 data_size = bucket->size();
9393 GLsizei imageSize = data_size;
9394 const void* data = bucket->GetData(0, data_size);
9395 if (!data) {
9396 return error::kInvalidArguments;
9398 return DoCompressedTexImage3D(target, level, internal_format, width, height,
9399 depth, border, imageSize, data);
9402 error::Error GLES2DecoderImpl::HandleTexImage2D(uint32 immediate_data_size,
9403 const void* cmd_data) {
9404 const gles2::cmds::TexImage2D& c =
9405 *static_cast<const gles2::cmds::TexImage2D*>(cmd_data);
9406 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage2D",
9407 "width", c.width, "height", c.height);
9408 // Set as failed for now, but if it successed, this will be set to not failed.
9409 texture_state_.tex_image_2d_failed = true;
9410 GLenum target = static_cast<GLenum>(c.target);
9411 GLint level = static_cast<GLint>(c.level);
9412 // TODO(kloveless): Change TexImage2D command to use unsigned integer
9413 // for internalformat.
9414 GLenum internal_format = static_cast<GLenum>(c.internalformat);
9415 GLsizei width = static_cast<GLsizei>(c.width);
9416 GLsizei height = static_cast<GLsizei>(c.height);
9417 GLint border = static_cast<GLint>(c.border);
9418 GLenum format = static_cast<GLenum>(c.format);
9419 GLenum type = static_cast<GLenum>(c.type);
9420 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
9421 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
9422 uint32 pixels_size;
9423 if (!GLES2Util::ComputeImageDataSizes(
9424 width, height, 1, format, type, state_.unpack_alignment, &pixels_size,
9425 NULL, NULL)) {
9426 return error::kOutOfBounds;
9428 const void* pixels = NULL;
9429 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
9430 pixels = GetSharedMemoryAs<const void*>(
9431 pixels_shm_id, pixels_shm_offset, pixels_size);
9432 if (!pixels) {
9433 return error::kOutOfBounds;
9437 // For testing only. Allows us to stress the ability to respond to OOM errors.
9438 if (workarounds().simulate_out_of_memory_on_large_textures &&
9439 (width * height >= 4096 * 4096)) {
9440 LOCAL_SET_GL_ERROR(
9441 GL_OUT_OF_MEMORY,
9442 "glTexImage2D", "synthetic out of memory");
9443 return error::kNoError;
9446 TextureManager::DoTextImage2DArguments args = {
9447 target, level, internal_format, width, height, border, format, type,
9448 pixels, pixels_size};
9449 texture_manager()->ValidateAndDoTexImage2D(
9450 &texture_state_, &state_, &framebuffer_state_, args);
9452 // This may be a slow command. Exit command processing to allow for
9453 // context preemption and GPU watchdog checks.
9454 ExitCommandProcessingEarly();
9455 return error::kNoError;
9458 error::Error GLES2DecoderImpl::HandleTexImage3D(uint32 immediate_data_size,
9459 const void* cmd_data) {
9460 // TODO(zmo): Unsafe ES3 API.
9461 if (!unsafe_es3_apis_enabled())
9462 return error::kUnknownCommand;
9464 const gles2::cmds::TexImage3D& c =
9465 *static_cast<const gles2::cmds::TexImage3D*>(cmd_data);
9466 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage3D",
9467 "widthXheight", c.width * c.height, "depth", c.depth);
9468 GLenum target = static_cast<GLenum>(c.target);
9469 GLint level = static_cast<GLint>(c.level);
9470 GLenum internal_format = static_cast<GLenum>(c.internalformat);
9471 GLsizei width = static_cast<GLsizei>(c.width);
9472 GLsizei height = static_cast<GLsizei>(c.height);
9473 GLsizei depth = static_cast<GLsizei>(c.depth);
9474 GLint border = static_cast<GLint>(c.border);
9475 GLenum format = static_cast<GLenum>(c.format);
9476 GLenum type = static_cast<GLenum>(c.type);
9477 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
9478 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
9479 uint32 pixels_size;
9480 if (!GLES2Util::ComputeImageDataSizes(
9481 width, height, depth, format, type, state_.unpack_alignment, &pixels_size,
9482 NULL, NULL)) {
9483 return error::kOutOfBounds;
9485 const void* pixels = NULL;
9486 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
9487 pixels = GetSharedMemoryAs<const void*>(
9488 pixels_shm_id, pixels_shm_offset, pixels_size);
9489 if (!pixels) {
9490 return error::kOutOfBounds;
9494 glTexImage3D(target, level, internal_format, width, height, depth, border,
9495 format, type, pixels);
9497 // This may be a slow command. Exit command processing to allow for
9498 // context preemption and GPU watchdog checks.
9499 ExitCommandProcessingEarly();
9500 return error::kNoError;
9503 void GLES2DecoderImpl::DoCompressedTexSubImage2D(
9504 GLenum target,
9505 GLint level,
9506 GLint xoffset,
9507 GLint yoffset,
9508 GLsizei width,
9509 GLsizei height,
9510 GLenum format,
9511 GLsizei image_size,
9512 const void * data) {
9513 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9514 &state_, target);
9515 if (!texture_ref) {
9516 LOCAL_SET_GL_ERROR(
9517 GL_INVALID_OPERATION,
9518 "glCompressedTexSubImage2D", "unknown texture for target");
9519 return;
9521 Texture* texture = texture_ref->texture();
9522 GLenum type = 0;
9523 GLenum internal_format = 0;
9524 if (!texture->GetLevelType(target, level, &type, &internal_format)) {
9525 LOCAL_SET_GL_ERROR(
9526 GL_INVALID_OPERATION,
9527 "glCompressedTexSubImage2D", "level does not exist.");
9528 return;
9530 if (internal_format != format) {
9531 LOCAL_SET_GL_ERROR(
9532 GL_INVALID_OPERATION,
9533 "glCompressedTexSubImage2D", "format does not match internal format.");
9534 return;
9536 if (!texture->ValidForTexture(
9537 target, level, xoffset, yoffset, width, height, type)) {
9538 LOCAL_SET_GL_ERROR(
9539 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "bad dimensions.");
9540 return;
9543 if (!ValidateCompressedTexFuncData("glCompressedTexSubImage2D",
9544 width, height, 1, format, image_size) ||
9545 !ValidateCompressedTexSubDimensions(
9546 "glCompressedTexSubImage2D",
9547 target, level, xoffset, yoffset, width, height, format, texture)) {
9548 return;
9552 // Note: There is no need to deal with texture cleared tracking here
9553 // because the validation above means you can only get here if the level
9554 // is already a matching compressed format and in that case
9555 // CompressedTexImage2D already cleared the texture.
9556 glCompressedTexSubImage2D(
9557 target, level, xoffset, yoffset, width, height, format, image_size, data);
9559 // This may be a slow command. Exit command processing to allow for
9560 // context preemption and GPU watchdog checks.
9561 ExitCommandProcessingEarly();
9564 static void Clip(
9565 GLint start, GLint range, GLint sourceRange,
9566 GLint* out_start, GLint* out_range) {
9567 DCHECK(out_start);
9568 DCHECK(out_range);
9569 if (start < 0) {
9570 range += start;
9571 start = 0;
9573 GLint end = start + range;
9574 if (end > sourceRange) {
9575 range -= end - sourceRange;
9577 *out_start = start;
9578 *out_range = range;
9581 void GLES2DecoderImpl::DoCopyTexImage2D(
9582 GLenum target,
9583 GLint level,
9584 GLenum internal_format,
9585 GLint x,
9586 GLint y,
9587 GLsizei width,
9588 GLsizei height,
9589 GLint border) {
9590 DCHECK(!ShouldDeferReads());
9591 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9592 &state_, target);
9593 if (!texture_ref) {
9594 LOCAL_SET_GL_ERROR(
9595 GL_INVALID_OPERATION,
9596 "glCopyTexImage2D", "unknown texture for target");
9597 return;
9599 Texture* texture = texture_ref->texture();
9600 if (texture->IsImmutable()) {
9601 LOCAL_SET_GL_ERROR(
9602 GL_INVALID_OPERATION, "glCopyTexImage2D", "texture is immutable");
9603 return;
9605 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
9606 border != 0) {
9607 LOCAL_SET_GL_ERROR(
9608 GL_INVALID_VALUE, "glCopyTexImage2D", "dimensions out of range");
9609 return;
9611 if (!texture_manager()->ValidateFormatAndTypeCombination(
9612 state_.GetErrorState(), "glCopyTexImage2D", internal_format,
9613 GL_UNSIGNED_BYTE)) {
9614 return;
9617 // Check we have compatible formats.
9618 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
9619 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
9620 uint32 channels_needed = GLES2Util::GetChannelsForFormat(internal_format);
9622 if ((channels_needed & channels_exist) != channels_needed) {
9623 LOCAL_SET_GL_ERROR(
9624 GL_INVALID_OPERATION, "glCopyTexImage2D", "incompatible format");
9625 return;
9628 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
9629 LOCAL_SET_GL_ERROR(
9630 GL_INVALID_OPERATION,
9631 "glCopyTexImage2D", "can not be used with depth or stencil textures");
9632 return;
9635 uint32 estimated_size = 0;
9636 if (!GLES2Util::ComputeImageDataSizes(
9637 width, height, 1, internal_format, GL_UNSIGNED_BYTE,
9638 state_.unpack_alignment, &estimated_size, NULL, NULL)) {
9639 LOCAL_SET_GL_ERROR(
9640 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too large");
9641 return;
9644 if (!EnsureGPUMemoryAvailable(estimated_size)) {
9645 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexImage2D", "out of memory");
9646 return;
9649 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexImage2D")) {
9650 return;
9653 if (FormsTextureCopyingFeedbackLoop(texture_ref, level)) {
9654 LOCAL_SET_GL_ERROR(
9655 GL_INVALID_OPERATION,
9656 "glCopyTexImage2D", "source and destination textures are the same");
9657 return;
9660 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
9661 return;
9664 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTexImage2D");
9665 ScopedResolvedFrameBufferBinder binder(this, false, true);
9666 gfx::Size size = GetBoundReadFrameBufferSize();
9668 if (texture->IsAttachedToFramebuffer()) {
9669 framebuffer_state_.clear_state_dirty = true;
9672 // Clip to size to source dimensions
9673 GLint copyX = 0;
9674 GLint copyY = 0;
9675 GLint copyWidth = 0;
9676 GLint copyHeight = 0;
9677 Clip(x, width, size.width(), &copyX, &copyWidth);
9678 Clip(y, height, size.height(), &copyY, &copyHeight);
9680 if (copyX != x ||
9681 copyY != y ||
9682 copyWidth != width ||
9683 copyHeight != height) {
9684 // some part was clipped so clear the texture.
9685 if (!ClearLevel(texture, target, level, internal_format, internal_format,
9686 GL_UNSIGNED_BYTE, width, height, texture->IsImmutable())) {
9687 LOCAL_SET_GL_ERROR(
9688 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too big");
9689 return;
9691 if (copyHeight > 0 && copyWidth > 0) {
9692 GLint dx = copyX - x;
9693 GLint dy = copyY - y;
9694 GLint destX = dx;
9695 GLint destY = dy;
9696 ScopedModifyPixels modify(texture_ref);
9697 glCopyTexSubImage2D(target, level,
9698 destX, destY, copyX, copyY,
9699 copyWidth, copyHeight);
9701 } else {
9702 ScopedModifyPixels modify(texture_ref);
9703 glCopyTexImage2D(target, level, internal_format,
9704 copyX, copyY, copyWidth, copyHeight, border);
9706 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTexImage2D");
9707 if (error == GL_NO_ERROR) {
9708 texture_manager()->SetLevelInfo(
9709 texture_ref, target, level, internal_format, width, height, 1,
9710 border, internal_format, GL_UNSIGNED_BYTE, true);
9713 // This may be a slow command. Exit command processing to allow for
9714 // context preemption and GPU watchdog checks.
9715 ExitCommandProcessingEarly();
9718 void GLES2DecoderImpl::DoCopyTexSubImage2D(
9719 GLenum target,
9720 GLint level,
9721 GLint xoffset,
9722 GLint yoffset,
9723 GLint x,
9724 GLint y,
9725 GLsizei width,
9726 GLsizei height) {
9727 DCHECK(!ShouldDeferReads());
9728 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9729 &state_, target);
9730 if (!texture_ref) {
9731 LOCAL_SET_GL_ERROR(
9732 GL_INVALID_OPERATION,
9733 "glCopyTexSubImage2D", "unknown texture for target");
9734 return;
9736 Texture* texture = texture_ref->texture();
9737 GLenum type = 0;
9738 GLenum format = 0;
9739 if (!texture->GetLevelType(target, level, &type, &format) ||
9740 !texture->ValidForTexture(
9741 target, level, xoffset, yoffset, width, height, type)) {
9742 LOCAL_SET_GL_ERROR(
9743 GL_INVALID_VALUE, "glCopyTexSubImage2D", "bad dimensions.");
9744 return;
9746 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
9747 LOCAL_SET_GL_ERROR(
9748 GL_INVALID_OPERATION,
9749 "glCopyTexSubImage2D", "async upload pending for texture");
9750 return;
9753 // Check we have compatible formats.
9754 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
9755 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
9756 uint32 channels_needed = GLES2Util::GetChannelsForFormat(format);
9758 if (!channels_needed ||
9759 (channels_needed & channels_exist) != channels_needed) {
9760 LOCAL_SET_GL_ERROR(
9761 GL_INVALID_OPERATION, "glCopyTexSubImage2D", "incompatible format");
9762 return;
9765 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
9766 LOCAL_SET_GL_ERROR(
9767 GL_INVALID_OPERATION,
9768 "glCopySubImage2D", "can not be used with depth or stencil textures");
9769 return;
9772 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexSubImage2D")) {
9773 return;
9776 if (FormsTextureCopyingFeedbackLoop(texture_ref, level)) {
9777 LOCAL_SET_GL_ERROR(
9778 GL_INVALID_OPERATION,
9779 "glCopyTexSubImage2D", "source and destination textures are the same");
9780 return;
9783 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
9784 return;
9787 ScopedResolvedFrameBufferBinder binder(this, false, true);
9788 gfx::Size size = GetBoundReadFrameBufferSize();
9789 GLint copyX = 0;
9790 GLint copyY = 0;
9791 GLint copyWidth = 0;
9792 GLint copyHeight = 0;
9793 Clip(x, width, size.width(), &copyX, &copyWidth);
9794 Clip(y, height, size.height(), &copyY, &copyHeight);
9796 if (xoffset != 0 || yoffset != 0 || width != size.width() ||
9797 height != size.height()) {
9798 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target,
9799 level)) {
9800 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexSubImage2D",
9801 "dimensions too big");
9802 return;
9804 } else {
9805 // Write all pixels in below.
9806 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
9809 if (copyX != x ||
9810 copyY != y ||
9811 copyWidth != width ||
9812 copyHeight != height) {
9813 // some part was clipped so clear the sub rect.
9814 uint32 pixels_size = 0;
9815 if (!GLES2Util::ComputeImageDataSizes(
9816 width, height, 1, format, type, state_.unpack_alignment, &pixels_size,
9817 NULL, NULL)) {
9818 LOCAL_SET_GL_ERROR(
9819 GL_INVALID_VALUE, "glCopyTexSubImage2D", "dimensions too large");
9820 return;
9822 scoped_ptr<char[]> zero(new char[pixels_size]);
9823 memset(zero.get(), 0, pixels_size);
9824 ScopedModifyPixels modify(texture_ref);
9825 glTexSubImage2D(
9826 target, level, xoffset, yoffset, width, height,
9827 format, type, zero.get());
9830 if (copyHeight > 0 && copyWidth > 0) {
9831 GLint dx = copyX - x;
9832 GLint dy = copyY - y;
9833 GLint destX = xoffset + dx;
9834 GLint destY = yoffset + dy;
9835 ScopedModifyPixels modify(texture_ref);
9836 glCopyTexSubImage2D(target, level,
9837 destX, destY, copyX, copyY,
9838 copyWidth, copyHeight);
9841 // This may be a slow command. Exit command processing to allow for
9842 // context preemption and GPU watchdog checks.
9843 ExitCommandProcessingEarly();
9846 bool GLES2DecoderImpl::ValidateTexSubImage2D(
9847 error::Error* error,
9848 const char* function_name,
9849 GLenum target,
9850 GLint level,
9851 GLint xoffset,
9852 GLint yoffset,
9853 GLsizei width,
9854 GLsizei height,
9855 GLenum format,
9856 GLenum type,
9857 const void * data) {
9858 (*error) = error::kNoError;
9859 if (!validators_->texture_target.IsValid(target)) {
9860 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
9861 return false;
9863 if (width < 0) {
9864 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "width < 0");
9865 return false;
9867 if (height < 0) {
9868 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "height < 0");
9869 return false;
9871 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9872 &state_, target);
9873 if (!texture_ref) {
9874 LOCAL_SET_GL_ERROR(
9875 GL_INVALID_OPERATION,
9876 function_name, "unknown texture for target");
9877 return false;
9879 Texture* texture = texture_ref->texture();
9880 GLenum current_type = 0;
9881 GLenum internal_format = 0;
9882 if (!texture->GetLevelType(target, level, &current_type, &internal_format)) {
9883 LOCAL_SET_GL_ERROR(
9884 GL_INVALID_OPERATION, function_name, "level does not exist.");
9885 return false;
9887 if (!texture_manager()->ValidateTextureParameters(state_.GetErrorState(),
9888 function_name, format, type, internal_format, level)) {
9889 return false;
9891 if (type != current_type) {
9892 LOCAL_SET_GL_ERROR(
9893 GL_INVALID_OPERATION,
9894 function_name, "type does not match type of texture.");
9895 return false;
9897 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
9898 LOCAL_SET_GL_ERROR(
9899 GL_INVALID_OPERATION,
9900 function_name, "async upload pending for texture");
9901 return false;
9903 if (!texture->ValidForTexture(
9904 target, level, xoffset, yoffset, width, height, type)) {
9905 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "bad dimensions.");
9906 return false;
9908 if ((GLES2Util::GetChannelsForFormat(format) &
9909 (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
9910 LOCAL_SET_GL_ERROR(
9911 GL_INVALID_OPERATION,
9912 function_name, "can not supply data for depth or stencil textures");
9913 return false;
9915 if (data == NULL) {
9916 (*error) = error::kOutOfBounds;
9917 return false;
9919 return true;
9922 error::Error GLES2DecoderImpl::DoTexSubImage2D(
9923 GLenum target,
9924 GLint level,
9925 GLint xoffset,
9926 GLint yoffset,
9927 GLsizei width,
9928 GLsizei height,
9929 GLenum format,
9930 GLenum type,
9931 const void * data) {
9932 error::Error error = error::kNoError;
9933 if (!ValidateTexSubImage2D(&error, "glTexSubImage2D", target, level,
9934 xoffset, yoffset, width, height, format, type, data)) {
9935 return error;
9937 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9938 &state_, target);
9939 Texture* texture = texture_ref->texture();
9940 GLsizei tex_width = 0;
9941 GLsizei tex_height = 0;
9942 bool ok = texture->GetLevelSize(target, level, &tex_width, &tex_height);
9943 DCHECK(ok);
9944 if (xoffset != 0 || yoffset != 0 ||
9945 width != tex_width || height != tex_height) {
9946 if (!texture_manager()->ClearTextureLevel(this, texture_ref,
9947 target, level)) {
9948 LOCAL_SET_GL_ERROR(
9949 GL_OUT_OF_MEMORY, "glTexSubImage2D", "dimensions too big");
9950 return error::kNoError;
9952 ScopedTextureUploadTimer timer(&texture_state_);
9953 glTexSubImage2D(
9954 target, level, xoffset, yoffset, width, height, format, type, data);
9955 return error::kNoError;
9958 if (!texture_state_.texsubimage2d_faster_than_teximage2d &&
9959 !texture->IsImmutable() &&
9960 !texture->HasImages()) {
9961 ScopedTextureUploadTimer timer(&texture_state_);
9962 GLenum internal_format;
9963 GLenum tex_type;
9964 texture->GetLevelType(target, level, &tex_type, &internal_format);
9965 // NOTE: In OpenGL ES 2.0 border is always zero. If that changes we'll need
9966 // to look it up.
9967 glTexImage2D(
9968 target, level, internal_format, width, height, 0, format, type, data);
9969 } else {
9970 ScopedTextureUploadTimer timer(&texture_state_);
9971 glTexSubImage2D(
9972 target, level, xoffset, yoffset, width, height, format, type, data);
9974 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
9976 // This may be a slow command. Exit command processing to allow for
9977 // context preemption and GPU watchdog checks.
9978 ExitCommandProcessingEarly();
9979 return error::kNoError;
9982 error::Error GLES2DecoderImpl::HandleTexSubImage2D(uint32 immediate_data_size,
9983 const void* cmd_data) {
9984 const gles2::cmds::TexSubImage2D& c =
9985 *static_cast<const gles2::cmds::TexSubImage2D*>(cmd_data);
9986 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage2D",
9987 "width", c.width, "height", c.height);
9988 GLboolean internal = static_cast<GLboolean>(c.internal);
9989 if (internal == GL_TRUE && texture_state_.tex_image_2d_failed)
9990 return error::kNoError;
9992 GLenum target = static_cast<GLenum>(c.target);
9993 GLint level = static_cast<GLint>(c.level);
9994 GLint xoffset = static_cast<GLint>(c.xoffset);
9995 GLint yoffset = static_cast<GLint>(c.yoffset);
9996 GLsizei width = static_cast<GLsizei>(c.width);
9997 GLsizei height = static_cast<GLsizei>(c.height);
9998 GLenum format = static_cast<GLenum>(c.format);
9999 GLenum type = static_cast<GLenum>(c.type);
10000 uint32 data_size;
10001 if (!GLES2Util::ComputeImageDataSizes(
10002 width, height, 1, format, type, state_.unpack_alignment, &data_size,
10003 NULL, NULL)) {
10004 return error::kOutOfBounds;
10006 const void* pixels = GetSharedMemoryAs<const void*>(
10007 c.pixels_shm_id, c.pixels_shm_offset, data_size);
10008 return DoTexSubImage2D(
10009 target, level, xoffset, yoffset, width, height, format, type, pixels);
10012 // TODO(zmo): Remove the below stub once we add the real function binding.
10013 // Currently it's missing due to a gmock limitation.
10014 static void glTexSubImage3D(
10015 GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
10016 GLsizei height, GLsizei width, GLsizei depth, GLenum format, GLenum type,
10017 const void* pixels) {
10018 NOTIMPLEMENTED();
10021 error::Error GLES2DecoderImpl::HandleTexSubImage3D(uint32 immediate_data_size,
10022 const void* cmd_data) {
10023 // TODO(zmo): Unsafe ES3 API.
10024 if (!unsafe_es3_apis_enabled())
10025 return error::kUnknownCommand;
10027 const gles2::cmds::TexSubImage3D& c =
10028 *static_cast<const gles2::cmds::TexSubImage3D*>(cmd_data);
10029 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage3D",
10030 "widthXheight", c.width * c.height, "depth", c.depth);
10031 GLenum target = static_cast<GLenum>(c.target);
10032 GLint level = static_cast<GLint>(c.level);
10033 GLint xoffset = static_cast<GLint>(c.xoffset);
10034 GLint yoffset = static_cast<GLint>(c.yoffset);
10035 GLint zoffset = static_cast<GLint>(c.zoffset);
10036 GLsizei width = static_cast<GLsizei>(c.width);
10037 GLsizei height = static_cast<GLsizei>(c.height);
10038 GLsizei depth = static_cast<GLsizei>(c.depth);
10039 GLenum format = static_cast<GLenum>(c.format);
10040 GLenum type = static_cast<GLenum>(c.type);
10041 uint32 data_size;
10042 if (!GLES2Util::ComputeImageDataSizes(
10043 width, height, depth, format, type, state_.unpack_alignment, &data_size,
10044 NULL, NULL)) {
10045 return error::kOutOfBounds;
10047 const void* pixels = GetSharedMemoryAs<const void*>(
10048 c.pixels_shm_id, c.pixels_shm_offset, data_size);
10049 glTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height,
10050 depth, format, type, pixels);
10051 return error::kNoError;
10054 error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
10055 uint32 immediate_data_size,
10056 const void* cmd_data) {
10057 const gles2::cmds::GetVertexAttribPointerv& c =
10058 *static_cast<const gles2::cmds::GetVertexAttribPointerv*>(cmd_data);
10059 GLuint index = static_cast<GLuint>(c.index);
10060 GLenum pname = static_cast<GLenum>(c.pname);
10061 typedef cmds::GetVertexAttribPointerv::Result Result;
10062 Result* result = GetSharedMemoryAs<Result*>(
10063 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
10064 if (!result) {
10065 return error::kOutOfBounds;
10067 // Check that the client initialized the result.
10068 if (result->size != 0) {
10069 return error::kInvalidArguments;
10071 if (!validators_->vertex_pointer.IsValid(pname)) {
10072 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10073 "glGetVertexAttribPointerv", pname, "pname");
10074 return error::kNoError;
10076 if (index >= group_->max_vertex_attribs()) {
10077 LOCAL_SET_GL_ERROR(
10078 GL_INVALID_VALUE, "glGetVertexAttribPointerv", "index out of range.");
10079 return error::kNoError;
10081 result->SetNumResults(1);
10082 *result->GetData() =
10083 state_.vertex_attrib_manager->GetVertexAttrib(index)->offset();
10084 return error::kNoError;
10087 bool GLES2DecoderImpl::GetUniformSetup(GLuint program_id,
10088 GLint fake_location,
10089 uint32 shm_id,
10090 uint32 shm_offset,
10091 error::Error* error,
10092 GLint* real_location,
10093 GLuint* service_id,
10094 void** result_pointer,
10095 GLenum* result_type,
10096 GLsizei* result_size) {
10097 DCHECK(error);
10098 DCHECK(service_id);
10099 DCHECK(result_pointer);
10100 DCHECK(result_type);
10101 DCHECK(real_location);
10102 *error = error::kNoError;
10103 // Make sure we have enough room for the result on failure.
10104 SizedResult<GLint>* result;
10105 result = GetSharedMemoryAs<SizedResult<GLint>*>(
10106 shm_id, shm_offset, SizedResult<GLint>::ComputeSize(0));
10107 if (!result) {
10108 *error = error::kOutOfBounds;
10109 return false;
10111 *result_pointer = result;
10112 // Set the result size to 0 so the client does not have to check for success.
10113 result->SetNumResults(0);
10114 Program* program = GetProgramInfoNotShader(program_id, "glGetUniform");
10115 if (!program) {
10116 return false;
10118 if (!program->IsValid()) {
10119 // Program was not linked successfully. (ie, glLinkProgram)
10120 LOCAL_SET_GL_ERROR(
10121 GL_INVALID_OPERATION, "glGetUniform", "program not linked");
10122 return false;
10124 *service_id = program->service_id();
10125 GLint array_index = -1;
10126 const Program::UniformInfo* uniform_info =
10127 program->GetUniformInfoByFakeLocation(
10128 fake_location, real_location, &array_index);
10129 if (!uniform_info) {
10130 // No such location.
10131 LOCAL_SET_GL_ERROR(
10132 GL_INVALID_OPERATION, "glGetUniform", "unknown location");
10133 return false;
10135 GLenum type = uniform_info->type;
10136 GLsizei size = GLES2Util::GetGLDataTypeSizeForUniforms(type);
10137 if (size == 0) {
10138 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glGetUniform", "unknown type");
10139 return false;
10141 result = GetSharedMemoryAs<SizedResult<GLint>*>(
10142 shm_id, shm_offset, SizedResult<GLint>::ComputeSizeFromBytes(size));
10143 if (!result) {
10144 *error = error::kOutOfBounds;
10145 return false;
10147 result->size = size;
10148 *result_size = size;
10149 *result_type = type;
10150 return true;
10153 error::Error GLES2DecoderImpl::HandleGetUniformiv(uint32 immediate_data_size,
10154 const void* cmd_data) {
10155 const gles2::cmds::GetUniformiv& c =
10156 *static_cast<const gles2::cmds::GetUniformiv*>(cmd_data);
10157 GLuint program = c.program;
10158 GLint fake_location = c.location;
10159 GLuint service_id;
10160 GLenum result_type;
10161 GLsizei result_size;
10162 GLint real_location = -1;
10163 Error error;
10164 void* result;
10165 if (GetUniformSetup(program, fake_location, c.params_shm_id,
10166 c.params_shm_offset, &error, &real_location, &service_id,
10167 &result, &result_type, &result_size)) {
10168 glGetUniformiv(
10169 service_id, real_location,
10170 static_cast<cmds::GetUniformiv::Result*>(result)->GetData());
10172 return error;
10175 error::Error GLES2DecoderImpl::HandleGetUniformfv(uint32 immediate_data_size,
10176 const void* cmd_data) {
10177 const gles2::cmds::GetUniformfv& c =
10178 *static_cast<const gles2::cmds::GetUniformfv*>(cmd_data);
10179 GLuint program = c.program;
10180 GLint fake_location = c.location;
10181 GLuint service_id;
10182 GLint real_location = -1;
10183 Error error;
10184 typedef cmds::GetUniformfv::Result Result;
10185 Result* result;
10186 GLenum result_type;
10187 GLsizei result_size;
10188 if (GetUniformSetup(program, fake_location, c.params_shm_id,
10189 c.params_shm_offset, &error, &real_location, &service_id,
10190 reinterpret_cast<void**>(&result), &result_type,
10191 &result_size)) {
10192 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
10193 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
10194 GLsizei num_values = result_size / sizeof(Result::Type);
10195 scoped_ptr<GLint[]> temp(new GLint[num_values]);
10196 glGetUniformiv(service_id, real_location, temp.get());
10197 GLfloat* dst = result->GetData();
10198 for (GLsizei ii = 0; ii < num_values; ++ii) {
10199 dst[ii] = (temp[ii] != 0);
10201 } else {
10202 glGetUniformfv(service_id, real_location, result->GetData());
10205 return error;
10208 error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
10209 uint32 immediate_data_size,
10210 const void* cmd_data) {
10211 const gles2::cmds::GetShaderPrecisionFormat& c =
10212 *static_cast<const gles2::cmds::GetShaderPrecisionFormat*>(cmd_data);
10213 GLenum shader_type = static_cast<GLenum>(c.shadertype);
10214 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
10215 typedef cmds::GetShaderPrecisionFormat::Result Result;
10216 Result* result = GetSharedMemoryAs<Result*>(
10217 c.result_shm_id, c.result_shm_offset, sizeof(*result));
10218 if (!result) {
10219 return error::kOutOfBounds;
10221 // Check that the client initialized the result.
10222 if (result->success != 0) {
10223 return error::kInvalidArguments;
10225 if (!validators_->shader_type.IsValid(shader_type)) {
10226 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10227 "glGetShaderPrecisionFormat", shader_type, "shader_type");
10228 return error::kNoError;
10230 if (!validators_->shader_precision.IsValid(precision_type)) {
10231 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10232 "glGetShaderPrecisionFormat", precision_type, "precision_type");
10233 return error::kNoError;
10236 result->success = 1; // true
10238 GLint range[2] = { 0, 0 };
10239 GLint precision = 0;
10240 GetShaderPrecisionFormatImpl(shader_type, precision_type, range, &precision);
10242 result->min_range = range[0];
10243 result->max_range = range[1];
10244 result->precision = precision;
10246 return error::kNoError;
10249 error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
10250 uint32 immediate_data_size,
10251 const void* cmd_data) {
10252 const gles2::cmds::GetAttachedShaders& c =
10253 *static_cast<const gles2::cmds::GetAttachedShaders*>(cmd_data);
10254 uint32 result_size = c.result_size;
10255 GLuint program_id = static_cast<GLuint>(c.program);
10256 Program* program = GetProgramInfoNotShader(
10257 program_id, "glGetAttachedShaders");
10258 if (!program) {
10259 return error::kNoError;
10261 typedef cmds::GetAttachedShaders::Result Result;
10262 uint32 max_count = Result::ComputeMaxResults(result_size);
10263 Result* result = GetSharedMemoryAs<Result*>(
10264 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
10265 if (!result) {
10266 return error::kOutOfBounds;
10268 // Check that the client initialized the result.
10269 if (result->size != 0) {
10270 return error::kInvalidArguments;
10272 GLsizei count = 0;
10273 glGetAttachedShaders(
10274 program->service_id(), max_count, &count, result->GetData());
10275 for (GLsizei ii = 0; ii < count; ++ii) {
10276 if (!shader_manager()->GetClientId(result->GetData()[ii],
10277 &result->GetData()[ii])) {
10278 NOTREACHED();
10279 return error::kGenericError;
10282 result->SetNumResults(count);
10283 return error::kNoError;
10286 error::Error GLES2DecoderImpl::HandleGetActiveUniform(
10287 uint32 immediate_data_size,
10288 const void* cmd_data) {
10289 const gles2::cmds::GetActiveUniform& c =
10290 *static_cast<const gles2::cmds::GetActiveUniform*>(cmd_data);
10291 GLuint program_id = c.program;
10292 GLuint index = c.index;
10293 uint32 name_bucket_id = c.name_bucket_id;
10294 typedef cmds::GetActiveUniform::Result Result;
10295 Result* result = GetSharedMemoryAs<Result*>(
10296 c.result_shm_id, c.result_shm_offset, sizeof(*result));
10297 if (!result) {
10298 return error::kOutOfBounds;
10300 // Check that the client initialized the result.
10301 if (result->success != 0) {
10302 return error::kInvalidArguments;
10304 Program* program = GetProgramInfoNotShader(
10305 program_id, "glGetActiveUniform");
10306 if (!program) {
10307 return error::kNoError;
10309 const Program::UniformInfo* uniform_info =
10310 program->GetUniformInfo(index);
10311 if (!uniform_info) {
10312 LOCAL_SET_GL_ERROR(
10313 GL_INVALID_VALUE, "glGetActiveUniform", "index out of range");
10314 return error::kNoError;
10316 result->success = 1; // true.
10317 result->size = uniform_info->size;
10318 result->type = uniform_info->type;
10319 Bucket* bucket = CreateBucket(name_bucket_id);
10320 bucket->SetFromString(uniform_info->name.c_str());
10321 return error::kNoError;
10324 error::Error GLES2DecoderImpl::HandleGetActiveUniformBlockiv(
10325 uint32 immediate_data_size, const void* cmd_data) {
10326 if (!unsafe_es3_apis_enabled())
10327 return error::kUnknownCommand;
10328 const gles2::cmds::GetActiveUniformBlockiv& c =
10329 *static_cast<const gles2::cmds::GetActiveUniformBlockiv*>(cmd_data);
10330 GLuint program_id = c.program;
10331 GLuint index = static_cast<GLuint>(c.index);
10332 GLenum pname = static_cast<GLenum>(c.pname);
10333 Program* program = GetProgramInfoNotShader(
10334 program_id, "glGetActiveUniformBlockiv");
10335 if (!program) {
10336 return error::kNoError;
10338 GLuint service_id = program->service_id();
10339 GLint link_status = GL_FALSE;
10340 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
10341 if (link_status != GL_TRUE) {
10342 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10343 "glGetActiveActiveUniformBlockiv", "program not linked");
10344 return error::kNoError;
10346 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetActiveUniformBlockiv");
10347 GLsizei num_values = 1;
10348 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES) {
10349 GLint num = 0;
10350 glGetActiveUniformBlockiv(
10351 service_id, index, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &num);
10352 GLenum error = glGetError();
10353 if (error != GL_NO_ERROR) {
10354 // Assume this will the same error if calling with pname.
10355 LOCAL_SET_GL_ERROR(error, "GetActiveUniformBlockiv", "");
10356 return error::kNoError;
10358 num_values = static_cast<GLsizei>(num);
10360 typedef cmds::GetActiveUniformBlockiv::Result Result;
10361 Result* result = GetSharedMemoryAs<Result*>(
10362 c.params_shm_id, c.params_shm_offset, Result::ComputeSize(num_values));
10363 GLint* params = result ? result->GetData() : NULL;
10364 if (params == NULL) {
10365 return error::kOutOfBounds;
10367 // Check that the client initialized the result.
10368 if (result->size != 0) {
10369 return error::kInvalidArguments;
10371 glGetActiveUniformBlockiv(service_id, index, pname, params);
10372 GLenum error = glGetError();
10373 if (error == GL_NO_ERROR) {
10374 result->SetNumResults(num_values);
10375 } else {
10376 LOCAL_SET_GL_ERROR(error, "GetActiveUniformBlockiv", "");
10378 return error::kNoError;
10381 error::Error GLES2DecoderImpl::HandleGetActiveUniformBlockName(
10382 uint32 immediate_data_size, const void* cmd_data) {
10383 if (!unsafe_es3_apis_enabled())
10384 return error::kUnknownCommand;
10385 const gles2::cmds::GetActiveUniformBlockName& c =
10386 *static_cast<const gles2::cmds::GetActiveUniformBlockName*>(cmd_data);
10387 GLuint program_id = c.program;
10388 GLuint index = c.index;
10389 uint32 name_bucket_id = c.name_bucket_id;
10390 typedef cmds::GetActiveUniformBlockName::Result Result;
10391 Result* result = GetSharedMemoryAs<Result*>(
10392 c.result_shm_id, c.result_shm_offset, sizeof(*result));
10393 if (!result) {
10394 return error::kOutOfBounds;
10396 // Check that the client initialized the result.
10397 if (*result != 0) {
10398 return error::kInvalidArguments;
10400 Program* program = GetProgramInfoNotShader(
10401 program_id, "glGetActiveUniformBlockName");
10402 if (!program) {
10403 return error::kNoError;
10405 GLuint service_id = program->service_id();
10406 GLint link_status = GL_FALSE;
10407 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
10408 if (link_status != GL_TRUE) {
10409 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10410 "glGetActiveActiveUniformBlockName", "program not linked");
10411 return error::kNoError;
10413 GLint max_length = 0;
10414 glGetProgramiv(
10415 service_id, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &max_length);
10416 // Increase one so &buffer[0] is always valid.
10417 GLsizei buf_size = static_cast<GLsizei>(max_length) + 1;
10418 std::vector<char> buffer(buf_size);
10419 GLsizei length = 0;
10420 glGetActiveUniformBlockName(
10421 service_id, index, buf_size, &length, &buffer[0]);
10422 if (length == 0) {
10423 *result = 0;
10424 return error::kNoError;
10426 *result = 1;
10427 Bucket* bucket = CreateBucket(name_bucket_id);
10428 DCHECK_GT(buf_size, length);
10429 DCHECK_EQ(0, buffer[length]);
10430 bucket->SetFromString(&buffer[0]);
10431 return error::kNoError;
10434 error::Error GLES2DecoderImpl::HandleGetActiveUniformsiv(
10435 uint32 immediate_data_size, const void* cmd_data) {
10436 if (!unsafe_es3_apis_enabled())
10437 return error::kUnknownCommand;
10438 const gles2::cmds::GetActiveUniformsiv& c =
10439 *static_cast<const gles2::cmds::GetActiveUniformsiv*>(cmd_data);
10440 GLuint program_id = c.program;
10441 GLenum pname = static_cast<GLenum>(c.pname);
10442 Bucket* bucket = GetBucket(c.indices_bucket_id);
10443 if (!bucket) {
10444 return error::kInvalidArguments;
10446 GLsizei count = static_cast<GLsizei>(bucket->size() / sizeof(GLuint));
10447 const GLuint* indices = bucket->GetDataAs<const GLuint*>(0, bucket->size());
10448 typedef cmds::GetActiveUniformsiv::Result Result;
10449 Result* result = GetSharedMemoryAs<Result*>(
10450 c.params_shm_id, c.params_shm_offset, Result::ComputeSize(count));
10451 GLint* params = result ? result->GetData() : NULL;
10452 if (params == NULL) {
10453 return error::kOutOfBounds;
10455 // Check that the client initialized the result.
10456 if (result->size != 0) {
10457 return error::kInvalidArguments;
10459 Program* program = GetProgramInfoNotShader(
10460 program_id, "glGetActiveUniformsiv");
10461 if (!program) {
10462 return error::kNoError;
10464 GLuint service_id = program->service_id();
10465 GLint link_status = GL_FALSE;
10466 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
10467 if (link_status != GL_TRUE) {
10468 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10469 "glGetActiveUniformsiv", "program not linked");
10470 return error::kNoError;
10472 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetActiveUniformsiv");
10473 glGetActiveUniformsiv(service_id, count, indices, pname, params);
10474 GLenum error = glGetError();
10475 if (error == GL_NO_ERROR) {
10476 result->SetNumResults(count);
10477 } else {
10478 LOCAL_SET_GL_ERROR(error, "GetActiveUniformsiv", "");
10480 return error::kNoError;
10483 error::Error GLES2DecoderImpl::HandleGetActiveAttrib(uint32 immediate_data_size,
10484 const void* cmd_data) {
10485 const gles2::cmds::GetActiveAttrib& c =
10486 *static_cast<const gles2::cmds::GetActiveAttrib*>(cmd_data);
10487 GLuint program_id = c.program;
10488 GLuint index = c.index;
10489 uint32 name_bucket_id = c.name_bucket_id;
10490 typedef cmds::GetActiveAttrib::Result Result;
10491 Result* result = GetSharedMemoryAs<Result*>(
10492 c.result_shm_id, c.result_shm_offset, sizeof(*result));
10493 if (!result) {
10494 return error::kOutOfBounds;
10496 // Check that the client initialized the result.
10497 if (result->success != 0) {
10498 return error::kInvalidArguments;
10500 Program* program = GetProgramInfoNotShader(
10501 program_id, "glGetActiveAttrib");
10502 if (!program) {
10503 return error::kNoError;
10505 const Program::VertexAttrib* attrib_info =
10506 program->GetAttribInfo(index);
10507 if (!attrib_info) {
10508 LOCAL_SET_GL_ERROR(
10509 GL_INVALID_VALUE, "glGetActiveAttrib", "index out of range");
10510 return error::kNoError;
10512 result->success = 1; // true.
10513 result->size = attrib_info->size;
10514 result->type = attrib_info->type;
10515 Bucket* bucket = CreateBucket(name_bucket_id);
10516 bucket->SetFromString(attrib_info->name.c_str());
10517 return error::kNoError;
10520 error::Error GLES2DecoderImpl::HandleShaderBinary(uint32 immediate_data_size,
10521 const void* cmd_data) {
10522 #if 1 // No binary shader support.
10523 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glShaderBinary", "not supported");
10524 return error::kNoError;
10525 #else
10526 GLsizei n = static_cast<GLsizei>(c.n);
10527 if (n < 0) {
10528 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "n < 0");
10529 return error::kNoError;
10531 GLsizei length = static_cast<GLsizei>(c.length);
10532 if (length < 0) {
10533 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "length < 0");
10534 return error::kNoError;
10536 uint32 data_size;
10537 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
10538 return error::kOutOfBounds;
10540 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
10541 c.shaders_shm_id, c.shaders_shm_offset, data_size);
10542 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
10543 const void* binary = GetSharedMemoryAs<const void*>(
10544 c.binary_shm_id, c.binary_shm_offset, length);
10545 if (shaders == NULL || binary == NULL) {
10546 return error::kOutOfBounds;
10548 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
10549 for (GLsizei ii = 0; ii < n; ++ii) {
10550 Shader* shader = GetShader(shaders[ii]);
10551 if (!shader) {
10552 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "unknown shader");
10553 return error::kNoError;
10555 service_ids[ii] = shader->service_id();
10557 // TODO(gman): call glShaderBinary
10558 return error::kNoError;
10559 #endif
10562 void GLES2DecoderImpl::DoSwapBuffers() {
10563 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
10565 int this_frame_number = frame_number_++;
10566 // TRACE_EVENT for gpu tests:
10567 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffersLatency",
10568 TRACE_EVENT_SCOPE_THREAD,
10569 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
10570 "width", (is_offscreen ? offscreen_size_.width() :
10571 surface_->GetSize().width()));
10572 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoSwapBuffers",
10573 "offscreen", is_offscreen,
10574 "frame", this_frame_number);
10576 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
10579 ScopedGPUTrace scoped_gpu_trace(gpu_tracer_.get(), kTraceDecoder,
10580 "gpu_toplevel", "SwapBuffer");
10582 bool is_tracing;
10583 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
10584 &is_tracing);
10585 if (is_tracing) {
10586 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
10587 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
10588 is_offscreen ? offscreen_size_ : surface_->GetSize());
10591 // If offscreen then don't actually SwapBuffers to the display. Just copy
10592 // the rendered frame to another frame buffer.
10593 if (is_offscreen) {
10594 TRACE_EVENT2("gpu", "Offscreen",
10595 "width", offscreen_size_.width(), "height", offscreen_size_.height());
10596 if (offscreen_size_ != offscreen_saved_color_texture_->size()) {
10597 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
10598 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
10599 // fix this.
10600 if (workarounds().needs_offscreen_buffer_workaround) {
10601 offscreen_saved_frame_buffer_->Create();
10602 glFinish();
10605 // Allocate the offscreen saved color texture.
10606 DCHECK(offscreen_saved_color_format_);
10607 offscreen_saved_color_texture_->AllocateStorage(
10608 offscreen_size_, offscreen_saved_color_format_, false);
10610 offscreen_saved_frame_buffer_->AttachRenderTexture(
10611 offscreen_saved_color_texture_.get());
10612 if (offscreen_size_.width() != 0 && offscreen_size_.height() != 0) {
10613 if (offscreen_saved_frame_buffer_->CheckStatus() !=
10614 GL_FRAMEBUFFER_COMPLETE) {
10615 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
10616 << "because offscreen saved FBO was incomplete.";
10617 MarkContextLost(error::kUnknown);
10618 group_->LoseContexts(error::kUnknown);
10619 return;
10622 // Clear the offscreen color texture.
10623 // TODO(piman): Is this still necessary?
10625 ScopedFrameBufferBinder binder(this,
10626 offscreen_saved_frame_buffer_->id());
10627 glClearColor(0, 0, 0, 0);
10628 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
10629 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
10630 glClear(GL_COLOR_BUFFER_BIT);
10631 RestoreClearState();
10635 UpdateParentTextureInfo();
10638 if (offscreen_size_.width() == 0 || offscreen_size_.height() == 0)
10639 return;
10640 ScopedGLErrorSuppressor suppressor(
10641 "GLES2DecoderImpl::DoSwapBuffers", GetErrorState());
10643 if (IsOffscreenBufferMultisampled()) {
10644 // For multisampled buffers, resolve the frame buffer.
10645 ScopedResolvedFrameBufferBinder binder(this, true, false);
10646 } else {
10647 ScopedFrameBufferBinder binder(this,
10648 offscreen_target_frame_buffer_->id());
10650 if (offscreen_target_buffer_preserved_) {
10651 // Copy the target frame buffer to the saved offscreen texture.
10652 offscreen_saved_color_texture_->Copy(
10653 offscreen_saved_color_texture_->size(),
10654 offscreen_saved_color_format_);
10655 } else {
10656 // Flip the textures in the parent context via the texture manager.
10657 if (!!offscreen_saved_color_texture_info_.get())
10658 offscreen_saved_color_texture_info_->texture()->
10659 SetServiceId(offscreen_target_color_texture_->id());
10661 offscreen_saved_color_texture_.swap(offscreen_target_color_texture_);
10662 offscreen_target_frame_buffer_->AttachRenderTexture(
10663 offscreen_target_color_texture_.get());
10666 // Ensure the side effects of the copy are visible to the parent
10667 // context. There is no need to do this for ANGLE because it uses a
10668 // single D3D device for all contexts.
10669 if (!feature_info_->gl_version_info().is_angle)
10670 glFlush();
10672 } else {
10673 if (!surface_->SwapBuffers()) {
10674 LOG(ERROR) << "Context lost because SwapBuffers failed.";
10675 if (!CheckResetStatus()) {
10676 MarkContextLost(error::kUnknown);
10677 group_->LoseContexts(error::kUnknown);
10682 // This may be a slow command. Exit command processing to allow for
10683 // context preemption and GPU watchdog checks.
10684 ExitCommandProcessingEarly();
10687 void GLES2DecoderImpl::DoSwapInterval(int interval) {
10688 context_->SetSwapInterval(interval);
10691 error::Error GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
10692 uint32 immediate_data_size,
10693 const void* cmd_data) {
10694 const gles2::cmds::EnableFeatureCHROMIUM& c =
10695 *static_cast<const gles2::cmds::EnableFeatureCHROMIUM*>(cmd_data);
10696 Bucket* bucket = GetBucket(c.bucket_id);
10697 if (!bucket || bucket->size() == 0) {
10698 return error::kInvalidArguments;
10700 typedef cmds::EnableFeatureCHROMIUM::Result Result;
10701 Result* result = GetSharedMemoryAs<Result*>(
10702 c.result_shm_id, c.result_shm_offset, sizeof(*result));
10703 if (!result) {
10704 return error::kOutOfBounds;
10706 // Check that the client initialized the result.
10707 if (*result != 0) {
10708 return error::kInvalidArguments;
10710 std::string feature_str;
10711 if (!bucket->GetAsString(&feature_str)) {
10712 return error::kInvalidArguments;
10715 // TODO(gman): make this some kind of table to function pointer thingy.
10716 if (feature_str.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
10717 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
10718 } else if (feature_str.compare("pepper3d_support_fixed_attribs") == 0) {
10719 buffer_manager()->set_allow_fixed_attribs(true);
10720 // TODO(gman): decide how to remove the need for this const_cast.
10721 // I could make validators_ non const but that seems bad as this is the only
10722 // place it is needed. I could make some special friend class of validators
10723 // just to allow this to set them. That seems silly. I could refactor this
10724 // code to use the extension mechanism or the initialization attributes to
10725 // turn this feature on. Given that the only real point of this is to make
10726 // the conformance tests pass and given that there is lots of real work that
10727 // needs to be done it seems like refactoring for one to one of those
10728 // methods is a very low priority.
10729 const_cast<Validators*>(validators_)->vertex_attrib_type.AddValue(GL_FIXED);
10730 } else if (feature_str.compare("webgl_enable_glsl_webgl_validation") == 0) {
10731 force_webgl_glsl_validation_ = true;
10732 InitializeShaderTranslator();
10733 } else {
10734 return error::kNoError;
10737 *result = 1; // true.
10738 return error::kNoError;
10741 error::Error GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
10742 uint32 immediate_data_size,
10743 const void* cmd_data) {
10744 const gles2::cmds::GetRequestableExtensionsCHROMIUM& c =
10745 *static_cast<const gles2::cmds::GetRequestableExtensionsCHROMIUM*>(
10746 cmd_data);
10747 Bucket* bucket = CreateBucket(c.bucket_id);
10748 scoped_refptr<FeatureInfo> info(new FeatureInfo());
10749 info->Initialize(disallowed_features_);
10750 bucket->SetFromString(info->extensions().c_str());
10751 return error::kNoError;
10754 error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
10755 uint32 immediate_data_size,
10756 const void* cmd_data) {
10757 const gles2::cmds::RequestExtensionCHROMIUM& c =
10758 *static_cast<const gles2::cmds::RequestExtensionCHROMIUM*>(cmd_data);
10759 Bucket* bucket = GetBucket(c.bucket_id);
10760 if (!bucket || bucket->size() == 0) {
10761 return error::kInvalidArguments;
10763 std::string feature_str;
10764 if (!bucket->GetAsString(&feature_str)) {
10765 return error::kInvalidArguments;
10768 bool desire_webgl_glsl_validation =
10769 feature_str.find("GL_CHROMIUM_webglsl") != std::string::npos;
10770 bool desire_standard_derivatives = false;
10771 bool desire_frag_depth = false;
10772 bool desire_draw_buffers = false;
10773 bool desire_shader_texture_lod = false;
10774 if (force_webgl_glsl_validation_) {
10775 desire_standard_derivatives =
10776 feature_str.find("GL_OES_standard_derivatives") != std::string::npos;
10777 desire_frag_depth =
10778 feature_str.find("GL_EXT_frag_depth") != std::string::npos;
10779 desire_draw_buffers =
10780 feature_str.find("GL_EXT_draw_buffers") != std::string::npos;
10781 desire_shader_texture_lod =
10782 feature_str.find("GL_EXT_shader_texture_lod") != std::string::npos;
10785 if (desire_webgl_glsl_validation != force_webgl_glsl_validation_ ||
10786 desire_standard_derivatives != derivatives_explicitly_enabled_ ||
10787 desire_frag_depth != frag_depth_explicitly_enabled_ ||
10788 desire_draw_buffers != draw_buffers_explicitly_enabled_) {
10789 force_webgl_glsl_validation_ |= desire_webgl_glsl_validation;
10790 derivatives_explicitly_enabled_ |= desire_standard_derivatives;
10791 frag_depth_explicitly_enabled_ |= desire_frag_depth;
10792 draw_buffers_explicitly_enabled_ |= desire_draw_buffers;
10793 shader_texture_lod_explicitly_enabled_ |= desire_shader_texture_lod;
10794 InitializeShaderTranslator();
10797 UpdateCapabilities();
10799 return error::kNoError;
10802 error::Error GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
10803 uint32 immediate_data_size,
10804 const void* cmd_data) {
10805 const gles2::cmds::GetProgramInfoCHROMIUM& c =
10806 *static_cast<const gles2::cmds::GetProgramInfoCHROMIUM*>(cmd_data);
10807 GLuint program_id = static_cast<GLuint>(c.program);
10808 uint32 bucket_id = c.bucket_id;
10809 Bucket* bucket = CreateBucket(bucket_id);
10810 bucket->SetSize(sizeof(ProgramInfoHeader)); // in case we fail.
10811 Program* program = NULL;
10812 program = GetProgram(program_id);
10813 if (!program || !program->IsValid()) {
10814 return error::kNoError;
10816 program->GetProgramInfo(program_manager(), bucket);
10817 return error::kNoError;
10820 error::Error GLES2DecoderImpl::HandleGetUniformBlocksCHROMIUM(
10821 uint32 immediate_data_size, const void* cmd_data) {
10822 if (!unsafe_es3_apis_enabled())
10823 return error::kUnknownCommand;
10824 const gles2::cmds::GetUniformBlocksCHROMIUM& c =
10825 *static_cast<const gles2::cmds::GetUniformBlocksCHROMIUM*>(cmd_data);
10826 GLuint program_id = static_cast<GLuint>(c.program);
10827 uint32 bucket_id = c.bucket_id;
10828 Bucket* bucket = CreateBucket(bucket_id);
10829 bucket->SetSize(sizeof(UniformBlocksHeader)); // in case we fail.
10830 Program* program = NULL;
10831 program = GetProgram(program_id);
10832 if (!program || !program->IsValid()) {
10833 return error::kNoError;
10835 program->GetUniformBlocks(bucket);
10836 return error::kNoError;
10839 error::Error GLES2DecoderImpl::HandleGetUniformsES3CHROMIUM(
10840 uint32 immediate_data_size, const void* cmd_data) {
10841 if (!unsafe_es3_apis_enabled())
10842 return error::kUnknownCommand;
10843 const gles2::cmds::GetUniformsES3CHROMIUM& c =
10844 *static_cast<const gles2::cmds::GetUniformsES3CHROMIUM*>(cmd_data);
10845 GLuint program_id = static_cast<GLuint>(c.program);
10846 uint32 bucket_id = c.bucket_id;
10847 Bucket* bucket = CreateBucket(bucket_id);
10848 bucket->SetSize(sizeof(UniformsES3Header)); // in case we fail.
10849 Program* program = NULL;
10850 program = GetProgram(program_id);
10851 if (!program || !program->IsValid()) {
10852 return error::kNoError;
10854 program->GetUniformsES3(bucket);
10855 return error::kNoError;
10858 error::Error GLES2DecoderImpl::HandleGetTransformFeedbackVarying(
10859 uint32 immediate_data_size,
10860 const void* cmd_data) {
10861 if (!unsafe_es3_apis_enabled())
10862 return error::kUnknownCommand;
10863 const gles2::cmds::GetTransformFeedbackVarying& c =
10864 *static_cast<const gles2::cmds::GetTransformFeedbackVarying*>(cmd_data);
10865 GLuint program_id = c.program;
10866 GLuint index = c.index;
10867 uint32 name_bucket_id = c.name_bucket_id;
10868 typedef cmds::GetTransformFeedbackVarying::Result Result;
10869 Result* result = GetSharedMemoryAs<Result*>(
10870 c.result_shm_id, c.result_shm_offset, sizeof(*result));
10871 if (!result) {
10872 return error::kOutOfBounds;
10874 // Check that the client initialized the result.
10875 if (result->success != 0) {
10876 return error::kInvalidArguments;
10878 Program* program = GetProgramInfoNotShader(
10879 program_id, "glGetTransformFeedbackVarying");
10880 if (!program) {
10881 return error::kNoError;
10883 GLuint service_id = program->service_id();
10884 GLint link_status = GL_FALSE;
10885 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
10886 if (link_status != GL_TRUE) {
10887 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10888 "glGetTransformFeedbackVarying", "program not linked");
10889 return error::kNoError;
10891 GLint max_length = 0;
10892 glGetProgramiv(
10893 service_id, GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH, &max_length);
10894 max_length = std::max(1, max_length);
10895 std::vector<char> buffer(max_length);
10896 GLsizei length = 0;
10897 GLsizei size = 0;
10898 GLenum type = 0;
10899 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetTransformFeedbackVarying");
10900 glGetTransformFeedbackVarying(
10901 service_id, index, max_length, &length, &size, &type, &buffer[0]);
10902 GLenum error = glGetError();
10903 if (error != GL_NO_ERROR) {
10904 LOCAL_SET_GL_ERROR(error, "glGetTransformFeedbackVarying", "");
10905 return error::kNoError;
10907 result->success = 1; // true.
10908 result->size = static_cast<int32_t>(size);
10909 result->type = static_cast<uint32_t>(type);
10910 Bucket* bucket = CreateBucket(name_bucket_id);
10911 DCHECK(length >= 0 && length < max_length);
10912 buffer[length] = '\0'; // Just to be safe.
10913 bucket->SetFromString(&buffer[0]);
10914 return error::kNoError;
10917 error::Error GLES2DecoderImpl::HandleGetTransformFeedbackVaryingsCHROMIUM(
10918 uint32 immediate_data_size, const void* cmd_data) {
10919 if (!unsafe_es3_apis_enabled())
10920 return error::kUnknownCommand;
10921 const gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM& c =
10922 *static_cast<const gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM*>(
10923 cmd_data);
10924 GLuint program_id = static_cast<GLuint>(c.program);
10925 uint32 bucket_id = c.bucket_id;
10926 Bucket* bucket = CreateBucket(bucket_id);
10927 bucket->SetSize(sizeof(TransformFeedbackVaryingsHeader)); // in case we fail.
10928 Program* program = NULL;
10929 program = GetProgram(program_id);
10930 if (!program || !program->IsValid()) {
10931 return error::kNoError;
10933 program->GetTransformFeedbackVaryings(bucket);
10934 return error::kNoError;
10937 error::ContextLostReason GLES2DecoderImpl::GetContextLostReason() {
10938 return context_lost_reason_;
10941 error::ContextLostReason GLES2DecoderImpl::GetContextLostReasonFromResetStatus(
10942 GLenum reset_status) const {
10943 switch (reset_status) {
10944 case GL_NO_ERROR:
10945 // TODO(kbr): improve the precision of the error code in this case.
10946 // Consider delegating to context for error code if MakeCurrent fails.
10947 return error::kUnknown;
10948 case GL_GUILTY_CONTEXT_RESET_ARB:
10949 return error::kGuilty;
10950 case GL_INNOCENT_CONTEXT_RESET_ARB:
10951 return error::kInnocent;
10952 case GL_UNKNOWN_CONTEXT_RESET_ARB:
10953 return error::kUnknown;
10956 NOTREACHED();
10957 return error::kUnknown;
10960 bool GLES2DecoderImpl::WasContextLost() const {
10961 return context_was_lost_;
10964 bool GLES2DecoderImpl::WasContextLostByRobustnessExtension() const {
10965 return WasContextLost() && reset_by_robustness_extension_;
10968 void GLES2DecoderImpl::MarkContextLost(error::ContextLostReason reason) {
10969 // Only lose the context once.
10970 if (WasContextLost())
10971 return;
10973 // Don't make GL calls in here, the context might not be current.
10974 context_lost_reason_ = reason;
10975 current_decoder_error_ = error::kLostContext;
10976 context_was_lost_ = true;
10978 // Some D3D drivers cannot recover from device lost in the GPU process
10979 // sandbox. Allow a new GPU process to launch.
10980 if (workarounds().exit_on_context_lost) {
10981 LOG(ERROR) << "Exiting GPU process because some drivers cannot reset"
10982 << " a D3D device in the Chrome GPU process sandbox.";
10983 #if defined(OS_WIN)
10984 base::win::SetShouldCrashOnProcessDetach(false);
10985 #endif
10986 exit(0);
10990 bool GLES2DecoderImpl::CheckResetStatus() {
10991 DCHECK(!WasContextLost());
10992 DCHECK(context_->IsCurrent(NULL));
10994 if (IsRobustnessSupported()) {
10995 // If the reason for the call was a GL error, we can try to determine the
10996 // reset status more accurately.
10997 GLenum driver_status = glGetGraphicsResetStatusARB();
10998 if (driver_status == GL_NO_ERROR)
10999 return false;
11001 LOG(ERROR) << (surface_->IsOffscreen() ? "Offscreen" : "Onscreen")
11002 << " context lost via ARB/EXT_robustness. Reset status = "
11003 << GLES2Util::GetStringEnum(driver_status);
11005 // Don't pretend we know which client was responsible.
11006 if (workarounds().use_virtualized_gl_contexts)
11007 driver_status = GL_UNKNOWN_CONTEXT_RESET_ARB;
11009 switch (driver_status) {
11010 case GL_GUILTY_CONTEXT_RESET_ARB:
11011 MarkContextLost(error::kGuilty);
11012 break;
11013 case GL_INNOCENT_CONTEXT_RESET_ARB:
11014 MarkContextLost(error::kInnocent);
11015 break;
11016 case GL_UNKNOWN_CONTEXT_RESET_ARB:
11017 MarkContextLost(error::kUnknown);
11018 break;
11019 default:
11020 NOTREACHED();
11021 return false;
11023 reset_by_robustness_extension_ = true;
11024 return true;
11026 return false;
11029 error::Error GLES2DecoderImpl::HandleInsertSyncPointCHROMIUM(
11030 uint32 immediate_data_size,
11031 const void* cmd_data) {
11032 return error::kUnknownCommand;
11035 error::Error GLES2DecoderImpl::HandleWaitSyncPointCHROMIUM(
11036 uint32 immediate_data_size,
11037 const void* cmd_data) {
11038 const gles2::cmds::WaitSyncPointCHROMIUM& c =
11039 *static_cast<const gles2::cmds::WaitSyncPointCHROMIUM*>(cmd_data);
11040 uint32 sync_point = c.sync_point;
11041 if (wait_sync_point_callback_.is_null())
11042 return error::kNoError;
11044 return wait_sync_point_callback_.Run(sync_point) ?
11045 error::kNoError : error::kDeferCommandUntilLater;
11048 error::Error GLES2DecoderImpl::HandleDiscardBackbufferCHROMIUM(
11049 uint32 immediate_data_size,
11050 const void* cmd_data) {
11051 if (surface_->DeferDraws())
11052 return error::kDeferCommandUntilLater;
11053 if (!surface_->SetBackbufferAllocation(false))
11054 return error::kLostContext;
11055 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
11056 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
11057 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
11058 return error::kNoError;
11061 bool GLES2DecoderImpl::GenQueriesEXTHelper(
11062 GLsizei n, const GLuint* client_ids) {
11063 for (GLsizei ii = 0; ii < n; ++ii) {
11064 if (query_manager_->GetQuery(client_ids[ii])) {
11065 return false;
11068 query_manager_->GenQueries(n, client_ids);
11069 return true;
11072 void GLES2DecoderImpl::DeleteQueriesEXTHelper(
11073 GLsizei n, const GLuint* client_ids) {
11074 for (GLsizei ii = 0; ii < n; ++ii) {
11075 QueryManager::Query* query = query_manager_->GetQuery(client_ids[ii]);
11076 if (query && !query->IsDeleted()) {
11077 ContextState::QueryMap::iterator it =
11078 state_.current_queries.find(query->target());
11079 if (it != state_.current_queries.end())
11080 state_.current_queries.erase(it);
11082 query->Destroy(true);
11084 query_manager_->RemoveQuery(client_ids[ii]);
11088 bool GLES2DecoderImpl::ProcessPendingQueries(bool did_finish) {
11089 if (query_manager_.get() == NULL) {
11090 return false;
11092 if (!query_manager_->ProcessPendingQueries(did_finish)) {
11093 current_decoder_error_ = error::kOutOfBounds;
11095 return query_manager_->HavePendingQueries();
11098 // Note that if there are no pending readpixels right now,
11099 // this function will call the callback immediately.
11100 void GLES2DecoderImpl::WaitForReadPixels(base::Closure callback) {
11101 if (features().use_async_readpixels && !pending_readpixel_fences_.empty()) {
11102 pending_readpixel_fences_.back()->callbacks.push_back(callback);
11103 } else {
11104 callback.Run();
11108 void GLES2DecoderImpl::ProcessPendingReadPixels() {
11109 while (!pending_readpixel_fences_.empty() &&
11110 pending_readpixel_fences_.front()->fence->HasCompleted()) {
11111 std::vector<base::Closure> callbacks =
11112 pending_readpixel_fences_.front()->callbacks;
11113 pending_readpixel_fences_.pop();
11114 for (size_t i = 0; i < callbacks.size(); i++) {
11115 callbacks[i].Run();
11120 bool GLES2DecoderImpl::HasMoreIdleWork() {
11121 return !pending_readpixel_fences_.empty() ||
11122 async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers();
11125 void GLES2DecoderImpl::PerformIdleWork() {
11126 ProcessPendingReadPixels();
11127 if (!async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers())
11128 return;
11129 async_pixel_transfer_manager_->ProcessMorePendingTransfers();
11130 ProcessFinishedAsyncTransfers();
11133 error::Error GLES2DecoderImpl::HandleBeginQueryEXT(uint32 immediate_data_size,
11134 const void* cmd_data) {
11135 const gles2::cmds::BeginQueryEXT& c =
11136 *static_cast<const gles2::cmds::BeginQueryEXT*>(cmd_data);
11137 GLenum target = static_cast<GLenum>(c.target);
11138 GLuint client_id = static_cast<GLuint>(c.id);
11139 int32 sync_shm_id = static_cast<int32>(c.sync_data_shm_id);
11140 uint32 sync_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
11142 switch (target) {
11143 case GL_COMMANDS_ISSUED_CHROMIUM:
11144 case GL_LATENCY_QUERY_CHROMIUM:
11145 case GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM:
11146 case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM:
11147 case GL_GET_ERROR_QUERY_CHROMIUM:
11148 break;
11149 case GL_COMMANDS_COMPLETED_CHROMIUM:
11150 if (!features().chromium_sync_query) {
11151 LOCAL_SET_GL_ERROR(
11152 GL_INVALID_OPERATION, "glBeginQueryEXT",
11153 "not enabled for commands completed queries");
11154 return error::kNoError;
11156 break;
11157 default:
11158 if (!features().occlusion_query_boolean) {
11159 LOCAL_SET_GL_ERROR(
11160 GL_INVALID_OPERATION, "glBeginQueryEXT",
11161 "not enabled for occlusion queries");
11162 return error::kNoError;
11164 break;
11167 if (state_.current_queries.find(target) != state_.current_queries.end()) {
11168 LOCAL_SET_GL_ERROR(
11169 GL_INVALID_OPERATION, "glBeginQueryEXT", "query already in progress");
11170 return error::kNoError;
11173 if (client_id == 0) {
11174 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glBeginQueryEXT", "id is 0");
11175 return error::kNoError;
11178 QueryManager::Query* query = query_manager_->GetQuery(client_id);
11179 if (!query) {
11180 if (!query_manager_->IsValidQuery(client_id)) {
11181 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
11182 "glBeginQueryEXT",
11183 "id not made by glGenQueriesEXT");
11184 return error::kNoError;
11186 query = query_manager_->CreateQuery(
11187 target, client_id, sync_shm_id, sync_shm_offset);
11190 if (query->target() != target) {
11191 LOCAL_SET_GL_ERROR(
11192 GL_INVALID_OPERATION, "glBeginQueryEXT", "target does not match");
11193 return error::kNoError;
11194 } else if (query->shm_id() != sync_shm_id ||
11195 query->shm_offset() != sync_shm_offset) {
11196 DLOG(ERROR) << "Shared memory used by query not the same as before";
11197 return error::kInvalidArguments;
11200 if (!query_manager_->BeginQuery(query)) {
11201 return error::kOutOfBounds;
11204 state_.current_queries[target] = query;
11205 return error::kNoError;
11208 error::Error GLES2DecoderImpl::HandleEndQueryEXT(uint32 immediate_data_size,
11209 const void* cmd_data) {
11210 const gles2::cmds::EndQueryEXT& c =
11211 *static_cast<const gles2::cmds::EndQueryEXT*>(cmd_data);
11212 GLenum target = static_cast<GLenum>(c.target);
11213 uint32 submit_count = static_cast<GLuint>(c.submit_count);
11214 ContextState::QueryMap::iterator it = state_.current_queries.find(target);
11216 if (it == state_.current_queries.end()) {
11217 LOCAL_SET_GL_ERROR(
11218 GL_INVALID_OPERATION, "glEndQueryEXT", "No active query");
11219 return error::kNoError;
11222 QueryManager::Query* query = it->second.get();
11223 if (!query_manager_->EndQuery(query, submit_count)) {
11224 return error::kOutOfBounds;
11227 query_manager_->ProcessPendingTransferQueries();
11229 state_.current_queries.erase(it);
11230 return error::kNoError;
11233 bool GLES2DecoderImpl::GenVertexArraysOESHelper(
11234 GLsizei n, const GLuint* client_ids) {
11235 for (GLsizei ii = 0; ii < n; ++ii) {
11236 if (GetVertexAttribManager(client_ids[ii])) {
11237 return false;
11241 if (!features().native_vertex_array_object) {
11242 // Emulated VAO
11243 for (GLsizei ii = 0; ii < n; ++ii) {
11244 CreateVertexAttribManager(client_ids[ii], 0, true);
11246 } else {
11247 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
11249 glGenVertexArraysOES(n, service_ids.get());
11250 for (GLsizei ii = 0; ii < n; ++ii) {
11251 CreateVertexAttribManager(client_ids[ii], service_ids[ii], true);
11255 return true;
11258 void GLES2DecoderImpl::DeleteVertexArraysOESHelper(
11259 GLsizei n, const GLuint* client_ids) {
11260 for (GLsizei ii = 0; ii < n; ++ii) {
11261 VertexAttribManager* vao =
11262 GetVertexAttribManager(client_ids[ii]);
11263 if (vao && !vao->IsDeleted()) {
11264 if (state_.vertex_attrib_manager.get() == vao) {
11265 DoBindVertexArrayOES(0);
11267 RemoveVertexAttribManager(client_ids[ii]);
11272 void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id) {
11273 VertexAttribManager* vao = NULL;
11274 if (client_id != 0) {
11275 vao = GetVertexAttribManager(client_id);
11276 if (!vao) {
11277 // Unlike most Bind* methods, the spec explicitly states that VertexArray
11278 // only allows names that have been previously generated. As such, we do
11279 // not generate new names here.
11280 LOCAL_SET_GL_ERROR(
11281 GL_INVALID_OPERATION,
11282 "glBindVertexArrayOES", "bad vertex array id.");
11283 current_decoder_error_ = error::kNoError;
11284 return;
11286 } else {
11287 vao = state_.default_vertex_attrib_manager.get();
11290 // Only set the VAO state if it's changed
11291 if (state_.vertex_attrib_manager.get() != vao) {
11292 state_.vertex_attrib_manager = vao;
11293 if (!features().native_vertex_array_object) {
11294 EmulateVertexArrayState();
11295 } else {
11296 GLuint service_id = vao->service_id();
11297 glBindVertexArrayOES(service_id);
11302 // Used when OES_vertex_array_object isn't natively supported
11303 void GLES2DecoderImpl::EmulateVertexArrayState() {
11304 // Setup the Vertex attribute state
11305 for (uint32 vv = 0; vv < group_->max_vertex_attribs(); ++vv) {
11306 RestoreStateForAttrib(vv, true);
11309 // Setup the element buffer
11310 Buffer* element_array_buffer =
11311 state_.vertex_attrib_manager->element_array_buffer();
11312 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
11313 element_array_buffer ? element_array_buffer->service_id() : 0);
11316 bool GLES2DecoderImpl::DoIsVertexArrayOES(GLuint client_id) {
11317 const VertexAttribManager* vao =
11318 GetVertexAttribManager(client_id);
11319 return vao && vao->IsValid() && !vao->IsDeleted();
11322 #if defined(OS_MACOSX)
11323 void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id) {
11324 TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.find(
11325 texture_id);
11326 if (it != texture_to_io_surface_map_.end()) {
11327 // Found a previous IOSurface bound to this texture; release it.
11328 IOSurfaceRef surface = it->second;
11329 CFRelease(surface);
11330 texture_to_io_surface_map_.erase(it);
11333 #endif
11335 void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
11336 GLenum target, GLsizei width, GLsizei height,
11337 GLuint io_surface_id, GLuint plane) {
11338 #if defined(OS_MACOSX)
11339 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) {
11340 LOCAL_SET_GL_ERROR(
11341 GL_INVALID_OPERATION,
11342 "glTexImageIOSurface2DCHROMIUM", "only supported on desktop GL.");
11343 return;
11346 if (target != GL_TEXTURE_RECTANGLE_ARB) {
11347 // This might be supported in the future, and if we could require
11348 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
11349 // could delete a lot of code. For now, perform strict validation so we
11350 // know what's going on.
11351 LOCAL_SET_GL_ERROR(
11352 GL_INVALID_OPERATION,
11353 "glTexImageIOSurface2DCHROMIUM",
11354 "requires TEXTURE_RECTANGLE_ARB target");
11355 return;
11358 // Default target might be conceptually valid, but disallow it to avoid
11359 // accidents.
11360 TextureRef* texture_ref =
11361 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
11362 if (!texture_ref) {
11363 LOCAL_SET_GL_ERROR(
11364 GL_INVALID_OPERATION,
11365 "glTexImageIOSurface2DCHROMIUM", "no rectangle texture bound");
11366 return;
11369 // Look up the new IOSurface. Note that because of asynchrony
11370 // between processes this might fail; during live resizing the
11371 // plugin process might allocate and release an IOSurface before
11372 // this process gets a chance to look it up. Hold on to any old
11373 // IOSurface in this case.
11374 IOSurfaceRef surface = IOSurfaceLookup(io_surface_id);
11375 if (!surface) {
11376 LOCAL_SET_GL_ERROR(
11377 GL_INVALID_OPERATION,
11378 "glTexImageIOSurface2DCHROMIUM", "no IOSurface with the given ID");
11379 return;
11382 // Release any IOSurface previously bound to this texture.
11383 ReleaseIOSurfaceForTexture(texture_ref->service_id());
11385 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
11386 texture_to_io_surface_map_.insert(
11387 std::make_pair(texture_ref->service_id(), surface));
11389 CGLContextObj context =
11390 static_cast<CGLContextObj>(context_->GetHandle());
11392 CGLError err = CGLTexImageIOSurface2D(
11393 context,
11394 target,
11395 GL_RGBA,
11396 width,
11397 height,
11398 GL_BGRA,
11399 GL_UNSIGNED_INT_8_8_8_8_REV,
11400 surface,
11401 plane);
11403 if (err != kCGLNoError) {
11404 LOCAL_SET_GL_ERROR(
11405 GL_INVALID_OPERATION,
11406 "glTexImageIOSurface2DCHROMIUM", "error in CGLTexImageIOSurface2D");
11407 return;
11410 texture_manager()->SetLevelInfo(
11411 texture_ref, target, 0, GL_RGBA, width, height, 1, 0,
11412 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, true);
11414 #else
11415 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
11416 "glTexImageIOSurface2DCHROMIUM", "not supported.");
11417 #endif
11420 static GLenum ExtractFormatFromStorageFormat(GLenum internalformat) {
11421 switch (internalformat) {
11422 case GL_RGB565:
11423 return GL_RGB;
11424 case GL_RGBA4:
11425 return GL_RGBA;
11426 case GL_RGB5_A1:
11427 return GL_RGBA;
11428 case GL_RGB8_OES:
11429 return GL_RGB;
11430 case GL_RGBA8_OES:
11431 return GL_RGBA;
11432 case GL_LUMINANCE8_ALPHA8_EXT:
11433 return GL_LUMINANCE_ALPHA;
11434 case GL_LUMINANCE8_EXT:
11435 return GL_LUMINANCE;
11436 case GL_ALPHA8_EXT:
11437 return GL_ALPHA;
11438 case GL_RGBA32F_EXT:
11439 return GL_RGBA;
11440 case GL_RGB32F_EXT:
11441 return GL_RGB;
11442 case GL_ALPHA32F_EXT:
11443 return GL_ALPHA;
11444 case GL_LUMINANCE32F_EXT:
11445 return GL_LUMINANCE;
11446 case GL_LUMINANCE_ALPHA32F_EXT:
11447 return GL_LUMINANCE_ALPHA;
11448 case GL_RGBA16F_EXT:
11449 return GL_RGBA;
11450 case GL_RGB16F_EXT:
11451 return GL_RGB;
11452 case GL_ALPHA16F_EXT:
11453 return GL_ALPHA;
11454 case GL_LUMINANCE16F_EXT:
11455 return GL_LUMINANCE;
11456 case GL_LUMINANCE_ALPHA16F_EXT:
11457 return GL_LUMINANCE_ALPHA;
11458 case GL_BGRA8_EXT:
11459 return GL_BGRA_EXT;
11460 case GL_SRGB8_ALPHA8_EXT:
11461 return GL_SRGB_ALPHA_EXT;
11462 default:
11463 return GL_NONE;
11467 bool GLES2DecoderImpl::ValidateCopyTextureCHROMIUM(
11468 const char* function_name,
11469 GLenum target,
11470 TextureRef* source_texture_ref,
11471 TextureRef* dest_texture_ref,
11472 GLenum dest_internal_format) {
11473 if (!source_texture_ref || !dest_texture_ref) {
11474 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "unknown texture id");
11475 return false;
11478 if (GL_TEXTURE_2D != target) {
11479 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name,
11480 "invalid texture target");
11481 return false;
11484 Texture* source_texture = source_texture_ref->texture();
11485 Texture* dest_texture = dest_texture_ref->texture();
11486 if (source_texture == dest_texture) {
11487 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
11488 "source and destination textures are the same");
11489 return false;
11492 if (dest_texture->target() != GL_TEXTURE_2D ||
11493 (source_texture->target() != GL_TEXTURE_2D &&
11494 source_texture->target() != GL_TEXTURE_RECTANGLE_ARB &&
11495 source_texture->target() != GL_TEXTURE_EXTERNAL_OES)) {
11496 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name,
11497 "invalid texture target binding");
11498 return false;
11501 GLenum source_type = 0;
11502 GLenum source_internal_format = 0;
11503 source_texture->GetLevelType(source_texture->target(), 0, &source_type,
11504 &source_internal_format);
11506 // The destination format should be GL_RGB, or GL_RGBA. GL_ALPHA,
11507 // GL_LUMINANCE, and GL_LUMINANCE_ALPHA are not supported because they are not
11508 // renderable on some platforms.
11509 bool valid_dest_format = dest_internal_format == GL_RGB ||
11510 dest_internal_format == GL_RGBA ||
11511 dest_internal_format == GL_BGRA_EXT;
11512 bool valid_source_format = source_internal_format == GL_ALPHA ||
11513 source_internal_format == GL_RGB ||
11514 source_internal_format == GL_RGBA ||
11515 source_internal_format == GL_LUMINANCE ||
11516 source_internal_format == GL_LUMINANCE_ALPHA ||
11517 source_internal_format == GL_BGRA_EXT;
11518 if (!valid_source_format || !valid_dest_format) {
11519 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
11520 "invalid internal format");
11521 return false;
11523 return true;
11526 void GLES2DecoderImpl::DoCopyTextureCHROMIUM(GLenum target,
11527 GLuint source_id,
11528 GLuint dest_id,
11529 GLenum internal_format,
11530 GLenum dest_type) {
11531 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopyTextureCHROMIUM");
11533 TextureRef* source_texture_ref = GetTexture(source_id);
11534 TextureRef* dest_texture_ref = GetTexture(dest_id);
11535 Texture* source_texture = source_texture_ref->texture();
11536 Texture* dest_texture = dest_texture_ref->texture();
11537 int source_width = 0;
11538 int source_height = 0;
11539 gfx::GLImage* image =
11540 source_texture->GetLevelImage(source_texture->target(), 0);
11541 if (image) {
11542 gfx::Size size = image->GetSize();
11543 source_width = size.width();
11544 source_height = size.height();
11545 if (source_width <= 0 || source_height <= 0) {
11546 LOCAL_SET_GL_ERROR(
11547 GL_INVALID_VALUE,
11548 "glCopyTextureChromium", "invalid image size");
11549 return;
11551 } else {
11552 if (!source_texture->GetLevelSize(
11553 source_texture->target(), 0, &source_width, &source_height)) {
11554 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
11555 "glCopyTextureChromium",
11556 "source texture has no level 0");
11557 return;
11560 // Check that this type of texture is allowed.
11561 if (!texture_manager()->ValidForTarget(source_texture->target(), 0,
11562 source_width, source_height, 1)) {
11563 LOCAL_SET_GL_ERROR(
11564 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "Bad dimensions");
11565 return;
11569 GLenum source_type = 0;
11570 GLenum source_internal_format = 0;
11571 source_texture->GetLevelType(
11572 source_texture->target(), 0, &source_type, &source_internal_format);
11574 if (dest_texture->IsImmutable()) {
11575 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCopyTextureCHROMIUM",
11576 "texture is immutable");
11577 return;
11580 if (!ValidateCopyTextureCHROMIUM("glCopyTextureCHROMIUM", target,
11581 source_texture_ref, dest_texture_ref,
11582 internal_format)) {
11583 return;
11586 // Clear the source texture if necessary.
11587 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref,
11588 source_texture->target(), 0)) {
11589 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTextureCHROMIUM",
11590 "dimensions too big");
11591 return;
11594 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
11595 // needed because it takes 10s of milliseconds to initialize.
11596 if (!copy_texture_CHROMIUM_.get()) {
11597 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
11598 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
11599 copy_texture_CHROMIUM_->Initialize(this);
11600 RestoreCurrentFramebufferBindings();
11601 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR)
11602 return;
11605 GLenum dest_type_previous = dest_type;
11606 GLenum dest_internal_format = internal_format;
11607 int dest_width = 0;
11608 int dest_height = 0;
11609 bool dest_level_defined =
11610 dest_texture->GetLevelSize(GL_TEXTURE_2D, 0, &dest_width, &dest_height);
11612 if (dest_level_defined) {
11613 dest_texture->GetLevelType(GL_TEXTURE_2D, 0, &dest_type_previous,
11614 &dest_internal_format);
11617 // Resize the destination texture to the dimensions of the source texture.
11618 if (!dest_level_defined || dest_width != source_width ||
11619 dest_height != source_height ||
11620 dest_internal_format != internal_format ||
11621 dest_type_previous != dest_type) {
11622 // Ensure that the glTexImage2D succeeds.
11623 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
11624 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
11625 glTexImage2D(GL_TEXTURE_2D, 0, internal_format, source_width, source_height,
11626 0, internal_format, dest_type, NULL);
11627 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM");
11628 if (error != GL_NO_ERROR) {
11629 RestoreCurrentTextureBindings(&state_, GL_TEXTURE_2D);
11630 return;
11633 texture_manager()->SetLevelInfo(
11634 dest_texture_ref, GL_TEXTURE_2D, 0, internal_format, source_width,
11635 source_height, 1, 0, internal_format, dest_type, true);
11636 } else {
11637 texture_manager()->SetLevelCleared(dest_texture_ref, GL_TEXTURE_2D, 0,
11638 true);
11641 ScopedModifyPixels modify(dest_texture_ref);
11643 // Try using GLImage::CopyTexImage when possible.
11644 bool unpack_premultiply_alpha_change =
11645 unpack_premultiply_alpha_ ^ unpack_unpremultiply_alpha_;
11646 if (image && !unpack_flip_y_ && !unpack_premultiply_alpha_change) {
11647 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
11648 if (image->CopyTexImage(GL_TEXTURE_2D))
11649 return;
11652 DoWillUseTexImageIfNeeded(source_texture, source_texture->target());
11654 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
11655 // before presenting.
11656 if (source_texture->target() == GL_TEXTURE_EXTERNAL_OES) {
11657 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
11658 // instead of using kIdentityMatrix crbug.com/226218.
11659 copy_texture_CHROMIUM_->DoCopyTextureWithTransform(
11660 this, source_texture->target(), source_texture->service_id(),
11661 dest_texture->service_id(), source_width, source_height, unpack_flip_y_,
11662 unpack_premultiply_alpha_, unpack_unpremultiply_alpha_,
11663 kIdentityMatrix);
11664 } else {
11665 copy_texture_CHROMIUM_->DoCopyTexture(
11666 this, source_texture->target(), source_texture->service_id(),
11667 source_internal_format, dest_texture->service_id(), internal_format,
11668 source_width, source_height, unpack_flip_y_, unpack_premultiply_alpha_,
11669 unpack_unpremultiply_alpha_);
11672 DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
11675 void GLES2DecoderImpl::DoCopySubTextureCHROMIUM(GLenum target,
11676 GLuint source_id,
11677 GLuint dest_id,
11678 GLint xoffset,
11679 GLint yoffset) {
11680 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopySubTextureCHROMIUM");
11682 TextureRef* source_texture_ref = GetTexture(source_id);
11683 TextureRef* dest_texture_ref = GetTexture(dest_id);
11684 Texture* source_texture = source_texture_ref->texture();
11685 Texture* dest_texture = dest_texture_ref->texture();
11686 int source_width = 0;
11687 int source_height = 0;
11688 gfx::GLImage* image =
11689 source_texture->GetLevelImage(source_texture->target(), 0);
11690 if (image) {
11691 gfx::Size size = image->GetSize();
11692 source_width = size.width();
11693 source_height = size.height();
11694 if (source_width <= 0 || source_height <= 0) {
11695 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
11696 "invalid image size");
11697 return;
11699 } else {
11700 if (!source_texture->GetLevelSize(source_texture->target(), 0,
11701 &source_width, &source_height)) {
11702 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
11703 "source texture has no level 0");
11704 return;
11707 // Check that this type of texture is allowed.
11708 if (!texture_manager()->ValidForTarget(source_texture->target(), 0,
11709 source_width, source_height, 1)) {
11710 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
11711 "source texture bad dimensions");
11712 return;
11716 GLenum source_type = 0;
11717 GLenum source_internal_format = 0;
11718 source_texture->GetLevelType(source_texture->target(), 0, &source_type,
11719 &source_internal_format);
11720 GLenum dest_type = 0;
11721 GLenum dest_internal_format = 0;
11722 bool dest_level_defined = dest_texture->GetLevelType(
11723 dest_texture->target(), 0, &dest_type, &dest_internal_format);
11724 if (!dest_level_defined) {
11725 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCopySubTextureCHROMIUM",
11726 "destination texture is not defined");
11727 return;
11729 if (!dest_texture->ValidForTexture(dest_texture->target(), 0, xoffset,
11730 yoffset, source_width, source_height,
11731 dest_type)) {
11732 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
11733 "destination texture bad dimensions.");
11734 return;
11737 if (!ValidateCopyTextureCHROMIUM("glCopySubTextureCHROMIUM", target,
11738 source_texture_ref, dest_texture_ref,
11739 dest_internal_format)) {
11740 return;
11743 // Clear the source texture if necessary.
11744 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref,
11745 source_texture->target(), 0)) {
11746 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopySubTextureCHROMIUM",
11747 "source texture dimensions too big");
11748 return;
11751 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
11752 // needed because it takes 10s of milliseconds to initialize.
11753 if (!copy_texture_CHROMIUM_.get()) {
11754 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopySubTextureCHROMIUM");
11755 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
11756 copy_texture_CHROMIUM_->Initialize(this);
11757 RestoreCurrentFramebufferBindings();
11758 if (LOCAL_PEEK_GL_ERROR("glCopySubTextureCHROMIUM") != GL_NO_ERROR)
11759 return;
11762 int dest_width = 0;
11763 int dest_height = 0;
11764 bool ok =
11765 dest_texture->GetLevelSize(GL_TEXTURE_2D, 0, &dest_width, &dest_height);
11766 DCHECK(ok);
11767 if (xoffset != 0 || yoffset != 0 || source_width != dest_width ||
11768 source_height != dest_height) {
11769 if (!texture_manager()->ClearTextureLevel(this, dest_texture_ref, target,
11770 0)) {
11771 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopySubTextureCHROMIUM",
11772 "destination texture dimensions too big");
11773 return;
11775 } else {
11776 texture_manager()->SetLevelCleared(dest_texture_ref, GL_TEXTURE_2D, 0,
11777 true);
11780 ScopedModifyPixels modify(dest_texture_ref);
11782 // Try using GLImage::CopyTexSubImage when possible.
11783 bool unpack_premultiply_alpha_change =
11784 unpack_premultiply_alpha_ ^ unpack_unpremultiply_alpha_;
11785 if (image && !unpack_flip_y_ && !unpack_premultiply_alpha_change &&
11786 !xoffset && !yoffset) {
11787 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
11788 if (image->CopyTexImage(GL_TEXTURE_2D))
11789 return;
11792 DoWillUseTexImageIfNeeded(source_texture, source_texture->target());
11794 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
11795 // before presenting.
11796 if (source_texture->target() == GL_TEXTURE_EXTERNAL_OES) {
11797 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
11798 // instead of using kIdentityMatrix crbug.com/226218.
11799 copy_texture_CHROMIUM_->DoCopySubTextureWithTransform(
11800 this, source_texture->target(), source_texture->service_id(),
11801 dest_texture->service_id(), xoffset, yoffset, dest_width, dest_height,
11802 source_width, source_height, unpack_flip_y_, unpack_premultiply_alpha_,
11803 unpack_unpremultiply_alpha_, kIdentityMatrix);
11804 } else {
11805 copy_texture_CHROMIUM_->DoCopySubTexture(
11806 this, source_texture->target(), source_texture->service_id(),
11807 source_internal_format, dest_texture->service_id(),
11808 dest_internal_format, xoffset, yoffset, dest_width, dest_height,
11809 source_width, source_height, unpack_flip_y_, unpack_premultiply_alpha_,
11810 unpack_unpremultiply_alpha_);
11813 DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
11816 static GLenum ExtractTypeFromStorageFormat(GLenum internalformat) {
11817 switch (internalformat) {
11818 case GL_RGB565:
11819 return GL_UNSIGNED_SHORT_5_6_5;
11820 case GL_RGBA4:
11821 return GL_UNSIGNED_SHORT_4_4_4_4;
11822 case GL_RGB5_A1:
11823 return GL_UNSIGNED_SHORT_5_5_5_1;
11824 case GL_RGB8_OES:
11825 return GL_UNSIGNED_BYTE;
11826 case GL_RGBA8_OES:
11827 return GL_UNSIGNED_BYTE;
11828 case GL_LUMINANCE8_ALPHA8_EXT:
11829 return GL_UNSIGNED_BYTE;
11830 case GL_LUMINANCE8_EXT:
11831 return GL_UNSIGNED_BYTE;
11832 case GL_ALPHA8_EXT:
11833 return GL_UNSIGNED_BYTE;
11834 case GL_RGBA32F_EXT:
11835 return GL_FLOAT;
11836 case GL_RGB32F_EXT:
11837 return GL_FLOAT;
11838 case GL_ALPHA32F_EXT:
11839 return GL_FLOAT;
11840 case GL_LUMINANCE32F_EXT:
11841 return GL_FLOAT;
11842 case GL_LUMINANCE_ALPHA32F_EXT:
11843 return GL_FLOAT;
11844 case GL_RGBA16F_EXT:
11845 return GL_HALF_FLOAT_OES;
11846 case GL_RGB16F_EXT:
11847 return GL_HALF_FLOAT_OES;
11848 case GL_ALPHA16F_EXT:
11849 return GL_HALF_FLOAT_OES;
11850 case GL_LUMINANCE16F_EXT:
11851 return GL_HALF_FLOAT_OES;
11852 case GL_LUMINANCE_ALPHA16F_EXT:
11853 return GL_HALF_FLOAT_OES;
11854 case GL_BGRA8_EXT:
11855 return GL_UNSIGNED_BYTE;
11856 default:
11857 return GL_NONE;
11861 void GLES2DecoderImpl::DoTexStorage2DEXT(
11862 GLenum target,
11863 GLint levels,
11864 GLenum internal_format,
11865 GLsizei width,
11866 GLsizei height) {
11867 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT",
11868 "width", width, "height", height);
11869 if (!texture_manager()->ValidForTarget(target, 0, width, height, 1) ||
11870 TextureManager::ComputeMipMapCount(target, width, height, 1) < levels) {
11871 LOCAL_SET_GL_ERROR(
11872 GL_INVALID_VALUE, "glTexStorage2DEXT", "dimensions out of range");
11873 return;
11875 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
11876 &state_, target);
11877 if (!texture_ref) {
11878 LOCAL_SET_GL_ERROR(
11879 GL_INVALID_OPERATION,
11880 "glTexStorage2DEXT", "unknown texture for target");
11881 return;
11883 Texture* texture = texture_ref->texture();
11884 if (texture->IsAttachedToFramebuffer()) {
11885 framebuffer_state_.clear_state_dirty = true;
11887 if (texture->IsImmutable()) {
11888 LOCAL_SET_GL_ERROR(
11889 GL_INVALID_OPERATION,
11890 "glTexStorage2DEXT", "texture is immutable");
11891 return;
11894 GLenum format = ExtractFormatFromStorageFormat(internal_format);
11895 GLenum type = ExtractTypeFromStorageFormat(internal_format);
11898 GLsizei level_width = width;
11899 GLsizei level_height = height;
11900 uint32 estimated_size = 0;
11901 for (int ii = 0; ii < levels; ++ii) {
11902 uint32 level_size = 0;
11903 if (!GLES2Util::ComputeImageDataSizes(
11904 level_width, level_height, 1, format, type, state_.unpack_alignment,
11905 &estimated_size, NULL, NULL) ||
11906 !SafeAddUint32(estimated_size, level_size, &estimated_size)) {
11907 LOCAL_SET_GL_ERROR(
11908 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "dimensions too large");
11909 return;
11911 level_width = std::max(1, level_width >> 1);
11912 level_height = std::max(1, level_height >> 1);
11914 if (!EnsureGPUMemoryAvailable(estimated_size)) {
11915 LOCAL_SET_GL_ERROR(
11916 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "out of memory");
11917 return;
11921 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexStorage2DEXT");
11922 glTexStorage2DEXT(target, levels, internal_format, width, height);
11923 GLenum error = LOCAL_PEEK_GL_ERROR("glTexStorage2DEXT");
11924 if (error == GL_NO_ERROR) {
11925 GLsizei level_width = width;
11926 GLsizei level_height = height;
11927 for (int ii = 0; ii < levels; ++ii) {
11928 texture_manager()->SetLevelInfo(
11929 texture_ref, target, ii, format,
11930 level_width, level_height, 1, 0, format, type, false);
11931 level_width = std::max(1, level_width >> 1);
11932 level_height = std::max(1, level_height >> 1);
11934 texture->SetImmutable(true);
11938 error::Error GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
11939 uint32 immediate_data_size,
11940 const void* cmd_data) {
11941 return error::kUnknownCommand;
11944 void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target,
11945 const GLbyte* data) {
11946 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureCHROMIUM",
11947 "context", logger_.GetLogPrefix(),
11948 "mailbox[0]", static_cast<unsigned char>(data[0]));
11950 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
11951 &state_, target);
11952 ProduceTextureRef("glProduceTextureCHROMIUM", texture_ref, target, data);
11955 void GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM(GLuint client_id,
11956 GLenum target, const GLbyte* data) {
11957 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM",
11958 "context", logger_.GetLogPrefix(),
11959 "mailbox[0]", static_cast<unsigned char>(data[0]));
11961 ProduceTextureRef("glProduceTextureDirectCHROMIUM", GetTexture(client_id),
11962 target, data);
11965 void GLES2DecoderImpl::ProduceTextureRef(std::string func_name,
11966 TextureRef* texture_ref, GLenum target, const GLbyte* data) {
11967 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
11968 DLOG_IF(ERROR, !mailbox.Verify()) << func_name << " was passed a "
11969 "mailbox that was not generated by "
11970 "GenMailboxCHROMIUM.";
11972 if (!texture_ref) {
11973 LOCAL_SET_GL_ERROR(
11974 GL_INVALID_OPERATION, func_name.c_str(), "unknown texture for target");
11975 return;
11978 Texture* produced = texture_manager()->Produce(texture_ref);
11979 if (!produced) {
11980 LOCAL_SET_GL_ERROR(
11981 GL_INVALID_OPERATION, func_name.c_str(), "invalid texture");
11982 return;
11985 if (produced->target() != target) {
11986 LOCAL_SET_GL_ERROR(
11987 GL_INVALID_OPERATION, func_name.c_str(), "invalid target");
11988 return;
11991 group_->mailbox_manager()->ProduceTexture(mailbox, produced);
11994 void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target,
11995 const GLbyte* data) {
11996 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoConsumeTextureCHROMIUM",
11997 "context", logger_.GetLogPrefix(),
11998 "mailbox[0]", static_cast<unsigned char>(data[0]));
11999 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
12000 DLOG_IF(ERROR, !mailbox.Verify()) << "ConsumeTextureCHROMIUM was passed a "
12001 "mailbox that was not generated by "
12002 "GenMailboxCHROMIUM.";
12004 scoped_refptr<TextureRef> texture_ref =
12005 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
12006 if (!texture_ref.get()) {
12007 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
12008 "glConsumeTextureCHROMIUM",
12009 "unknown texture for target");
12010 return;
12012 GLuint client_id = texture_ref->client_id();
12013 if (!client_id) {
12014 LOCAL_SET_GL_ERROR(
12015 GL_INVALID_OPERATION,
12016 "glConsumeTextureCHROMIUM", "unknown texture for target");
12017 return;
12019 Texture* texture = group_->mailbox_manager()->ConsumeTexture(mailbox);
12020 if (!texture) {
12021 LOCAL_SET_GL_ERROR(
12022 GL_INVALID_OPERATION,
12023 "glConsumeTextureCHROMIUM", "invalid mailbox name");
12024 return;
12026 if (texture->target() != target) {
12027 LOCAL_SET_GL_ERROR(
12028 GL_INVALID_OPERATION,
12029 "glConsumeTextureCHROMIUM", "invalid target");
12030 return;
12033 DeleteTexturesHelper(1, &client_id);
12034 texture_ref = texture_manager()->Consume(client_id, texture);
12035 glBindTexture(target, texture_ref->service_id());
12037 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
12038 unit.bind_target = target;
12039 switch (target) {
12040 case GL_TEXTURE_2D:
12041 unit.bound_texture_2d = texture_ref;
12042 break;
12043 case GL_TEXTURE_CUBE_MAP:
12044 unit.bound_texture_cube_map = texture_ref;
12045 break;
12046 case GL_TEXTURE_EXTERNAL_OES:
12047 unit.bound_texture_external_oes = texture_ref;
12048 break;
12049 case GL_TEXTURE_RECTANGLE_ARB:
12050 unit.bound_texture_rectangle_arb = texture_ref;
12051 break;
12052 default:
12053 NOTREACHED(); // Validation should prevent us getting here.
12054 break;
12058 void GLES2DecoderImpl::EnsureTextureForClientId(
12059 GLenum target,
12060 GLuint client_id) {
12061 TextureRef* texture_ref = GetTexture(client_id);
12062 if (!texture_ref) {
12063 GLuint service_id;
12064 glGenTextures(1, &service_id);
12065 DCHECK_NE(0u, service_id);
12066 texture_ref = CreateTexture(client_id, service_id);
12067 texture_manager()->SetTarget(texture_ref, target);
12068 glBindTexture(target, service_id);
12069 RestoreCurrentTextureBindings(&state_, target);
12073 // If CreateAndConsumeTexture fails we still need to ensure that the client_id
12074 // provided is associated with a service_id/TextureRef for consistency, even if
12075 // the resulting texture is incomplete.
12076 error::Error GLES2DecoderImpl::HandleCreateAndConsumeTextureCHROMIUMImmediate(
12077 uint32_t immediate_data_size,
12078 const void* cmd_data) {
12079 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate& c =
12080 *static_cast<
12081 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate*>(
12082 cmd_data);
12083 GLenum target = static_cast<GLenum>(c.target);
12084 uint32_t data_size;
12085 if (!ComputeDataSize(1, sizeof(GLbyte), 64, &data_size)) {
12086 return error::kOutOfBounds;
12088 if (data_size > immediate_data_size) {
12089 return error::kOutOfBounds;
12091 const GLbyte* mailbox =
12092 GetImmediateDataAs<const GLbyte*>(c, data_size, immediate_data_size);
12093 if (!validators_->texture_bind_target.IsValid(target)) {
12094 LOCAL_SET_GL_ERROR_INVALID_ENUM(
12095 "glCreateAndConsumeTextureCHROMIUM", target, "target");
12096 return error::kNoError;
12098 if (mailbox == NULL) {
12099 return error::kOutOfBounds;
12101 uint32_t client_id = c.client_id;
12102 DoCreateAndConsumeTextureCHROMIUM(target, mailbox, client_id);
12103 return error::kNoError;
12106 void GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM(GLenum target,
12107 const GLbyte* data, GLuint client_id) {
12108 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM",
12109 "context", logger_.GetLogPrefix(),
12110 "mailbox[0]", static_cast<unsigned char>(data[0]));
12111 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
12112 DLOG_IF(ERROR, !mailbox.Verify()) << "CreateAndConsumeTextureCHROMIUM was "
12113 "passed a mailbox that was not "
12114 "generated by GenMailboxCHROMIUM.";
12116 TextureRef* texture_ref = GetTexture(client_id);
12117 if (texture_ref) {
12118 // No need to call EnsureTextureForClientId here, the client_id already has
12119 // an associated texture.
12120 LOCAL_SET_GL_ERROR(
12121 GL_INVALID_OPERATION,
12122 "glCreateAndConsumeTextureCHROMIUM", "client id already in use");
12123 return;
12125 Texture* texture = group_->mailbox_manager()->ConsumeTexture(mailbox);
12126 if (!texture) {
12127 EnsureTextureForClientId(target, client_id);
12128 LOCAL_SET_GL_ERROR(
12129 GL_INVALID_OPERATION,
12130 "glCreateAndConsumeTextureCHROMIUM", "invalid mailbox name");
12131 return;
12134 if (texture->target() != target) {
12135 EnsureTextureForClientId(target, client_id);
12136 LOCAL_SET_GL_ERROR(
12137 GL_INVALID_OPERATION,
12138 "glCreateAndConsumeTextureCHROMIUM", "invalid target");
12139 return;
12142 texture_ref = texture_manager()->Consume(client_id, texture);
12145 bool GLES2DecoderImpl::DoIsValuebufferCHROMIUM(GLuint client_id) {
12146 const Valuebuffer* valuebuffer = GetValuebuffer(client_id);
12147 return valuebuffer && valuebuffer->IsValid();
12150 void GLES2DecoderImpl::DoBindValueBufferCHROMIUM(GLenum target,
12151 GLuint client_id) {
12152 Valuebuffer* valuebuffer = NULL;
12153 if (client_id != 0) {
12154 valuebuffer = GetValuebuffer(client_id);
12155 if (!valuebuffer) {
12156 if (!group_->bind_generates_resource()) {
12157 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glBindValuebufferCHROMIUM",
12158 "id not generated by glBindValuebufferCHROMIUM");
12159 return;
12162 // It's a new id so make a valuebuffer for it.
12163 CreateValuebuffer(client_id);
12164 valuebuffer = GetValuebuffer(client_id);
12166 valuebuffer->MarkAsValid();
12168 state_.bound_valuebuffer = valuebuffer;
12171 void GLES2DecoderImpl::DoSubscribeValueCHROMIUM(GLenum target,
12172 GLenum subscription) {
12173 if (!CheckCurrentValuebuffer("glSubscribeValueCHROMIUM")) {
12174 return;
12176 state_.bound_valuebuffer.get()->AddSubscription(subscription);
12179 void GLES2DecoderImpl::DoPopulateSubscribedValuesCHROMIUM(GLenum target) {
12180 if (!CheckCurrentValuebuffer("glPopulateSubscribedValuesCHROMIUM")) {
12181 return;
12183 valuebuffer_manager()->UpdateValuebufferState(state_.bound_valuebuffer.get());
12186 void GLES2DecoderImpl::DoUniformValueBufferCHROMIUM(GLint location,
12187 GLenum target,
12188 GLenum subscription) {
12189 if (!CheckCurrentValuebufferForSubscription(
12190 subscription, "glPopulateSubscribedValuesCHROMIUM")) {
12191 return;
12193 if (!CheckSubscriptionTarget(location, subscription,
12194 "glPopulateSubscribedValuesCHROMIUM")) {
12195 return;
12197 const ValueState* state =
12198 state_.bound_valuebuffer.get()->GetState(subscription);
12199 if (state) {
12200 switch (subscription) {
12201 case GL_MOUSE_POSITION_CHROMIUM:
12202 DoUniform2iv(location, 1, state->int_value);
12203 break;
12204 default:
12205 NOTREACHED() << "Unhandled uniform subscription target "
12206 << subscription;
12207 break;
12212 void GLES2DecoderImpl::DoInsertEventMarkerEXT(
12213 GLsizei length, const GLchar* marker) {
12214 if (!marker) {
12215 marker = "";
12217 debug_marker_manager_.SetMarker(
12218 length ? std::string(marker, length) : std::string(marker));
12221 void GLES2DecoderImpl::DoPushGroupMarkerEXT(
12222 GLsizei length, const GLchar* marker) {
12223 if (!marker) {
12224 marker = "";
12226 std::string name = length ? std::string(marker, length) : std::string(marker);
12227 debug_marker_manager_.PushGroup(name);
12228 gpu_tracer_->Begin(TRACE_DISABLED_BY_DEFAULT("gpu_group_marker"), name,
12229 kTraceGroupMarker);
12232 void GLES2DecoderImpl::DoPopGroupMarkerEXT(void) {
12233 debug_marker_manager_.PopGroup();
12234 gpu_tracer_->End(kTraceGroupMarker);
12237 void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(
12238 GLenum target, GLint image_id) {
12239 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM");
12241 if (target == GL_TEXTURE_CUBE_MAP) {
12242 LOCAL_SET_GL_ERROR(
12243 GL_INVALID_ENUM,
12244 "glBindTexImage2DCHROMIUM", "invalid target");
12245 return;
12248 // Default target might be conceptually valid, but disallow it to avoid
12249 // accidents.
12250 TextureRef* texture_ref =
12251 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
12252 if (!texture_ref) {
12253 LOCAL_SET_GL_ERROR(
12254 GL_INVALID_OPERATION,
12255 "glBindTexImage2DCHROMIUM", "no texture bound");
12256 return;
12259 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
12260 if (!gl_image) {
12261 LOCAL_SET_GL_ERROR(
12262 GL_INVALID_OPERATION,
12263 "glBindTexImage2DCHROMIUM", "no image found with the given ID");
12264 return;
12268 ScopedGLErrorSuppressor suppressor(
12269 "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", GetErrorState());
12270 if (!gl_image->BindTexImage(target)) {
12271 LOCAL_SET_GL_ERROR(
12272 GL_INVALID_OPERATION,
12273 "glBindTexImage2DCHROMIUM", "fail to bind image with the given ID");
12274 return;
12278 gfx::Size size = gl_image->GetSize();
12279 texture_manager()->SetLevelInfo(
12280 texture_ref, target, 0, GL_RGBA, size.width(), size.height(), 1, 0,
12281 GL_RGBA, GL_UNSIGNED_BYTE, true);
12282 texture_manager()->SetLevelImage(texture_ref, target, 0, gl_image);
12285 void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(
12286 GLenum target, GLint image_id) {
12287 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM");
12289 // Default target might be conceptually valid, but disallow it to avoid
12290 // accidents.
12291 TextureRef* texture_ref =
12292 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
12293 if (!texture_ref) {
12294 LOCAL_SET_GL_ERROR(
12295 GL_INVALID_OPERATION,
12296 "glReleaseTexImage2DCHROMIUM", "no texture bound");
12297 return;
12300 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
12301 if (!gl_image) {
12302 LOCAL_SET_GL_ERROR(
12303 GL_INVALID_OPERATION,
12304 "glReleaseTexImage2DCHROMIUM", "no image found with the given ID");
12305 return;
12308 // Do nothing when image is not currently bound.
12309 if (texture_ref->texture()->GetLevelImage(target, 0) != gl_image)
12310 return;
12313 ScopedGLErrorSuppressor suppressor(
12314 "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", GetErrorState());
12315 gl_image->ReleaseTexImage(target);
12318 texture_manager()->SetLevelInfo(
12319 texture_ref, target, 0, GL_RGBA, 0, 0, 1, 0,
12320 GL_RGBA, GL_UNSIGNED_BYTE, false);
12323 error::Error GLES2DecoderImpl::HandleTraceBeginCHROMIUM(
12324 uint32 immediate_data_size,
12325 const void* cmd_data) {
12326 const gles2::cmds::TraceBeginCHROMIUM& c =
12327 *static_cast<const gles2::cmds::TraceBeginCHROMIUM*>(cmd_data);
12328 Bucket* category_bucket = GetBucket(c.category_bucket_id);
12329 Bucket* name_bucket = GetBucket(c.name_bucket_id);
12330 if (!category_bucket || category_bucket->size() == 0 ||
12331 !name_bucket || name_bucket->size() == 0) {
12332 return error::kInvalidArguments;
12335 std::string category_name;
12336 std::string trace_name;
12337 if (!category_bucket->GetAsString(&category_name) ||
12338 !name_bucket->GetAsString(&trace_name)) {
12339 return error::kInvalidArguments;
12342 if (!gpu_tracer_->Begin(category_name, trace_name, kTraceCHROMIUM)) {
12343 LOCAL_SET_GL_ERROR(
12344 GL_INVALID_OPERATION,
12345 "glTraceBeginCHROMIUM", "unable to create begin trace");
12346 return error::kNoError;
12348 return error::kNoError;
12351 void GLES2DecoderImpl::DoTraceEndCHROMIUM() {
12352 if (!gpu_tracer_->End(kTraceCHROMIUM)) {
12353 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
12354 "glTraceEndCHROMIUM", "no trace begin found");
12355 return;
12359 void GLES2DecoderImpl::DoDrawBuffersEXT(
12360 GLsizei count, const GLenum* bufs) {
12361 if (count > static_cast<GLsizei>(group_->max_draw_buffers())) {
12362 LOCAL_SET_GL_ERROR(
12363 GL_INVALID_VALUE,
12364 "glDrawBuffersEXT", "greater than GL_MAX_DRAW_BUFFERS_EXT");
12365 return;
12368 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
12369 if (framebuffer) {
12370 for (GLsizei i = 0; i < count; ++i) {
12371 if (bufs[i] != static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i) &&
12372 bufs[i] != GL_NONE) {
12373 LOCAL_SET_GL_ERROR(
12374 GL_INVALID_OPERATION,
12375 "glDrawBuffersEXT",
12376 "bufs[i] not GL_NONE or GL_COLOR_ATTACHMENTi_EXT");
12377 return;
12380 glDrawBuffersARB(count, bufs);
12381 framebuffer->SetDrawBuffers(count, bufs);
12382 } else { // backbuffer
12383 if (count > 1 ||
12384 (bufs[0] != GL_BACK && bufs[0] != GL_NONE)) {
12385 LOCAL_SET_GL_ERROR(
12386 GL_INVALID_OPERATION,
12387 "glDrawBuffersEXT",
12388 "more than one buffer or bufs not GL_NONE or GL_BACK");
12389 return;
12391 GLenum mapped_buf = bufs[0];
12392 if (GetBackbufferServiceId() != 0 && // emulated backbuffer
12393 bufs[0] == GL_BACK) {
12394 mapped_buf = GL_COLOR_ATTACHMENT0;
12396 glDrawBuffersARB(count, &mapped_buf);
12397 group_->set_draw_buffer(bufs[0]);
12401 void GLES2DecoderImpl::DoLoseContextCHROMIUM(GLenum current, GLenum other) {
12402 MarkContextLost(GetContextLostReasonFromResetStatus(current));
12403 group_->LoseContexts(GetContextLostReasonFromResetStatus(other));
12404 reset_by_robustness_extension_ = true;
12407 void GLES2DecoderImpl::DoMatrixLoadfCHROMIUM(GLenum matrix_mode,
12408 const GLfloat* matrix) {
12409 DCHECK(matrix_mode == GL_PATH_PROJECTION_CHROMIUM ||
12410 matrix_mode == GL_PATH_MODELVIEW_CHROMIUM);
12411 if (!features().chromium_path_rendering) {
12412 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
12413 "glMatrixLoadfCHROMIUM",
12414 "function not available");
12415 return;
12418 GLfloat* target_matrix = matrix_mode == GL_PATH_PROJECTION_CHROMIUM
12419 ? state_.projection_matrix
12420 : state_.modelview_matrix;
12421 memcpy(target_matrix, matrix, sizeof(GLfloat) * 16);
12422 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
12423 // since the values of the _NV and _CHROMIUM tokens match.
12424 glMatrixLoadfEXT(matrix_mode, matrix);
12427 void GLES2DecoderImpl::DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode) {
12428 DCHECK(matrix_mode == GL_PATH_PROJECTION_CHROMIUM ||
12429 matrix_mode == GL_PATH_MODELVIEW_CHROMIUM);
12431 if (!features().chromium_path_rendering) {
12432 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
12433 "glMatrixLoadIdentityCHROMIUM",
12434 "function not available");
12435 return;
12438 GLfloat* target_matrix = matrix_mode == GL_PATH_PROJECTION_CHROMIUM
12439 ? state_.projection_matrix
12440 : state_.modelview_matrix;
12441 memcpy(target_matrix, kIdentityMatrix, sizeof(kIdentityMatrix));
12442 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
12443 // since the values of the _NV and _CHROMIUM tokens match.
12444 glMatrixLoadIdentityEXT(matrix_mode);
12447 bool GLES2DecoderImpl::ValidateAsyncTransfer(
12448 const char* function_name,
12449 TextureRef* texture_ref,
12450 GLenum target,
12451 GLint level,
12452 const void * data) {
12453 // We only support async uploads to 2D textures for now.
12454 if (GL_TEXTURE_2D != target) {
12455 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
12456 return false;
12458 // We only support uploads to level zero for now.
12459 if (level != 0) {
12460 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "level != 0");
12461 return false;
12463 // A transfer buffer must be bound, even for asyncTexImage2D.
12464 if (data == NULL) {
12465 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, "buffer == 0");
12466 return false;
12468 // We only support one async transfer in progress.
12469 if (!texture_ref ||
12470 async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
12471 LOCAL_SET_GL_ERROR(
12472 GL_INVALID_OPERATION,
12473 function_name, "transfer already in progress");
12474 return false;
12476 return true;
12479 base::Closure GLES2DecoderImpl::AsyncUploadTokenCompletionClosure(
12480 uint32 async_upload_token,
12481 uint32 sync_data_shm_id,
12482 uint32 sync_data_shm_offset) {
12483 scoped_refptr<gpu::Buffer> buffer = GetSharedMemoryBuffer(sync_data_shm_id);
12484 if (!buffer.get() ||
12485 !buffer->GetDataAddress(sync_data_shm_offset, sizeof(AsyncUploadSync)))
12486 return base::Closure();
12488 AsyncMemoryParams mem_params(buffer,
12489 sync_data_shm_offset,
12490 sizeof(AsyncUploadSync));
12492 scoped_refptr<AsyncUploadTokenCompletionObserver> observer(
12493 new AsyncUploadTokenCompletionObserver(async_upload_token));
12495 return base::Bind(
12496 &AsyncPixelTransferManager::AsyncNotifyCompletion,
12497 base::Unretained(GetAsyncPixelTransferManager()),
12498 mem_params,
12499 observer);
12502 error::Error GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM(
12503 uint32 immediate_data_size,
12504 const void* cmd_data) {
12505 const gles2::cmds::AsyncTexImage2DCHROMIUM& c =
12506 *static_cast<const gles2::cmds::AsyncTexImage2DCHROMIUM*>(cmd_data);
12507 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM");
12508 GLenum target = static_cast<GLenum>(c.target);
12509 GLint level = static_cast<GLint>(c.level);
12510 GLenum internal_format = static_cast<GLenum>(c.internalformat);
12511 GLsizei width = static_cast<GLsizei>(c.width);
12512 GLsizei height = static_cast<GLsizei>(c.height);
12513 GLint border = static_cast<GLint>(c.border);
12514 GLenum format = static_cast<GLenum>(c.format);
12515 GLenum type = static_cast<GLenum>(c.type);
12516 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
12517 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
12518 uint32 pixels_size;
12519 uint32 async_upload_token = static_cast<uint32>(c.async_upload_token);
12520 uint32 sync_data_shm_id = static_cast<uint32>(c.sync_data_shm_id);
12521 uint32 sync_data_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
12523 base::ScopedClosureRunner scoped_completion_callback;
12524 if (async_upload_token) {
12525 base::Closure completion_closure =
12526 AsyncUploadTokenCompletionClosure(async_upload_token,
12527 sync_data_shm_id,
12528 sync_data_shm_offset);
12529 if (completion_closure.is_null())
12530 return error::kInvalidArguments;
12532 scoped_completion_callback.Reset(completion_closure);
12535 // TODO(epenner): Move this and copies of this memory validation
12536 // into ValidateTexImage2D step.
12537 if (!GLES2Util::ComputeImageDataSizes(
12538 width, height, 1, format, type, state_.unpack_alignment, &pixels_size,
12539 NULL, NULL)) {
12540 return error::kOutOfBounds;
12542 const void* pixels = NULL;
12543 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
12544 pixels = GetSharedMemoryAs<const void*>(
12545 pixels_shm_id, pixels_shm_offset, pixels_size);
12546 if (!pixels) {
12547 return error::kOutOfBounds;
12551 TextureManager::DoTextImage2DArguments args = {
12552 target, level, internal_format, width, height, border, format, type,
12553 pixels, pixels_size};
12554 TextureRef* texture_ref;
12555 // All the normal glTexSubImage2D validation.
12556 if (!texture_manager()->ValidateTexImage2D(
12557 &state_, "glAsyncTexImage2DCHROMIUM", args, &texture_ref)) {
12558 return error::kNoError;
12561 // Extra async validation.
12562 Texture* texture = texture_ref->texture();
12563 if (!ValidateAsyncTransfer(
12564 "glAsyncTexImage2DCHROMIUM", texture_ref, target, level, pixels))
12565 return error::kNoError;
12567 // Don't allow async redefinition of a textures.
12568 if (texture->IsDefined()) {
12569 LOCAL_SET_GL_ERROR(
12570 GL_INVALID_OPERATION,
12571 "glAsyncTexImage2DCHROMIUM", "already defined");
12572 return error::kNoError;
12575 if (!EnsureGPUMemoryAvailable(pixels_size)) {
12576 LOCAL_SET_GL_ERROR(
12577 GL_OUT_OF_MEMORY, "glAsyncTexImage2DCHROMIUM", "out of memory");
12578 return error::kNoError;
12581 // Setup the parameters.
12582 AsyncTexImage2DParams tex_params = {
12583 target, level, static_cast<GLenum>(internal_format),
12584 width, height, border, format, type};
12585 AsyncMemoryParams mem_params(
12586 GetSharedMemoryBuffer(c.pixels_shm_id), c.pixels_shm_offset, pixels_size);
12588 // Set up the async state if needed, and make the texture
12589 // immutable so the async state stays valid. The level info
12590 // is set up lazily when the transfer completes.
12591 AsyncPixelTransferDelegate* delegate =
12592 async_pixel_transfer_manager_->CreatePixelTransferDelegate(texture_ref,
12593 tex_params);
12594 texture->SetImmutable(true);
12596 delegate->AsyncTexImage2D(
12597 tex_params,
12598 mem_params,
12599 base::Bind(&TextureManager::SetLevelInfoFromParams,
12600 // The callback is only invoked if the transfer delegate still
12601 // exists, which implies through manager->texture_ref->state
12602 // ownership that both of these pointers are valid.
12603 base::Unretained(texture_manager()),
12604 base::Unretained(texture_ref),
12605 tex_params));
12606 return error::kNoError;
12609 error::Error GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM(
12610 uint32 immediate_data_size,
12611 const void* cmd_data) {
12612 const gles2::cmds::AsyncTexSubImage2DCHROMIUM& c =
12613 *static_cast<const gles2::cmds::AsyncTexSubImage2DCHROMIUM*>(cmd_data);
12614 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM");
12615 GLenum target = static_cast<GLenum>(c.target);
12616 GLint level = static_cast<GLint>(c.level);
12617 GLint xoffset = static_cast<GLint>(c.xoffset);
12618 GLint yoffset = static_cast<GLint>(c.yoffset);
12619 GLsizei width = static_cast<GLsizei>(c.width);
12620 GLsizei height = static_cast<GLsizei>(c.height);
12621 GLenum format = static_cast<GLenum>(c.format);
12622 GLenum type = static_cast<GLenum>(c.type);
12623 uint32 async_upload_token = static_cast<uint32>(c.async_upload_token);
12624 uint32 sync_data_shm_id = static_cast<uint32>(c.sync_data_shm_id);
12625 uint32 sync_data_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
12627 base::ScopedClosureRunner scoped_completion_callback;
12628 if (async_upload_token) {
12629 base::Closure completion_closure =
12630 AsyncUploadTokenCompletionClosure(async_upload_token,
12631 sync_data_shm_id,
12632 sync_data_shm_offset);
12633 if (completion_closure.is_null())
12634 return error::kInvalidArguments;
12636 scoped_completion_callback.Reset(completion_closure);
12639 // TODO(epenner): Move this and copies of this memory validation
12640 // into ValidateTexSubImage2D step.
12641 uint32 data_size;
12642 if (!GLES2Util::ComputeImageDataSizes(
12643 width, height, 1, format, type, state_.unpack_alignment, &data_size,
12644 NULL, NULL)) {
12645 return error::kOutOfBounds;
12647 const void* pixels = GetSharedMemoryAs<const void*>(
12648 c.data_shm_id, c.data_shm_offset, data_size);
12650 // All the normal glTexSubImage2D validation.
12651 error::Error error = error::kNoError;
12652 if (!ValidateTexSubImage2D(&error, "glAsyncTexSubImage2DCHROMIUM",
12653 target, level, xoffset, yoffset, width, height, format, type, pixels)) {
12654 return error;
12657 // Extra async validation.
12658 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
12659 &state_, target);
12660 Texture* texture = texture_ref->texture();
12661 if (!ValidateAsyncTransfer(
12662 "glAsyncTexSubImage2DCHROMIUM", texture_ref, target, level, pixels))
12663 return error::kNoError;
12665 // Guarantee async textures are always 'cleared' as follows:
12666 // - AsyncTexImage2D can not redefine an existing texture
12667 // - AsyncTexImage2D must initialize the entire image via non-null buffer.
12668 // - AsyncTexSubImage2D clears synchronously if not already cleared.
12669 // - Textures become immutable after an async call.
12670 // This way we know in all cases that an async texture is always clear.
12671 if (!texture->SafeToRenderFrom()) {
12672 if (!texture_manager()->ClearTextureLevel(this, texture_ref,
12673 target, level)) {
12674 LOCAL_SET_GL_ERROR(
12675 GL_OUT_OF_MEMORY,
12676 "glAsyncTexSubImage2DCHROMIUM", "dimensions too big");
12677 return error::kNoError;
12681 // Setup the parameters.
12682 AsyncTexSubImage2DParams tex_params = {target, level, xoffset, yoffset,
12683 width, height, format, type};
12684 AsyncMemoryParams mem_params(
12685 GetSharedMemoryBuffer(c.data_shm_id), c.data_shm_offset, data_size);
12686 AsyncPixelTransferDelegate* delegate =
12687 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
12688 if (!delegate) {
12689 // TODO(epenner): We may want to enforce exclusive use
12690 // of async APIs in which case this should become an error,
12691 // (the texture should have been async defined).
12692 AsyncTexImage2DParams define_params = {target, level,
12693 0, 0, 0, 0, 0, 0};
12694 texture->GetLevelSize(target, level, &define_params.width,
12695 &define_params.height);
12696 texture->GetLevelType(target, level, &define_params.type,
12697 &define_params.internal_format);
12698 // Set up the async state if needed, and make the texture
12699 // immutable so the async state stays valid.
12700 delegate = async_pixel_transfer_manager_->CreatePixelTransferDelegate(
12701 texture_ref, define_params);
12702 texture->SetImmutable(true);
12705 delegate->AsyncTexSubImage2D(tex_params, mem_params);
12706 return error::kNoError;
12709 error::Error GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM(
12710 uint32 immediate_data_size,
12711 const void* cmd_data) {
12712 const gles2::cmds::WaitAsyncTexImage2DCHROMIUM& c =
12713 *static_cast<const gles2::cmds::WaitAsyncTexImage2DCHROMIUM*>(cmd_data);
12714 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
12715 GLenum target = static_cast<GLenum>(c.target);
12717 if (GL_TEXTURE_2D != target) {
12718 LOCAL_SET_GL_ERROR(
12719 GL_INVALID_ENUM, "glWaitAsyncTexImage2DCHROMIUM", "target");
12720 return error::kNoError;
12722 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
12723 &state_, target);
12724 if (!texture_ref) {
12725 LOCAL_SET_GL_ERROR(
12726 GL_INVALID_OPERATION,
12727 "glWaitAsyncTexImage2DCHROMIUM", "unknown texture");
12728 return error::kNoError;
12730 AsyncPixelTransferDelegate* delegate =
12731 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
12732 if (!delegate) {
12733 LOCAL_SET_GL_ERROR(
12734 GL_INVALID_OPERATION,
12735 "glWaitAsyncTexImage2DCHROMIUM", "No async transfer started");
12736 return error::kNoError;
12738 delegate->WaitForTransferCompletion();
12739 ProcessFinishedAsyncTransfers();
12740 return error::kNoError;
12743 error::Error GLES2DecoderImpl::HandleWaitAllAsyncTexImage2DCHROMIUM(
12744 uint32 immediate_data_size,
12745 const void* data) {
12746 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
12748 GetAsyncPixelTransferManager()->WaitAllAsyncTexImage2D();
12749 ProcessFinishedAsyncTransfers();
12750 return error::kNoError;
12753 error::Error GLES2DecoderImpl::HandleUniformBlockBinding(
12754 uint32_t immediate_data_size, const void* cmd_data) {
12755 if (!unsafe_es3_apis_enabled())
12756 return error::kUnknownCommand;
12757 const gles2::cmds::UniformBlockBinding& c =
12758 *static_cast<const gles2::cmds::UniformBlockBinding*>(cmd_data);
12759 GLuint client_id = c.program;
12760 GLuint index = static_cast<GLuint>(c.index);
12761 GLuint binding = static_cast<GLuint>(c.binding);
12762 Program* program = GetProgramInfoNotShader(
12763 client_id, "glUniformBlockBinding");
12764 if (!program) {
12765 return error::kNoError;
12767 GLuint service_id = program->service_id();
12768 glUniformBlockBinding(service_id, index, binding);
12769 return error::kNoError;
12772 error::Error GLES2DecoderImpl::HandleClientWaitSync(
12773 uint32_t immediate_data_size, const void* cmd_data) {
12774 if (!unsafe_es3_apis_enabled())
12775 return error::kUnknownCommand;
12776 const gles2::cmds::ClientWaitSync& c =
12777 *static_cast<const gles2::cmds::ClientWaitSync*>(cmd_data);
12778 GLuint sync = static_cast<GLuint>(c.sync);
12779 GLbitfield flags = static_cast<GLbitfield>(c.flags);
12780 GLuint64 timeout = GLES2Util::MapTwoUint32ToUint64(c.timeout_0, c.timeout_1);
12781 typedef cmds::ClientWaitSync::Result Result;
12782 Result* result_dst = GetSharedMemoryAs<Result*>(
12783 c.result_shm_id, c.result_shm_offset, sizeof(*result_dst));
12784 if (!result_dst) {
12785 return error::kOutOfBounds;
12787 if (*result_dst != GL_WAIT_FAILED) {
12788 return error::kInvalidArguments;
12790 GLsync service_sync = 0;
12791 if (!group_->GetSyncServiceId(sync, &service_sync)) {
12792 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "ClientWaitSync", "invalid sync");
12793 return error::kNoError;
12795 *result_dst = glClientWaitSync(service_sync, flags, timeout);
12796 return error::kNoError;
12799 error::Error GLES2DecoderImpl::HandleWaitSync(
12800 uint32_t immediate_data_size, const void* cmd_data) {
12801 if (!unsafe_es3_apis_enabled())
12802 return error::kUnknownCommand;
12803 const gles2::cmds::WaitSync& c =
12804 *static_cast<const gles2::cmds::WaitSync*>(cmd_data);
12805 GLuint sync = static_cast<GLuint>(c.sync);
12806 GLbitfield flags = static_cast<GLbitfield>(c.flags);
12807 GLuint64 timeout = GLES2Util::MapTwoUint32ToUint64(c.timeout_0, c.timeout_1);
12808 GLsync service_sync = 0;
12809 if (!group_->GetSyncServiceId(sync, &service_sync)) {
12810 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "WaitSync", "invalid sync");
12811 return error::kNoError;
12813 glWaitSync(service_sync, flags, timeout);
12814 return error::kNoError;
12817 error::Error GLES2DecoderImpl::HandleMapBufferRange(
12818 uint32_t immediate_data_size, const void* cmd_data) {
12819 if (!unsafe_es3_apis_enabled()) {
12820 return error::kUnknownCommand;
12822 const gles2::cmds::MapBufferRange& c =
12823 *static_cast<const gles2::cmds::MapBufferRange*>(cmd_data);
12824 GLenum target = static_cast<GLenum>(c.target);
12825 GLbitfield access = static_cast<GLbitfield>(c.access);
12826 GLintptr offset = static_cast<GLintptr>(c.offset);
12827 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
12829 typedef cmds::MapBufferRange::Result Result;
12830 Result* result = GetSharedMemoryAs<Result*>(
12831 c.result_shm_id, c.result_shm_offset, sizeof(*result));
12832 if (!result) {
12833 return error::kOutOfBounds;
12835 if (*result != 0) {
12836 *result = 0;
12837 return error::kInvalidArguments;
12839 int8_t* mem =
12840 GetSharedMemoryAs<int8_t*>(c.data_shm_id, c.data_shm_offset, size);
12841 if (!mem) {
12842 return error::kOutOfBounds;
12845 GLbitfield mask = GL_MAP_INVALIDATE_BUFFER_BIT;
12846 if ((access & mask) == mask) {
12847 // TODO(zmo): To be on the safe side, always map
12848 // GL_MAP_INVALIDATE_BUFFER_BIT to GL_MAP_INVALIDATE_RANGE_BIT.
12849 access = (access & ~GL_MAP_INVALIDATE_BUFFER_BIT);
12850 access = (access | GL_MAP_INVALIDATE_RANGE_BIT);
12852 // TODO(zmo): Always filter out GL_MAP_UNSYNCHRONIZED_BIT to get rid of
12853 // undefined behaviors.
12854 mask = GL_MAP_READ_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
12855 if ((access & mask) == mask) {
12856 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "MapBufferRange",
12857 "incompatible access bits");
12858 return error::kNoError;
12860 access = (access & ~GL_MAP_UNSYNCHRONIZED_BIT);
12861 if ((access & GL_MAP_WRITE_BIT) == GL_MAP_WRITE_BIT &&
12862 (access & GL_MAP_INVALIDATE_RANGE_BIT) == 0) {
12863 access = (access | GL_MAP_READ_BIT);
12865 void* ptr = glMapBufferRange(target, offset, size, access);
12866 if (ptr == nullptr) {
12867 return error::kNoError;
12869 Buffer* buffer = buffer_manager()->GetBufferInfoForTarget(&state_, target);
12870 DCHECK(buffer);
12871 buffer->SetMappedRange(offset, size, access, ptr,
12872 GetSharedMemoryBuffer(c.data_shm_id));
12873 if ((access & GL_MAP_INVALIDATE_RANGE_BIT) == 0) {
12874 memcpy(mem, ptr, size);
12876 *result = 1;
12877 return error::kNoError;
12880 error::Error GLES2DecoderImpl::HandleUnmapBuffer(
12881 uint32_t immediate_data_size, const void* cmd_data) {
12882 if (!unsafe_es3_apis_enabled()) {
12883 return error::kUnknownCommand;
12885 const gles2::cmds::UnmapBuffer& c =
12886 *static_cast<const gles2::cmds::UnmapBuffer*>(cmd_data);
12887 GLenum target = static_cast<GLenum>(c.target);
12889 Buffer* buffer = buffer_manager()->GetBufferInfoForTarget(&state_, target);
12890 if (!buffer) {
12891 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "UnmapBuffer", "no buffer bound");
12892 return error::kNoError;
12894 const Buffer::MappedRange* mapped_range = buffer->GetMappedRange();
12895 if (!mapped_range) {
12896 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "UnmapBuffer",
12897 "buffer is unmapped");
12898 return error::kNoError;
12900 if ((mapped_range->access & GL_MAP_WRITE_BIT) == 0 ||
12901 (mapped_range->access & GL_MAP_FLUSH_EXPLICIT_BIT) ==
12902 GL_MAP_FLUSH_EXPLICIT_BIT) {
12903 // If we don't need to write back, or explict flush is required, no copying
12904 // back is needed.
12905 } else {
12906 void* mem = mapped_range->GetShmPointer();
12907 if (!mem) {
12908 return error::kOutOfBounds;
12910 DCHECK(mapped_range->pointer);
12911 memcpy(mapped_range->pointer, mem, mapped_range->size);
12913 buffer->RemoveMappedRange();
12914 GLboolean rt = glUnmapBuffer(target);
12915 if (rt == GL_FALSE) {
12916 // At this point, we have already done the necessary validation, so
12917 // GL_FALSE indicates data corruption.
12918 // TODO(zmo): We could redo the map / copy data / unmap to recover, but
12919 // the second unmap could still return GL_FALSE. For now, we simply lose
12920 // the contexts in the share group.
12921 LOG(ERROR) << "glUnmapBuffer unexpectedly returned GL_FALSE";
12922 // Need to lose current context before broadcasting!
12923 MarkContextLost(error::kGuilty);
12924 group_->LoseContexts(error::kInnocent);
12925 return error::kLostContext;
12927 return error::kNoError;
12930 void GLES2DecoderImpl::OnTextureRefDetachedFromFramebuffer(
12931 TextureRef* texture_ref) {
12932 Texture* texture = texture_ref->texture();
12933 DoDidUseTexImageIfNeeded(texture, texture->target());
12936 // Note that GL_LOST_CONTEXT is specific to GLES.
12937 // For desktop GL we have to query the reset status proactively.
12938 void GLES2DecoderImpl::OnContextLostError() {
12939 if (!WasContextLost()) {
12940 // Need to lose current context before broadcasting!
12941 CheckResetStatus();
12942 group_->LoseContexts(error::kUnknown);
12943 reset_by_robustness_extension_ = true;
12947 void GLES2DecoderImpl::OnOutOfMemoryError() {
12948 if (lose_context_when_out_of_memory_ && !WasContextLost()) {
12949 error::ContextLostReason other = error::kOutOfMemory;
12950 if (CheckResetStatus()) {
12951 other = error::kUnknown;
12952 } else {
12953 // Need to lose current context before broadcasting!
12954 MarkContextLost(error::kOutOfMemory);
12956 group_->LoseContexts(other);
12960 // Include the auto-generated part of this file. We split this because it means
12961 // we can easily edit the non-auto generated parts right here in this file
12962 // instead of having to edit some template or the code generator.
12963 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
12965 } // namespace gles2
12966 } // namespace gpu