Remove wpr.archive_info dependancy on page to avoid circular dependancies.
[chromium-blink-merge.git] / gpu / command_buffer / service / gles2_cmd_decoder.cc
bloba22c2f9b83e6f863d1d0e213dba7c857b685e56f
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 CompressedTexSubImage3D.
891 void DoCompressedTexSubImage3D(
892 GLenum target,
893 GLint level,
894 GLint xoffset,
895 GLint yoffset,
896 GLint zoffset,
897 GLsizei width,
898 GLsizei height,
899 GLsizei depth,
900 GLenum format,
901 GLsizei image_size,
902 const void* data);
904 // Wrapper for CopyTexImage2D.
905 void DoCopyTexImage2D(
906 GLenum target,
907 GLint level,
908 GLenum internal_format,
909 GLint x,
910 GLint y,
911 GLsizei width,
912 GLsizei height,
913 GLint border);
915 // Wrapper for SwapBuffers.
916 void DoSwapBuffers();
918 // Wrapper for SwapInterval.
919 void DoSwapInterval(int interval);
921 // Wrapper for CopyTexSubImage2D.
922 void DoCopyTexSubImage2D(
923 GLenum target,
924 GLint level,
925 GLint xoffset,
926 GLint yoffset,
927 GLint x,
928 GLint y,
929 GLsizei width,
930 GLsizei height);
932 // Validation for TexSubImage2D.
933 bool ValidateTexSubImage2D(
934 error::Error* error,
935 const char* function_name,
936 GLenum target,
937 GLint level,
938 GLint xoffset,
939 GLint yoffset,
940 GLsizei width,
941 GLsizei height,
942 GLenum format,
943 GLenum type,
944 const void * data);
946 // Wrapper for TexSubImage2D.
947 error::Error DoTexSubImage2D(
948 GLenum target,
949 GLint level,
950 GLint xoffset,
951 GLint yoffset,
952 GLsizei width,
953 GLsizei height,
954 GLenum format,
955 GLenum type,
956 const void * data);
958 // Extra validation for async tex(Sub)Image2D.
959 bool ValidateAsyncTransfer(
960 const char* function_name,
961 TextureRef* texture_ref,
962 GLenum target,
963 GLint level,
964 const void * data);
966 // Wrapper for TexImageIOSurface2DCHROMIUM.
967 void DoTexImageIOSurface2DCHROMIUM(
968 GLenum target,
969 GLsizei width,
970 GLsizei height,
971 GLuint io_surface_id,
972 GLuint plane);
974 void DoCopyTextureCHROMIUM(GLenum target,
975 GLuint source_id,
976 GLuint dest_id,
977 GLenum internal_format,
978 GLenum dest_type);
980 void DoCopySubTextureCHROMIUM(GLenum target,
981 GLuint source_id,
982 GLuint dest_id,
983 GLint xoffset,
984 GLint yoffset);
986 // Wrapper for TexStorage2DEXT.
987 void DoTexStorage2DEXT(
988 GLenum target,
989 GLint levels,
990 GLenum internal_format,
991 GLsizei width,
992 GLsizei height);
994 void DoProduceTextureCHROMIUM(GLenum target, const GLbyte* key);
995 void DoProduceTextureDirectCHROMIUM(GLuint texture, GLenum target,
996 const GLbyte* key);
997 void ProduceTextureRef(std::string func_name, TextureRef* texture_ref,
998 GLenum target, const GLbyte* data);
1000 void EnsureTextureForClientId(GLenum target, GLuint client_id);
1001 void DoConsumeTextureCHROMIUM(GLenum target, const GLbyte* key);
1002 void DoCreateAndConsumeTextureCHROMIUM(GLenum target, const GLbyte* key,
1003 GLuint client_id);
1005 bool DoIsValuebufferCHROMIUM(GLuint client_id);
1006 void DoBindValueBufferCHROMIUM(GLenum target, GLuint valuebuffer);
1007 void DoSubscribeValueCHROMIUM(GLenum target, GLenum subscription);
1008 void DoPopulateSubscribedValuesCHROMIUM(GLenum target);
1009 void DoUniformValueBufferCHROMIUM(GLint location,
1010 GLenum target,
1011 GLenum subscription);
1013 void DoBindTexImage2DCHROMIUM(
1014 GLenum target,
1015 GLint image_id);
1016 void DoReleaseTexImage2DCHROMIUM(
1017 GLenum target,
1018 GLint image_id);
1020 void DoTraceEndCHROMIUM(void);
1022 void DoDrawBuffersEXT(GLsizei count, const GLenum* bufs);
1024 void DoLoseContextCHROMIUM(GLenum current, GLenum other);
1026 void DoMatrixLoadfCHROMIUM(GLenum matrix_mode, const GLfloat* matrix);
1027 void DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode);
1029 // Creates a Program for the given program.
1030 Program* CreateProgram(
1031 GLuint client_id, GLuint service_id) {
1032 return program_manager()->CreateProgram(client_id, service_id);
1035 // Gets the program info for the given program. Returns NULL if none exists.
1036 Program* GetProgram(GLuint client_id) {
1037 return program_manager()->GetProgram(client_id);
1040 #if defined(NDEBUG)
1041 void LogClientServiceMapping(
1042 const char* /* function_name */,
1043 GLuint /* client_id */,
1044 GLuint /* service_id */) {
1046 template<typename T>
1047 void LogClientServiceForInfo(
1048 T* /* info */, GLuint /* client_id */, const char* /* function_name */) {
1050 #else
1051 void LogClientServiceMapping(
1052 const char* function_name, GLuint client_id, GLuint service_id) {
1053 if (service_logging_) {
1054 VLOG(1) << "[" << logger_.GetLogPrefix() << "] " << function_name
1055 << ": client_id = " << client_id
1056 << ", service_id = " << service_id;
1059 template<typename T>
1060 void LogClientServiceForInfo(
1061 T* info, GLuint client_id, const char* function_name) {
1062 if (info) {
1063 LogClientServiceMapping(function_name, client_id, info->service_id());
1066 #endif
1068 // Gets the program info for the given program. If it's not a program
1069 // generates a GL error. Returns NULL if not program.
1070 Program* GetProgramInfoNotShader(
1071 GLuint client_id, const char* function_name) {
1072 Program* program = GetProgram(client_id);
1073 if (!program) {
1074 if (GetShader(client_id)) {
1075 LOCAL_SET_GL_ERROR(
1076 GL_INVALID_OPERATION, function_name, "shader passed for program");
1077 } else {
1078 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "unknown program");
1081 LogClientServiceForInfo(program, client_id, function_name);
1082 return program;
1086 // Creates a Shader for the given shader.
1087 Shader* CreateShader(
1088 GLuint client_id,
1089 GLuint service_id,
1090 GLenum shader_type) {
1091 return shader_manager()->CreateShader(
1092 client_id, service_id, shader_type);
1095 // Gets the shader info for the given shader. Returns NULL if none exists.
1096 Shader* GetShader(GLuint client_id) {
1097 return shader_manager()->GetShader(client_id);
1100 // Gets the shader info for the given shader. If it's not a shader generates a
1101 // GL error. Returns NULL if not shader.
1102 Shader* GetShaderInfoNotProgram(
1103 GLuint client_id, const char* function_name) {
1104 Shader* shader = GetShader(client_id);
1105 if (!shader) {
1106 if (GetProgram(client_id)) {
1107 LOCAL_SET_GL_ERROR(
1108 GL_INVALID_OPERATION, function_name, "program passed for shader");
1109 } else {
1110 LOCAL_SET_GL_ERROR(
1111 GL_INVALID_VALUE, function_name, "unknown shader");
1114 LogClientServiceForInfo(shader, client_id, function_name);
1115 return shader;
1118 // Creates a buffer info for the given buffer.
1119 void CreateBuffer(GLuint client_id, GLuint service_id) {
1120 return buffer_manager()->CreateBuffer(client_id, service_id);
1123 // Gets the buffer info for the given buffer.
1124 Buffer* GetBuffer(GLuint client_id) {
1125 Buffer* buffer = buffer_manager()->GetBuffer(client_id);
1126 return buffer;
1129 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
1130 // on glDeleteBuffers so we can make sure the user does not try to render
1131 // with deleted buffers.
1132 void RemoveBuffer(GLuint client_id);
1134 // Creates a framebuffer info for the given framebuffer.
1135 void CreateFramebuffer(GLuint client_id, GLuint service_id) {
1136 return framebuffer_manager()->CreateFramebuffer(client_id, service_id);
1139 // Gets the framebuffer info for the given framebuffer.
1140 Framebuffer* GetFramebuffer(GLuint client_id) {
1141 return framebuffer_manager()->GetFramebuffer(client_id);
1144 // Removes the framebuffer info for the given framebuffer.
1145 void RemoveFramebuffer(GLuint client_id) {
1146 framebuffer_manager()->RemoveFramebuffer(client_id);
1149 // Creates a renderbuffer info for the given renderbuffer.
1150 void CreateRenderbuffer(GLuint client_id, GLuint service_id) {
1151 return renderbuffer_manager()->CreateRenderbuffer(
1152 client_id, service_id);
1155 // Gets the renderbuffer info for the given renderbuffer.
1156 Renderbuffer* GetRenderbuffer(GLuint client_id) {
1157 return renderbuffer_manager()->GetRenderbuffer(client_id);
1160 // Removes the renderbuffer info for the given renderbuffer.
1161 void RemoveRenderbuffer(GLuint client_id) {
1162 renderbuffer_manager()->RemoveRenderbuffer(client_id);
1165 // Creates a valuebuffer info for the given valuebuffer.
1166 void CreateValuebuffer(GLuint client_id) {
1167 return valuebuffer_manager()->CreateValuebuffer(client_id);
1170 // Gets the valuebuffer info for a given valuebuffer.
1171 Valuebuffer* GetValuebuffer(GLuint client_id) {
1172 return valuebuffer_manager()->GetValuebuffer(client_id);
1175 // Removes the valuebuffer info for the given valuebuffer.
1176 void RemoveValuebuffer(GLuint client_id) {
1177 valuebuffer_manager()->RemoveValuebuffer(client_id);
1180 // Gets the vertex attrib manager for the given vertex array.
1181 VertexAttribManager* GetVertexAttribManager(GLuint client_id) {
1182 VertexAttribManager* info =
1183 vertex_array_manager()->GetVertexAttribManager(client_id);
1184 return info;
1187 // Removes the vertex attrib manager for the given vertex array.
1188 void RemoveVertexAttribManager(GLuint client_id) {
1189 vertex_array_manager()->RemoveVertexAttribManager(client_id);
1192 // Creates a vertex attrib manager for the given vertex array.
1193 scoped_refptr<VertexAttribManager> CreateVertexAttribManager(
1194 GLuint client_id,
1195 GLuint service_id,
1196 bool client_visible) {
1197 return vertex_array_manager()->CreateVertexAttribManager(
1198 client_id, service_id, group_->max_vertex_attribs(), client_visible);
1201 void DoBindAttribLocation(GLuint client_id, GLuint index, const char* name);
1202 void DoBindUniformLocationCHROMIUM(
1203 GLuint client_id, GLint location, const char* name);
1205 error::Error GetAttribLocationHelper(
1206 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1207 const std::string& name_str);
1209 error::Error GetUniformLocationHelper(
1210 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1211 const std::string& name_str);
1213 error::Error GetFragDataLocationHelper(
1214 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1215 const std::string& name_str);
1217 // Wrapper for glShaderSource.
1218 void DoShaderSource(
1219 GLuint client_id, GLsizei count, const char** data, const GLint* length);
1221 // Wrapper for glTransformFeedbackVaryings.
1222 void DoTransformFeedbackVaryings(
1223 GLuint client_program_id, GLsizei count, const char* const* varyings,
1224 GLenum buffer_mode);
1226 // Clear any textures used by the current program.
1227 bool ClearUnclearedTextures();
1229 // Clears any uncleared attachments attached to the given frame buffer.
1230 // Returns false if there was a generated GL error.
1231 void ClearUnclearedAttachments(GLenum target, Framebuffer* framebuffer);
1233 // overridden from GLES2Decoder
1234 bool ClearLevel(Texture* texture,
1235 unsigned target,
1236 int level,
1237 unsigned internal_format,
1238 unsigned format,
1239 unsigned type,
1240 int width,
1241 int height,
1242 bool is_texture_immutable) override;
1244 // Restore all GL state that affects clearing.
1245 void RestoreClearState();
1247 // Remembers the state of some capabilities.
1248 // Returns: true if glEnable/glDisable should actually be called.
1249 bool SetCapabilityState(GLenum cap, bool enabled);
1251 // Check that the currently bound framebuffers are valid.
1252 // Generates GL error if not.
1253 bool CheckBoundFramebuffersValid(const char* func_name);
1255 // Check that the currently bound read framebuffer has a color image
1256 // attached. Generates GL error if not.
1257 bool CheckBoundReadFramebufferColorAttachment(const char* func_name);
1259 // Check that the currently bound read framebuffer's color image
1260 // isn't the target texture of the glCopyTex{Sub}Image2D.
1261 bool FormsTextureCopyingFeedbackLoop(TextureRef* texture, GLint level);
1263 // Check if a framebuffer meets our requirements.
1264 bool CheckFramebufferValid(
1265 Framebuffer* framebuffer,
1266 GLenum target,
1267 const char* func_name);
1269 // Check if the current valuebuffer exists and is valid. If not generates
1270 // the appropriate GL error. Returns true if the current valuebuffer is in
1271 // a usable state.
1272 bool CheckCurrentValuebuffer(const char* function_name);
1274 // Check if the current valuebuffer exists and is valiud and that the
1275 // value buffer is actually subscribed to the given subscription
1276 bool CheckCurrentValuebufferForSubscription(GLenum subscription,
1277 const char* function_name);
1279 // Check if the location can be used for the given subscription target. If not
1280 // generates the appropriate GL error. Returns true if the location is usable
1281 bool CheckSubscriptionTarget(GLint location,
1282 GLenum subscription,
1283 const char* function_name);
1285 // Checks if the current program exists and is valid. If not generates the
1286 // appropriate GL error. Returns true if the current program is in a usable
1287 // state.
1288 bool CheckCurrentProgram(const char* function_name);
1290 // Checks if the current program exists and is valid and that location is not
1291 // -1. If the current program is not valid generates the appropriate GL
1292 // error. Returns true if the current program is in a usable state and
1293 // location is not -1.
1294 bool CheckCurrentProgramForUniform(GLint location, const char* function_name);
1296 // Checks if the current program samples a texture that is also the color
1297 // image of the current bound framebuffer, i.e., the source and destination
1298 // of the draw operation are the same.
1299 bool CheckDrawingFeedbackLoops();
1301 // Checks if |api_type| is valid for the given uniform
1302 // If the api type is not valid generates the appropriate GL
1303 // error. Returns true if |api_type| is valid for the uniform
1304 bool CheckUniformForApiType(const Program::UniformInfo* info,
1305 const char* function_name,
1306 Program::UniformApiType api_type);
1308 // Gets the type of a uniform for a location in the current program. Sets GL
1309 // errors if the current program is not valid. Returns true if the current
1310 // program is valid and the location exists. Adjusts count so it
1311 // does not overflow the uniform.
1312 bool PrepForSetUniformByLocation(GLint fake_location,
1313 const char* function_name,
1314 Program::UniformApiType api_type,
1315 GLint* real_location,
1316 GLenum* type,
1317 GLsizei* count);
1319 // Gets the service id for any simulated backbuffer fbo.
1320 GLuint GetBackbufferServiceId() const;
1322 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
1323 bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
1325 // Helper for glGetVertexAttrib
1326 void GetVertexAttribHelper(
1327 const VertexAttrib* attrib, GLenum pname, GLint* param);
1329 // Wrapper for glActiveTexture
1330 void DoActiveTexture(GLenum texture_unit);
1332 // Wrapper for glAttachShader
1333 void DoAttachShader(GLuint client_program_id, GLint client_shader_id);
1335 // Wrapper for glBindBuffer since we need to track the current targets.
1336 void DoBindBuffer(GLenum target, GLuint buffer);
1338 // Wrapper for glBindFramebuffer since we need to track the current targets.
1339 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
1341 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1342 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
1344 // Wrapper for glBindTexture since we need to track the current targets.
1345 void DoBindTexture(GLenum target, GLuint texture);
1347 // Wrapper for glBindVertexArrayOES
1348 void DoBindVertexArrayOES(GLuint array);
1349 void EmulateVertexArrayState();
1351 // Wrapper for glBlitFramebufferCHROMIUM.
1352 void DoBlitFramebufferCHROMIUM(
1353 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
1354 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
1355 GLbitfield mask, GLenum filter);
1357 // Wrapper for glBufferSubData.
1358 void DoBufferSubData(
1359 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
1361 // Wrapper for glCheckFramebufferStatus
1362 GLenum DoCheckFramebufferStatus(GLenum target);
1364 // Wrapper for glClear
1365 error::Error DoClear(GLbitfield mask);
1367 // Wrappers for various state.
1368 void DoDepthRangef(GLclampf znear, GLclampf zfar);
1369 void DoSampleCoverage(GLclampf value, GLboolean invert);
1371 // Wrapper for glCompileShader.
1372 void DoCompileShader(GLuint shader);
1374 // Wrapper for glDetachShader
1375 void DoDetachShader(GLuint client_program_id, GLint client_shader_id);
1377 // Wrapper for glDisable
1378 void DoDisable(GLenum cap);
1380 // Wrapper for glDisableVertexAttribArray.
1381 void DoDisableVertexAttribArray(GLuint index);
1383 // Wrapper for glDiscardFramebufferEXT, since we need to track undefined
1384 // attachments.
1385 void DoDiscardFramebufferEXT(GLenum target,
1386 GLsizei numAttachments,
1387 const GLenum* attachments);
1389 // Wrapper for glEnable
1390 void DoEnable(GLenum cap);
1392 // Wrapper for glEnableVertexAttribArray.
1393 void DoEnableVertexAttribArray(GLuint index);
1395 // Wrapper for glFinish.
1396 void DoFinish();
1398 // Wrapper for glFlush.
1399 void DoFlush();
1401 // Wrapper for glFramebufferRenderbufffer.
1402 void DoFramebufferRenderbuffer(
1403 GLenum target, GLenum attachment, GLenum renderbuffertarget,
1404 GLuint renderbuffer);
1406 // Wrapper for glFramebufferTexture2D.
1407 void DoFramebufferTexture2D(
1408 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
1409 GLint level);
1411 // Wrapper for glFramebufferTexture2DMultisampleEXT.
1412 void DoFramebufferTexture2DMultisample(
1413 GLenum target, GLenum attachment, GLenum textarget,
1414 GLuint texture, GLint level, GLsizei samples);
1416 // Common implementation for both DoFramebufferTexture2D wrappers.
1417 void DoFramebufferTexture2DCommon(const char* name,
1418 GLenum target, GLenum attachment, GLenum textarget,
1419 GLuint texture, GLint level, GLsizei samples);
1421 // Wrapper for glFramebufferTextureLayer.
1422 void DoFramebufferTextureLayer(
1423 GLenum target, GLenum attachment, GLuint texture, GLint level,
1424 GLint layer);
1426 // Wrapper for glGenerateMipmap
1427 void DoGenerateMipmap(GLenum target);
1429 // Helper for DoGetBooleanv, Floatv, and Intergerv to adjust pname
1430 // to account for different pname values defined in different extension
1431 // variants.
1432 GLenum AdjustGetPname(GLenum pname);
1434 // Wrapper for DoGetBooleanv.
1435 void DoGetBooleanv(GLenum pname, GLboolean* params);
1437 // Wrapper for DoGetFloatv.
1438 void DoGetFloatv(GLenum pname, GLfloat* params);
1440 // Wrapper for glGetFramebufferAttachmentParameteriv.
1441 void DoGetFramebufferAttachmentParameteriv(
1442 GLenum target, GLenum attachment, GLenum pname, GLint* params);
1444 // Wrapper for glGetInteger64v.
1445 void DoGetInteger64v(GLenum pname, GLint64* params);
1447 // Wrapper for glGetIntegerv.
1448 void DoGetIntegerv(GLenum pname, GLint* params);
1450 // Gets the max value in a range in a buffer.
1451 GLuint DoGetMaxValueInBufferCHROMIUM(
1452 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset);
1454 // Wrapper for glGetBufferParameteriv.
1455 void DoGetBufferParameteriv(
1456 GLenum target, GLenum pname, GLint* params);
1458 // Wrapper for glGetProgramiv.
1459 void DoGetProgramiv(
1460 GLuint program_id, GLenum pname, GLint* params);
1462 // Wrapper for glRenderbufferParameteriv.
1463 void DoGetRenderbufferParameteriv(
1464 GLenum target, GLenum pname, GLint* params);
1466 // Wrapper for glGetShaderiv
1467 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
1469 // Wrappers for glGetTexParameter.
1470 void DoGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params);
1471 void DoGetTexParameteriv(GLenum target, GLenum pname, GLint* params);
1472 void InitTextureMaxAnisotropyIfNeeded(GLenum target, GLenum pname);
1474 // Wrappers for glGetVertexAttrib.
1475 void DoGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params);
1476 void DoGetVertexAttribiv(GLuint index, GLenum pname, GLint *params);
1478 // Wrappers for glIsXXX functions.
1479 bool DoIsEnabled(GLenum cap);
1480 bool DoIsBuffer(GLuint client_id);
1481 bool DoIsFramebuffer(GLuint client_id);
1482 bool DoIsProgram(GLuint client_id);
1483 bool DoIsRenderbuffer(GLuint client_id);
1484 bool DoIsShader(GLuint client_id);
1485 bool DoIsTexture(GLuint client_id);
1486 bool DoIsVertexArrayOES(GLuint client_id);
1488 // Wrapper for glLinkProgram
1489 void DoLinkProgram(GLuint program);
1491 // Wrapper for glRenderbufferStorage.
1492 void DoRenderbufferStorage(
1493 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
1495 // Handler for glRenderbufferStorageMultisampleCHROMIUM.
1496 void DoRenderbufferStorageMultisampleCHROMIUM(
1497 GLenum target, GLsizei samples, GLenum internalformat,
1498 GLsizei width, GLsizei height);
1500 // Handler for glRenderbufferStorageMultisampleEXT
1501 // (multisampled_render_to_texture).
1502 void DoRenderbufferStorageMultisampleEXT(
1503 GLenum target, GLsizei samples, GLenum internalformat,
1504 GLsizei width, GLsizei height);
1506 // Common validation for multisample extensions.
1507 bool ValidateRenderbufferStorageMultisample(GLsizei samples,
1508 GLenum internalformat,
1509 GLsizei width,
1510 GLsizei height);
1512 // Verifies that the currently bound multisample renderbuffer is valid
1513 // Very slow! Only done on platforms with driver bugs that return invalid
1514 // buffers under memory pressure
1515 bool VerifyMultisampleRenderbufferIntegrity(
1516 GLuint renderbuffer, GLenum format);
1518 // Wrapper for glReleaseShaderCompiler.
1519 void DoReleaseShaderCompiler() { }
1521 // Wrappers for glSamplerParameter*v functions.
1522 void DoSamplerParameterfv(
1523 GLuint sampler, GLenum pname, const GLfloat* params);
1524 void DoSamplerParameteriv(GLuint sampler, GLenum pname, const GLint* params);
1526 // Wrappers for glTexParameter functions.
1527 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
1528 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
1529 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
1530 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
1532 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1533 // spec only these 2 functions can be used to set sampler uniforms.
1534 void DoUniform1i(GLint fake_location, GLint v0);
1535 void DoUniform1iv(GLint fake_location, GLsizei count, const GLint* value);
1536 void DoUniform2iv(GLint fake_location, GLsizei count, const GLint* value);
1537 void DoUniform3iv(GLint fake_location, GLsizei count, const GLint* value);
1538 void DoUniform4iv(GLint fake_location, GLsizei count, const GLint* value);
1540 // Wrappers for glUniformfv because some drivers don't correctly accept
1541 // bool uniforms.
1542 void DoUniform1fv(GLint fake_location, GLsizei count, const GLfloat* value);
1543 void DoUniform2fv(GLint fake_location, GLsizei count, const GLfloat* value);
1544 void DoUniform3fv(GLint fake_location, GLsizei count, const GLfloat* value);
1545 void DoUniform4fv(GLint fake_location, GLsizei count, const GLfloat* value);
1547 void DoUniformMatrix2fv(
1548 GLint fake_location, GLsizei count, GLboolean transpose,
1549 const GLfloat* value);
1550 void DoUniformMatrix3fv(
1551 GLint fake_location, GLsizei count, GLboolean transpose,
1552 const GLfloat* value);
1553 void DoUniformMatrix4fv(
1554 GLint fake_location, GLsizei count, GLboolean transpose,
1555 const GLfloat* value);
1557 bool SetVertexAttribValue(
1558 const char* function_name, GLuint index, const GLfloat* value);
1560 // Wrappers for glVertexAttrib??
1561 void DoVertexAttrib1f(GLuint index, GLfloat v0);
1562 void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
1563 void DoVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
1564 void DoVertexAttrib4f(
1565 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
1566 void DoVertexAttrib1fv(GLuint index, const GLfloat *v);
1567 void DoVertexAttrib2fv(GLuint index, const GLfloat *v);
1568 void DoVertexAttrib3fv(GLuint index, const GLfloat *v);
1569 void DoVertexAttrib4fv(GLuint index, const GLfloat *v);
1571 // Wrapper for glViewport
1572 void DoViewport(GLint x, GLint y, GLsizei width, GLsizei height);
1574 // Wrapper for glUseProgram
1575 void DoUseProgram(GLuint program);
1577 // Wrapper for glValidateProgram.
1578 void DoValidateProgram(GLuint program_client_id);
1580 void DoInsertEventMarkerEXT(GLsizei length, const GLchar* marker);
1581 void DoPushGroupMarkerEXT(GLsizei length, const GLchar* group);
1582 void DoPopGroupMarkerEXT(void);
1584 // Gets the number of values that will be returned by glGetXXX. Returns
1585 // false if pname is unknown.
1586 bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
1588 // Checks if the current program and vertex attributes are valid for drawing.
1589 bool IsDrawValid(
1590 const char* function_name, GLuint max_vertex_accessed, bool instanced,
1591 GLsizei primcount);
1593 // Returns true if successful, simulated will be true if attrib0 was
1594 // simulated.
1595 bool SimulateAttrib0(
1596 const char* function_name, GLuint max_vertex_accessed, bool* simulated);
1597 void RestoreStateForAttrib(GLuint attrib, bool restore_array_binding);
1599 // If an image is bound to texture, this will call Will/DidUseTexImage
1600 // if needed.
1601 void DoWillUseTexImageIfNeeded(Texture* texture, GLenum textarget);
1602 void DoDidUseTexImageIfNeeded(Texture* texture, GLenum textarget);
1604 // Returns false if textures were replaced.
1605 bool PrepareTexturesForRender();
1606 void RestoreStateForTextures();
1608 // Returns true if GL_FIXED attribs were simulated.
1609 bool SimulateFixedAttribs(
1610 const char* function_name,
1611 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount);
1612 void RestoreStateForSimulatedFixedAttribs();
1614 // Handle DrawArrays and DrawElements for both instanced and non-instanced
1615 // cases (primcount is always 1 for non-instanced).
1616 error::Error DoDrawArrays(
1617 const char* function_name,
1618 bool instanced, GLenum mode, GLint first, GLsizei count,
1619 GLsizei primcount);
1620 error::Error DoDrawElements(
1621 const char* function_name,
1622 bool instanced, GLenum mode, GLsizei count, GLenum type,
1623 int32 offset, GLsizei primcount);
1625 GLenum GetBindTargetForSamplerType(GLenum type) {
1626 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
1627 type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB);
1628 switch (type) {
1629 case GL_SAMPLER_2D:
1630 return GL_TEXTURE_2D;
1631 case GL_SAMPLER_CUBE:
1632 return GL_TEXTURE_CUBE_MAP;
1633 case GL_SAMPLER_EXTERNAL_OES:
1634 return GL_TEXTURE_EXTERNAL_OES;
1635 case GL_SAMPLER_2D_RECT_ARB:
1636 return GL_TEXTURE_RECTANGLE_ARB;
1639 NOTREACHED();
1640 return 0;
1643 // Gets the framebuffer info for a particular target.
1644 Framebuffer* GetFramebufferInfoForTarget(GLenum target) {
1645 Framebuffer* framebuffer = NULL;
1646 switch (target) {
1647 case GL_FRAMEBUFFER:
1648 case GL_DRAW_FRAMEBUFFER_EXT:
1649 framebuffer = framebuffer_state_.bound_draw_framebuffer.get();
1650 break;
1651 case GL_READ_FRAMEBUFFER_EXT:
1652 framebuffer = framebuffer_state_.bound_read_framebuffer.get();
1653 break;
1654 default:
1655 NOTREACHED();
1656 break;
1658 return framebuffer;
1661 Renderbuffer* GetRenderbufferInfoForTarget(
1662 GLenum target) {
1663 Renderbuffer* renderbuffer = NULL;
1664 switch (target) {
1665 case GL_RENDERBUFFER:
1666 renderbuffer = state_.bound_renderbuffer.get();
1667 break;
1668 default:
1669 NOTREACHED();
1670 break;
1672 return renderbuffer;
1675 // Validates the program and location for a glGetUniform call and returns
1676 // a SizeResult setup to receive the result. Returns true if glGetUniform
1677 // should be called.
1678 template <class T>
1679 bool GetUniformSetup(GLuint program,
1680 GLint fake_location,
1681 uint32 shm_id,
1682 uint32 shm_offset,
1683 error::Error* error,
1684 GLint* real_location,
1685 GLuint* service_id,
1686 SizedResult<T>** result,
1687 GLenum* result_type,
1688 GLsizei* result_size);
1690 bool WasContextLost() const override;
1691 bool WasContextLostByRobustnessExtension() const override;
1692 void MarkContextLost(error::ContextLostReason reason) override;
1693 bool CheckResetStatus();
1695 #if defined(OS_MACOSX)
1696 void ReleaseIOSurfaceForTexture(GLuint texture_id);
1697 #endif
1699 bool ValidateCompressedTexDimensions(
1700 const char* function_name, GLenum target, GLint level,
1701 GLsizei width, GLsizei height, GLsizei depth, GLenum format);
1702 bool ValidateCompressedTexFuncData(
1703 const char* function_name, GLsizei width, GLsizei height, GLsizei depth,
1704 GLenum format, GLsizei size);
1705 bool ValidateCompressedTexSubDimensions(
1706 const char* function_name,
1707 GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
1708 GLsizei width, GLsizei height, GLsizei depth, GLenum format,
1709 Texture* texture);
1710 bool ValidateCopyTextureCHROMIUM(const char* function_name,
1711 GLenum target,
1712 TextureRef* source_texture_ref,
1713 TextureRef* dest_texture_ref,
1714 GLenum dest_internal_format);
1716 void RenderWarning(const char* filename, int line, const std::string& msg);
1717 void PerformanceWarning(
1718 const char* filename, int line, const std::string& msg);
1720 const FeatureInfo::FeatureFlags& features() const {
1721 return feature_info_->feature_flags();
1724 const FeatureInfo::Workarounds& workarounds() const {
1725 return feature_info_->workarounds();
1728 bool ShouldDeferDraws() {
1729 return !offscreen_target_frame_buffer_.get() &&
1730 framebuffer_state_.bound_draw_framebuffer.get() == NULL &&
1731 surface_->DeferDraws();
1734 bool ShouldDeferReads() {
1735 return !offscreen_target_frame_buffer_.get() &&
1736 framebuffer_state_.bound_read_framebuffer.get() == NULL &&
1737 surface_->DeferDraws();
1740 bool IsRobustnessSupported() {
1741 return has_robustness_extension_ &&
1742 context_->WasAllocatedUsingRobustnessExtension();
1745 error::Error WillAccessBoundFramebufferForDraw() {
1746 if (ShouldDeferDraws())
1747 return error::kDeferCommandUntilLater;
1748 if (!offscreen_target_frame_buffer_.get() &&
1749 !framebuffer_state_.bound_draw_framebuffer.get() &&
1750 !surface_->SetBackbufferAllocation(true))
1751 return error::kLostContext;
1752 return error::kNoError;
1755 error::Error WillAccessBoundFramebufferForRead() {
1756 if (ShouldDeferReads())
1757 return error::kDeferCommandUntilLater;
1758 if (!offscreen_target_frame_buffer_.get() &&
1759 !framebuffer_state_.bound_read_framebuffer.get() &&
1760 !surface_->SetBackbufferAllocation(true))
1761 return error::kLostContext;
1762 return error::kNoError;
1765 // Set remaining commands to process to 0 to force DoCommands to return
1766 // and allow context preemption and GPU watchdog checks in GpuScheduler().
1767 void ExitCommandProcessingEarly() { commands_to_process_ = 0; }
1769 void ProcessPendingReadPixels();
1770 void FinishReadPixels(const cmds::ReadPixels& c, GLuint buffer);
1772 // Generate a member function prototype for each command in an automated and
1773 // typesafe way.
1774 #define GLES2_CMD_OP(name) \
1775 Error Handle##name(uint32 immediate_data_size, const void* data);
1777 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1779 #undef GLES2_CMD_OP
1781 // The GL context this decoder renders to on behalf of the client.
1782 scoped_refptr<gfx::GLSurface> surface_;
1783 scoped_refptr<gfx::GLContext> context_;
1785 // The ContextGroup for this decoder uses to track resources.
1786 scoped_refptr<ContextGroup> group_;
1788 DebugMarkerManager debug_marker_manager_;
1789 Logger logger_;
1791 // All the state for this context.
1792 ContextState state_;
1794 // Current width and height of the offscreen frame buffer.
1795 gfx::Size offscreen_size_;
1797 // Util to help with GL.
1798 GLES2Util util_;
1800 // unpack flip y as last set by glPixelStorei
1801 bool unpack_flip_y_;
1803 // unpack (un)premultiply alpha as last set by glPixelStorei
1804 bool unpack_premultiply_alpha_;
1805 bool unpack_unpremultiply_alpha_;
1807 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1808 GLuint attrib_0_buffer_id_;
1810 // The value currently in attrib_0.
1811 Vec4 attrib_0_value_;
1813 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1814 bool attrib_0_buffer_matches_value_;
1816 // The size of attrib 0.
1817 GLsizei attrib_0_size_;
1819 // The buffer used to simulate GL_FIXED attribs.
1820 GLuint fixed_attrib_buffer_id_;
1822 // The size of fiixed attrib buffer.
1823 GLsizei fixed_attrib_buffer_size_;
1825 // The offscreen frame buffer that the client renders to. With EGL, the
1826 // depth and stencil buffers are separate. With regular GL there is a single
1827 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1828 // offscreen_target_stencil_render_buffer_ is unused.
1829 scoped_ptr<BackFramebuffer> offscreen_target_frame_buffer_;
1830 scoped_ptr<BackTexture> offscreen_target_color_texture_;
1831 scoped_ptr<BackRenderbuffer> offscreen_target_color_render_buffer_;
1832 scoped_ptr<BackRenderbuffer> offscreen_target_depth_render_buffer_;
1833 scoped_ptr<BackRenderbuffer> offscreen_target_stencil_render_buffer_;
1834 GLenum offscreen_target_color_format_;
1835 GLenum offscreen_target_depth_format_;
1836 GLenum offscreen_target_stencil_format_;
1837 GLsizei offscreen_target_samples_;
1838 GLboolean offscreen_target_buffer_preserved_;
1840 // The copy that is saved when SwapBuffers is called.
1841 scoped_ptr<BackFramebuffer> offscreen_saved_frame_buffer_;
1842 scoped_ptr<BackTexture> offscreen_saved_color_texture_;
1843 scoped_refptr<TextureRef>
1844 offscreen_saved_color_texture_info_;
1846 // The copy that is used as the destination for multi-sample resolves.
1847 scoped_ptr<BackFramebuffer> offscreen_resolved_frame_buffer_;
1848 scoped_ptr<BackTexture> offscreen_resolved_color_texture_;
1849 GLenum offscreen_saved_color_format_;
1851 scoped_ptr<QueryManager> query_manager_;
1853 scoped_ptr<VertexArrayManager> vertex_array_manager_;
1855 scoped_ptr<ImageManager> image_manager_;
1857 base::Callback<void(gfx::Size, float)> resize_callback_;
1859 WaitSyncPointCallback wait_sync_point_callback_;
1861 ShaderCacheCallback shader_cache_callback_;
1863 scoped_ptr<AsyncPixelTransferManager> async_pixel_transfer_manager_;
1865 // The format of the back buffer_
1866 GLenum back_buffer_color_format_;
1867 bool back_buffer_has_depth_;
1868 bool back_buffer_has_stencil_;
1870 bool surfaceless_;
1872 // Backbuffer attachments that are currently undefined.
1873 uint32 backbuffer_needs_clear_bits_;
1875 // The current decoder error communicates the decoder error through command
1876 // processing functions that do not return the error value. Should be set only
1877 // if not returning an error.
1878 error::Error current_decoder_error_;
1880 bool use_shader_translator_;
1881 scoped_refptr<ShaderTranslatorInterface> vertex_translator_;
1882 scoped_refptr<ShaderTranslatorInterface> fragment_translator_;
1884 DisallowedFeatures disallowed_features_;
1886 // Cached from ContextGroup
1887 const Validators* validators_;
1888 scoped_refptr<FeatureInfo> feature_info_;
1890 int frame_number_;
1892 // Number of commands remaining to be processed in DoCommands().
1893 int commands_to_process_;
1895 bool has_robustness_extension_;
1896 error::ContextLostReason context_lost_reason_;
1897 bool context_was_lost_;
1898 bool reset_by_robustness_extension_;
1899 bool supports_post_sub_buffer_;
1901 // These flags are used to override the state of the shared feature_info_
1902 // member. Because the same FeatureInfo instance may be shared among many
1903 // contexts, the assumptions on the availablity of extensions in WebGL
1904 // contexts may be broken. These flags override the shared state to preserve
1905 // WebGL semantics.
1906 bool force_webgl_glsl_validation_;
1907 bool derivatives_explicitly_enabled_;
1908 bool frag_depth_explicitly_enabled_;
1909 bool draw_buffers_explicitly_enabled_;
1910 bool shader_texture_lod_explicitly_enabled_;
1912 bool compile_shader_always_succeeds_;
1914 // An optional behaviour to lose the context and group when OOM.
1915 bool lose_context_when_out_of_memory_;
1917 // Log extra info.
1918 bool service_logging_;
1920 #if defined(OS_MACOSX)
1921 typedef std::map<GLuint, IOSurfaceRef> TextureToIOSurfaceMap;
1922 TextureToIOSurfaceMap texture_to_io_surface_map_;
1923 #endif
1925 scoped_ptr<CopyTextureCHROMIUMResourceManager> copy_texture_CHROMIUM_;
1926 scoped_ptr<ClearFramebufferResourceManager> clear_framebuffer_blit_;
1928 // Cached values of the currently assigned viewport dimensions.
1929 GLsizei viewport_max_width_;
1930 GLsizei viewport_max_height_;
1932 // Command buffer stats.
1933 base::TimeDelta total_processing_commands_time_;
1935 // States related to each manager.
1936 DecoderTextureState texture_state_;
1937 DecoderFramebufferState framebuffer_state_;
1939 scoped_ptr<GPUTracer> gpu_tracer_;
1940 scoped_ptr<GPUStateTracer> gpu_state_tracer_;
1941 const unsigned char* cb_command_trace_category_;
1942 const unsigned char* gpu_decoder_category_;
1943 int gpu_trace_level_;
1944 bool gpu_trace_commands_;
1945 bool gpu_debug_commands_;
1947 std::queue<linked_ptr<FenceCallback> > pending_readpixel_fences_;
1949 // Used to validate multisample renderbuffers if needed
1950 GLuint validation_texture_;
1951 GLuint validation_fbo_multisample_;
1952 GLuint validation_fbo_;
1954 typedef gpu::gles2::GLES2Decoder::Error (GLES2DecoderImpl::*CmdHandler)(
1955 uint32 immediate_data_size,
1956 const void* data);
1958 // A struct to hold info about each command.
1959 struct CommandInfo {
1960 CmdHandler cmd_handler;
1961 uint8 arg_flags; // How to handle the arguments for this command
1962 uint8 cmd_flags; // How to handle this command
1963 uint16 arg_count; // How many arguments are expected for this command.
1966 // A table of CommandInfo for all the commands.
1967 static const CommandInfo command_info[kNumCommands - kStartPoint];
1969 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
1972 const GLES2DecoderImpl::CommandInfo GLES2DecoderImpl::command_info[] = {
1973 #define GLES2_CMD_OP(name) \
1975 &GLES2DecoderImpl::Handle##name, cmds::name::kArgFlags, \
1976 cmds::name::cmd_flags, \
1977 sizeof(cmds::name) / sizeof(CommandBufferEntry) - 1, \
1979 , /* NOLINT */
1980 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1981 #undef GLES2_CMD_OP
1984 ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(
1985 const char* function_name, ErrorState* error_state)
1986 : function_name_(function_name),
1987 error_state_(error_state) {
1988 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state_, function_name_);
1991 ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
1992 ERRORSTATE_CLEAR_REAL_GL_ERRORS(error_state_, function_name_);
1995 static void RestoreCurrentTextureBindings(ContextState* state, GLenum target) {
1996 TextureUnit& info = state->texture_units[0];
1997 GLuint last_id;
1998 scoped_refptr<TextureRef> texture_ref;
1999 switch (target) {
2000 case GL_TEXTURE_2D:
2001 texture_ref = info.bound_texture_2d;
2002 break;
2003 case GL_TEXTURE_CUBE_MAP:
2004 texture_ref = info.bound_texture_cube_map;
2005 break;
2006 case GL_TEXTURE_EXTERNAL_OES:
2007 texture_ref = info.bound_texture_external_oes;
2008 break;
2009 case GL_TEXTURE_RECTANGLE_ARB:
2010 texture_ref = info.bound_texture_rectangle_arb;
2011 break;
2012 default:
2013 NOTREACHED();
2014 break;
2016 if (texture_ref.get()) {
2017 last_id = texture_ref->service_id();
2018 } else {
2019 last_id = 0;
2022 glBindTexture(target, last_id);
2023 glActiveTexture(GL_TEXTURE0 + state->active_texture_unit);
2026 ScopedTextureBinder::ScopedTextureBinder(ContextState* state,
2027 GLuint id,
2028 GLenum target)
2029 : state_(state),
2030 target_(target) {
2031 ScopedGLErrorSuppressor suppressor(
2032 "ScopedTextureBinder::ctor", state_->GetErrorState());
2034 // TODO(apatrick): Check if there are any other states that need to be reset
2035 // before binding a new texture.
2036 glActiveTexture(GL_TEXTURE0);
2037 glBindTexture(target, id);
2040 ScopedTextureBinder::~ScopedTextureBinder() {
2041 ScopedGLErrorSuppressor suppressor(
2042 "ScopedTextureBinder::dtor", state_->GetErrorState());
2043 RestoreCurrentTextureBindings(state_, target_);
2046 ScopedRenderBufferBinder::ScopedRenderBufferBinder(ContextState* state,
2047 GLuint id)
2048 : state_(state) {
2049 ScopedGLErrorSuppressor suppressor(
2050 "ScopedRenderBufferBinder::ctor", state_->GetErrorState());
2051 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
2054 ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
2055 ScopedGLErrorSuppressor suppressor(
2056 "ScopedRenderBufferBinder::dtor", state_->GetErrorState());
2057 state_->RestoreRenderbufferBindings();
2060 ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
2061 GLuint id)
2062 : decoder_(decoder) {
2063 ScopedGLErrorSuppressor suppressor(
2064 "ScopedFrameBufferBinder::ctor", decoder_->GetErrorState());
2065 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
2066 decoder->OnFboChanged();
2069 ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
2070 ScopedGLErrorSuppressor suppressor(
2071 "ScopedFrameBufferBinder::dtor", decoder_->GetErrorState());
2072 decoder_->RestoreCurrentFramebufferBindings();
2075 ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
2076 GLES2DecoderImpl* decoder, bool enforce_internal_framebuffer, bool internal)
2077 : decoder_(decoder) {
2078 resolve_and_bind_ = (
2079 decoder_->offscreen_target_frame_buffer_.get() &&
2080 decoder_->IsOffscreenBufferMultisampled() &&
2081 (!decoder_->framebuffer_state_.bound_read_framebuffer.get() ||
2082 enforce_internal_framebuffer));
2083 if (!resolve_and_bind_)
2084 return;
2086 ScopedGLErrorSuppressor suppressor(
2087 "ScopedResolvedFrameBufferBinder::ctor", decoder_->GetErrorState());
2088 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT,
2089 decoder_->offscreen_target_frame_buffer_->id());
2090 GLuint targetid;
2091 if (internal) {
2092 if (!decoder_->offscreen_resolved_frame_buffer_.get()) {
2093 decoder_->offscreen_resolved_frame_buffer_.reset(
2094 new BackFramebuffer(decoder_));
2095 decoder_->offscreen_resolved_frame_buffer_->Create();
2096 decoder_->offscreen_resolved_color_texture_.reset(
2097 new BackTexture(decoder->memory_tracker(), &decoder->state_));
2098 decoder_->offscreen_resolved_color_texture_->Create();
2100 DCHECK(decoder_->offscreen_saved_color_format_);
2101 decoder_->offscreen_resolved_color_texture_->AllocateStorage(
2102 decoder_->offscreen_size_, decoder_->offscreen_saved_color_format_,
2103 false);
2104 decoder_->offscreen_resolved_frame_buffer_->AttachRenderTexture(
2105 decoder_->offscreen_resolved_color_texture_.get());
2106 if (decoder_->offscreen_resolved_frame_buffer_->CheckStatus() !=
2107 GL_FRAMEBUFFER_COMPLETE) {
2108 LOG(ERROR) << "ScopedResolvedFrameBufferBinder failed "
2109 << "because offscreen resolved FBO was incomplete.";
2110 return;
2113 targetid = decoder_->offscreen_resolved_frame_buffer_->id();
2114 } else {
2115 targetid = decoder_->offscreen_saved_frame_buffer_->id();
2117 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, targetid);
2118 const int width = decoder_->offscreen_size_.width();
2119 const int height = decoder_->offscreen_size_.height();
2120 decoder->state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
2121 decoder->BlitFramebufferHelper(0,
2123 width,
2124 height,
2127 width,
2128 height,
2129 GL_COLOR_BUFFER_BIT,
2130 GL_NEAREST);
2131 glBindFramebufferEXT(GL_FRAMEBUFFER, targetid);
2134 ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
2135 if (!resolve_and_bind_)
2136 return;
2138 ScopedGLErrorSuppressor suppressor(
2139 "ScopedResolvedFrameBufferBinder::dtor", decoder_->GetErrorState());
2140 decoder_->RestoreCurrentFramebufferBindings();
2141 if (decoder_->state_.enable_flags.scissor_test) {
2142 decoder_->state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
2146 BackTexture::BackTexture(
2147 MemoryTracker* memory_tracker,
2148 ContextState* state)
2149 : memory_tracker_(memory_tracker, MemoryTracker::kUnmanaged),
2150 state_(state),
2151 bytes_allocated_(0),
2152 id_(0) {
2155 BackTexture::~BackTexture() {
2156 // This does not destroy the render texture because that would require that
2157 // the associated GL context was current. Just check that it was explicitly
2158 // destroyed.
2159 DCHECK_EQ(id_, 0u);
2162 void BackTexture::Create() {
2163 ScopedGLErrorSuppressor suppressor("BackTexture::Create",
2164 state_->GetErrorState());
2165 Destroy();
2166 glGenTextures(1, &id_);
2167 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2168 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2169 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2170 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2171 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2173 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
2174 // never called on an offscreen context, no data will ever be uploaded to the
2175 // saved offscreen color texture (it is deferred until to when SwapBuffers
2176 // is called). My idea is that some nvidia drivers might have a bug where
2177 // deleting a texture that has never been populated might cause a
2178 // crash.
2179 glTexImage2D(
2180 GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
2182 bytes_allocated_ = 16u * 16u * 4u;
2183 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2186 bool BackTexture::AllocateStorage(
2187 const gfx::Size& size, GLenum format, bool zero) {
2188 DCHECK_NE(id_, 0u);
2189 ScopedGLErrorSuppressor suppressor("BackTexture::AllocateStorage",
2190 state_->GetErrorState());
2191 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2192 uint32 image_size = 0;
2193 GLES2Util::ComputeImageDataSizes(
2194 size.width(), size.height(), 1, format, GL_UNSIGNED_BYTE, 8, &image_size,
2195 NULL, NULL);
2197 if (!memory_tracker_.EnsureGPUMemoryAvailable(image_size)) {
2198 return false;
2201 scoped_ptr<char[]> zero_data;
2202 if (zero) {
2203 zero_data.reset(new char[image_size]);
2204 memset(zero_data.get(), 0, image_size);
2207 glTexImage2D(GL_TEXTURE_2D,
2208 0, // mip level
2209 format,
2210 size.width(),
2211 size.height(),
2212 0, // border
2213 format,
2214 GL_UNSIGNED_BYTE,
2215 zero_data.get());
2217 size_ = size;
2219 bool success = glGetError() == GL_NO_ERROR;
2220 if (success) {
2221 memory_tracker_.TrackMemFree(bytes_allocated_);
2222 bytes_allocated_ = image_size;
2223 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2225 return success;
2228 void BackTexture::Copy(const gfx::Size& size, GLenum format) {
2229 DCHECK_NE(id_, 0u);
2230 ScopedGLErrorSuppressor suppressor("BackTexture::Copy",
2231 state_->GetErrorState());
2232 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2233 glCopyTexImage2D(GL_TEXTURE_2D,
2234 0, // level
2235 format,
2236 0, 0,
2237 size.width(),
2238 size.height(),
2239 0); // border
2242 void BackTexture::Destroy() {
2243 if (id_ != 0) {
2244 ScopedGLErrorSuppressor suppressor("BackTexture::Destroy",
2245 state_->GetErrorState());
2246 glDeleteTextures(1, &id_);
2247 id_ = 0;
2249 memory_tracker_.TrackMemFree(bytes_allocated_);
2250 bytes_allocated_ = 0;
2253 void BackTexture::Invalidate() {
2254 id_ = 0;
2257 BackRenderbuffer::BackRenderbuffer(
2258 RenderbufferManager* renderbuffer_manager,
2259 MemoryTracker* memory_tracker,
2260 ContextState* state)
2261 : renderbuffer_manager_(renderbuffer_manager),
2262 memory_tracker_(memory_tracker, MemoryTracker::kUnmanaged),
2263 state_(state),
2264 bytes_allocated_(0),
2265 id_(0) {
2268 BackRenderbuffer::~BackRenderbuffer() {
2269 // This does not destroy the render buffer because that would require that
2270 // the associated GL context was current. Just check that it was explicitly
2271 // destroyed.
2272 DCHECK_EQ(id_, 0u);
2275 void BackRenderbuffer::Create() {
2276 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Create",
2277 state_->GetErrorState());
2278 Destroy();
2279 glGenRenderbuffersEXT(1, &id_);
2282 bool BackRenderbuffer::AllocateStorage(const FeatureInfo* feature_info,
2283 const gfx::Size& size,
2284 GLenum format,
2285 GLsizei samples) {
2286 ScopedGLErrorSuppressor suppressor(
2287 "BackRenderbuffer::AllocateStorage", state_->GetErrorState());
2288 ScopedRenderBufferBinder binder(state_, id_);
2290 uint32 estimated_size = 0;
2291 if (!renderbuffer_manager_->ComputeEstimatedRenderbufferSize(
2292 size.width(), size.height(), samples, format, &estimated_size)) {
2293 return false;
2296 if (!memory_tracker_.EnsureGPUMemoryAvailable(estimated_size)) {
2297 return false;
2300 if (samples <= 1) {
2301 glRenderbufferStorageEXT(GL_RENDERBUFFER,
2302 format,
2303 size.width(),
2304 size.height());
2305 } else {
2306 GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(feature_info,
2307 GL_RENDERBUFFER,
2308 samples,
2309 format,
2310 size.width(),
2311 size.height());
2313 bool success = glGetError() == GL_NO_ERROR;
2314 if (success) {
2315 // Mark the previously allocated bytes as free.
2316 memory_tracker_.TrackMemFree(bytes_allocated_);
2317 bytes_allocated_ = estimated_size;
2318 // Track the newly allocated bytes.
2319 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2321 return success;
2324 void BackRenderbuffer::Destroy() {
2325 if (id_ != 0) {
2326 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Destroy",
2327 state_->GetErrorState());
2328 glDeleteRenderbuffersEXT(1, &id_);
2329 id_ = 0;
2331 memory_tracker_.TrackMemFree(bytes_allocated_);
2332 bytes_allocated_ = 0;
2335 void BackRenderbuffer::Invalidate() {
2336 id_ = 0;
2339 BackFramebuffer::BackFramebuffer(GLES2DecoderImpl* decoder)
2340 : decoder_(decoder),
2341 id_(0) {
2344 BackFramebuffer::~BackFramebuffer() {
2345 // This does not destroy the frame buffer because that would require that
2346 // the associated GL context was current. Just check that it was explicitly
2347 // destroyed.
2348 DCHECK_EQ(id_, 0u);
2351 void BackFramebuffer::Create() {
2352 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Create",
2353 decoder_->GetErrorState());
2354 Destroy();
2355 glGenFramebuffersEXT(1, &id_);
2358 void BackFramebuffer::AttachRenderTexture(BackTexture* texture) {
2359 DCHECK_NE(id_, 0u);
2360 ScopedGLErrorSuppressor suppressor(
2361 "BackFramebuffer::AttachRenderTexture", decoder_->GetErrorState());
2362 ScopedFrameBufferBinder binder(decoder_, id_);
2363 GLuint attach_id = texture ? texture->id() : 0;
2364 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
2365 GL_COLOR_ATTACHMENT0,
2366 GL_TEXTURE_2D,
2367 attach_id,
2371 void BackFramebuffer::AttachRenderBuffer(GLenum target,
2372 BackRenderbuffer* render_buffer) {
2373 DCHECK_NE(id_, 0u);
2374 ScopedGLErrorSuppressor suppressor(
2375 "BackFramebuffer::AttachRenderBuffer", decoder_->GetErrorState());
2376 ScopedFrameBufferBinder binder(decoder_, id_);
2377 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
2378 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
2379 target,
2380 GL_RENDERBUFFER,
2381 attach_id);
2384 void BackFramebuffer::Destroy() {
2385 if (id_ != 0) {
2386 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Destroy",
2387 decoder_->GetErrorState());
2388 glDeleteFramebuffersEXT(1, &id_);
2389 id_ = 0;
2393 void BackFramebuffer::Invalidate() {
2394 id_ = 0;
2397 GLenum BackFramebuffer::CheckStatus() {
2398 DCHECK_NE(id_, 0u);
2399 ScopedGLErrorSuppressor suppressor("BackFramebuffer::CheckStatus",
2400 decoder_->GetErrorState());
2401 ScopedFrameBufferBinder binder(decoder_, id_);
2402 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
2405 GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
2406 return new GLES2DecoderImpl(group);
2409 GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
2410 : GLES2Decoder(),
2411 group_(group),
2412 logger_(&debug_marker_manager_),
2413 state_(group_->feature_info(), this, &logger_),
2414 unpack_flip_y_(false),
2415 unpack_premultiply_alpha_(false),
2416 unpack_unpremultiply_alpha_(false),
2417 attrib_0_buffer_id_(0),
2418 attrib_0_buffer_matches_value_(true),
2419 attrib_0_size_(0),
2420 fixed_attrib_buffer_id_(0),
2421 fixed_attrib_buffer_size_(0),
2422 offscreen_target_color_format_(0),
2423 offscreen_target_depth_format_(0),
2424 offscreen_target_stencil_format_(0),
2425 offscreen_target_samples_(0),
2426 offscreen_target_buffer_preserved_(true),
2427 offscreen_saved_color_format_(0),
2428 back_buffer_color_format_(0),
2429 back_buffer_has_depth_(false),
2430 back_buffer_has_stencil_(false),
2431 surfaceless_(false),
2432 backbuffer_needs_clear_bits_(0),
2433 current_decoder_error_(error::kNoError),
2434 use_shader_translator_(true),
2435 validators_(group_->feature_info()->validators()),
2436 feature_info_(group_->feature_info()),
2437 frame_number_(0),
2438 has_robustness_extension_(false),
2439 context_lost_reason_(error::kUnknown),
2440 context_was_lost_(false),
2441 reset_by_robustness_extension_(false),
2442 supports_post_sub_buffer_(false),
2443 force_webgl_glsl_validation_(false),
2444 derivatives_explicitly_enabled_(false),
2445 frag_depth_explicitly_enabled_(false),
2446 draw_buffers_explicitly_enabled_(false),
2447 shader_texture_lod_explicitly_enabled_(false),
2448 compile_shader_always_succeeds_(false),
2449 lose_context_when_out_of_memory_(false),
2450 service_logging_(base::CommandLine::ForCurrentProcess()->HasSwitch(
2451 switches::kEnableGPUServiceLoggingGPU)),
2452 viewport_max_width_(0),
2453 viewport_max_height_(0),
2454 texture_state_(group_->feature_info()
2455 ->workarounds()
2456 .texsubimage2d_faster_than_teximage2d),
2457 cb_command_trace_category_(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
2458 TRACE_DISABLED_BY_DEFAULT("cb_command"))),
2459 gpu_decoder_category_(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
2460 TRACE_DISABLED_BY_DEFAULT("gpu_decoder"))),
2461 gpu_trace_level_(2),
2462 gpu_trace_commands_(false),
2463 gpu_debug_commands_(false),
2464 validation_texture_(0),
2465 validation_fbo_multisample_(0),
2466 validation_fbo_(0) {
2467 DCHECK(group);
2469 attrib_0_value_.v[0] = 0.0f;
2470 attrib_0_value_.v[1] = 0.0f;
2471 attrib_0_value_.v[2] = 0.0f;
2472 attrib_0_value_.v[3] = 1.0f;
2474 // The shader translator is used for WebGL even when running on EGL
2475 // because additional restrictions are needed (like only enabling
2476 // GL_OES_standard_derivatives on demand). It is used for the unit
2477 // tests because GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes
2478 // the empty string to CompileShader and this is not a valid shader.
2479 if (gfx::GetGLImplementation() == gfx::kGLImplementationMockGL ||
2480 base::CommandLine::ForCurrentProcess()->HasSwitch(
2481 switches::kDisableGLSLTranslator)) {
2482 use_shader_translator_ = false;
2486 GLES2DecoderImpl::~GLES2DecoderImpl() {
2489 bool GLES2DecoderImpl::Initialize(
2490 const scoped_refptr<gfx::GLSurface>& surface,
2491 const scoped_refptr<gfx::GLContext>& context,
2492 bool offscreen,
2493 const gfx::Size& offscreen_size,
2494 const DisallowedFeatures& disallowed_features,
2495 const std::vector<int32>& attribs) {
2496 TRACE_EVENT0("gpu", "GLES2DecoderImpl::Initialize");
2497 DCHECK(context->IsCurrent(surface.get()));
2498 DCHECK(!context_.get());
2499 DCHECK(!offscreen || !offscreen_size.IsEmpty());
2501 ContextCreationAttribHelper attrib_parser;
2502 if (!attrib_parser.Parse(attribs))
2503 return false;
2505 surfaceless_ = surface->IsSurfaceless() && !offscreen;
2507 set_initialized();
2508 gpu_state_tracer_ = GPUStateTracer::Create(&state_);
2510 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2511 switches::kEnableGPUDebugging)) {
2512 set_debug(true);
2515 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2516 switches::kEnableGPUCommandLogging)) {
2517 set_log_commands(true);
2520 compile_shader_always_succeeds_ =
2521 base::CommandLine::ForCurrentProcess()->HasSwitch(
2522 switches::kCompileShaderAlwaysSucceeds);
2524 // Take ownership of the context and surface. The surface can be replaced with
2525 // SetSurface.
2526 context_ = context;
2527 surface_ = surface;
2529 // Create GPU Tracer for timing values.
2530 gpu_tracer_.reset(new GPUTracer(this));
2532 // Save the loseContextWhenOutOfMemory context creation attribute.
2533 lose_context_when_out_of_memory_ =
2534 attrib_parser.lose_context_when_out_of_memory;
2536 // If the failIfMajorPerformanceCaveat context creation attribute was true
2537 // and we are using a software renderer, fail.
2538 if (attrib_parser.fail_if_major_perf_caveat &&
2539 feature_info_->feature_flags().is_swiftshader) {
2540 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
2541 Destroy(true);
2542 return false;
2545 if (!group_->Initialize(this, disallowed_features)) {
2546 LOG(ERROR) << "GpuScheduler::InitializeCommon failed because group "
2547 << "failed to initialize.";
2548 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
2549 Destroy(true);
2550 return false;
2552 CHECK_GL_ERROR();
2554 if (attrib_parser.es3_context_required &&
2555 feature_info_->IsES3Capable()) {
2556 feature_info_->EnableES3Validators();
2557 set_unsafe_es3_apis_enabled(true);
2560 disallowed_features_ = disallowed_features;
2562 state_.attrib_values.resize(group_->max_vertex_attribs());
2563 vertex_array_manager_.reset(new VertexArrayManager());
2565 GLuint default_vertex_attrib_service_id = 0;
2566 if (features().native_vertex_array_object) {
2567 glGenVertexArraysOES(1, &default_vertex_attrib_service_id);
2568 glBindVertexArrayOES(default_vertex_attrib_service_id);
2571 state_.default_vertex_attrib_manager =
2572 CreateVertexAttribManager(0, default_vertex_attrib_service_id, false);
2574 state_.default_vertex_attrib_manager->Initialize(
2575 group_->max_vertex_attribs(),
2576 feature_info_->workarounds().init_vertex_attributes);
2578 // vertex_attrib_manager is set to default_vertex_attrib_manager by this call
2579 DoBindVertexArrayOES(0);
2581 query_manager_.reset(new QueryManager(this, feature_info_.get()));
2583 image_manager_.reset(new ImageManager);
2585 util_.set_num_compressed_texture_formats(
2586 validators_->compressed_texture_format.GetValues().size());
2588 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2589 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
2590 // OpenGL ES 2.0 does not have this issue.
2591 glEnableVertexAttribArray(0);
2593 glGenBuffersARB(1, &attrib_0_buffer_id_);
2594 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
2595 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
2596 glBindBuffer(GL_ARRAY_BUFFER, 0);
2597 glGenBuffersARB(1, &fixed_attrib_buffer_id_);
2599 state_.texture_units.resize(group_->max_texture_units());
2600 for (uint32 tt = 0; tt < state_.texture_units.size(); ++tt) {
2601 glActiveTexture(GL_TEXTURE0 + tt);
2602 // We want the last bind to be 2D.
2603 TextureRef* ref;
2604 if (features().oes_egl_image_external) {
2605 ref = texture_manager()->GetDefaultTextureInfo(
2606 GL_TEXTURE_EXTERNAL_OES);
2607 state_.texture_units[tt].bound_texture_external_oes = ref;
2608 glBindTexture(GL_TEXTURE_EXTERNAL_OES, ref ? ref->service_id() : 0);
2610 if (features().arb_texture_rectangle) {
2611 ref = texture_manager()->GetDefaultTextureInfo(
2612 GL_TEXTURE_RECTANGLE_ARB);
2613 state_.texture_units[tt].bound_texture_rectangle_arb = ref;
2614 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, ref ? ref->service_id() : 0);
2616 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
2617 state_.texture_units[tt].bound_texture_cube_map = ref;
2618 glBindTexture(GL_TEXTURE_CUBE_MAP, ref ? ref->service_id() : 0);
2619 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
2620 state_.texture_units[tt].bound_texture_2d = ref;
2621 glBindTexture(GL_TEXTURE_2D, ref ? ref->service_id() : 0);
2623 glActiveTexture(GL_TEXTURE0);
2624 CHECK_GL_ERROR();
2626 // cache ALPHA_BITS result for re-use with clear behaviour
2627 GLint alpha_bits = 0;
2629 if (offscreen) {
2630 if (attrib_parser.samples > 0 && attrib_parser.sample_buffers > 0 &&
2631 features().chromium_framebuffer_multisample) {
2632 // Per ext_framebuffer_multisample spec, need max bound on sample count.
2633 // max_sample_count must be initialized to a sane value. If
2634 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2635 GLint max_sample_count = 1;
2636 glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count);
2637 offscreen_target_samples_ = std::min(attrib_parser.samples,
2638 max_sample_count);
2639 } else {
2640 offscreen_target_samples_ = 1;
2642 offscreen_target_buffer_preserved_ = attrib_parser.buffer_preserved;
2644 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
2645 const bool rgb8_supported =
2646 context_->HasExtension("GL_OES_rgb8_rgba8");
2647 // The only available default render buffer formats in GLES2 have very
2648 // little precision. Don't enable multisampling unless 8-bit render
2649 // buffer formats are available--instead fall back to 8-bit textures.
2650 if (rgb8_supported && offscreen_target_samples_ > 1) {
2651 offscreen_target_color_format_ = attrib_parser.alpha_size > 0 ?
2652 GL_RGBA8 : GL_RGB8;
2653 } else {
2654 offscreen_target_samples_ = 1;
2655 offscreen_target_color_format_ =
2656 attrib_parser.alpha_size > 0 || workarounds().disable_gl_rgb_format
2657 ? GL_RGBA
2658 : GL_RGB;
2661 // ANGLE only supports packed depth/stencil formats, so use it if it is
2662 // available.
2663 const bool depth24_stencil8_supported =
2664 feature_info_->feature_flags().packed_depth24_stencil8;
2665 VLOG(1) << "GL_OES_packed_depth_stencil "
2666 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
2667 if ((attrib_parser.depth_size > 0 || attrib_parser.stencil_size > 0) &&
2668 depth24_stencil8_supported) {
2669 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2670 offscreen_target_stencil_format_ = 0;
2671 } else {
2672 // It may be the case that this depth/stencil combination is not
2673 // supported, but this will be checked later by CheckFramebufferStatus.
2674 offscreen_target_depth_format_ = attrib_parser.depth_size > 0 ?
2675 GL_DEPTH_COMPONENT16 : 0;
2676 offscreen_target_stencil_format_ = attrib_parser.stencil_size > 0 ?
2677 GL_STENCIL_INDEX8 : 0;
2679 } else {
2680 offscreen_target_color_format_ =
2681 attrib_parser.alpha_size > 0 || workarounds().disable_gl_rgb_format
2682 ? GL_RGBA
2683 : GL_RGB;
2685 // If depth is requested at all, use the packed depth stencil format if
2686 // it's available, as some desktop GL drivers don't support any non-packed
2687 // formats for depth attachments.
2688 const bool depth24_stencil8_supported =
2689 feature_info_->feature_flags().packed_depth24_stencil8;
2690 VLOG(1) << "GL_EXT_packed_depth_stencil "
2691 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
2693 if ((attrib_parser.depth_size > 0 || attrib_parser.stencil_size > 0) &&
2694 depth24_stencil8_supported) {
2695 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2696 offscreen_target_stencil_format_ = 0;
2697 } else {
2698 offscreen_target_depth_format_ = attrib_parser.depth_size > 0 ?
2699 GL_DEPTH_COMPONENT : 0;
2700 offscreen_target_stencil_format_ = attrib_parser.stencil_size > 0 ?
2701 GL_STENCIL_INDEX : 0;
2705 offscreen_saved_color_format_ =
2706 attrib_parser.alpha_size > 0 || workarounds().disable_gl_rgb_format
2707 ? GL_RGBA
2708 : GL_RGB;
2710 // Create the target frame buffer. This is the one that the client renders
2711 // directly to.
2712 offscreen_target_frame_buffer_.reset(new BackFramebuffer(this));
2713 offscreen_target_frame_buffer_->Create();
2714 // Due to GLES2 format limitations, either the color texture (for
2715 // non-multisampling) or the color render buffer (for multisampling) will be
2716 // attached to the offscreen frame buffer. The render buffer has more
2717 // limited formats available to it, but the texture can't do multisampling.
2718 if (IsOffscreenBufferMultisampled()) {
2719 offscreen_target_color_render_buffer_.reset(new BackRenderbuffer(
2720 renderbuffer_manager(), memory_tracker(), &state_));
2721 offscreen_target_color_render_buffer_->Create();
2722 } else {
2723 offscreen_target_color_texture_.reset(new BackTexture(
2724 memory_tracker(), &state_));
2725 offscreen_target_color_texture_->Create();
2727 offscreen_target_depth_render_buffer_.reset(new BackRenderbuffer(
2728 renderbuffer_manager(), memory_tracker(), &state_));
2729 offscreen_target_depth_render_buffer_->Create();
2730 offscreen_target_stencil_render_buffer_.reset(new BackRenderbuffer(
2731 renderbuffer_manager(), memory_tracker(), &state_));
2732 offscreen_target_stencil_render_buffer_->Create();
2734 // Create the saved offscreen texture. The target frame buffer is copied
2735 // here when SwapBuffers is called.
2736 offscreen_saved_frame_buffer_.reset(new BackFramebuffer(this));
2737 offscreen_saved_frame_buffer_->Create();
2739 offscreen_saved_color_texture_.reset(new BackTexture(
2740 memory_tracker(), &state_));
2741 offscreen_saved_color_texture_->Create();
2743 // Allocate the render buffers at their initial size and check the status
2744 // of the frame buffers is okay.
2745 if (!ResizeOffscreenFrameBuffer(offscreen_size)) {
2746 LOG(ERROR) << "Could not allocate offscreen buffer storage.";
2747 Destroy(true);
2748 return false;
2751 state_.viewport_width = offscreen_size.width();
2752 state_.viewport_height = offscreen_size.height();
2754 // Allocate the offscreen saved color texture.
2755 DCHECK(offscreen_saved_color_format_);
2756 offscreen_saved_color_texture_->AllocateStorage(
2757 gfx::Size(1, 1), offscreen_saved_color_format_, true);
2759 offscreen_saved_frame_buffer_->AttachRenderTexture(
2760 offscreen_saved_color_texture_.get());
2761 if (offscreen_saved_frame_buffer_->CheckStatus() !=
2762 GL_FRAMEBUFFER_COMPLETE) {
2763 LOG(ERROR) << "Offscreen saved FBO was incomplete.";
2764 Destroy(true);
2765 return false;
2768 // Bind to the new default frame buffer (the offscreen target frame buffer).
2769 // This should now be associated with ID zero.
2770 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2771 } else {
2772 glBindFramebufferEXT(GL_FRAMEBUFFER, GetBackbufferServiceId());
2773 // These are NOT if the back buffer has these proprorties. They are
2774 // if we want the command buffer to enforce them regardless of what
2775 // the real backbuffer is assuming the real back buffer gives us more than
2776 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2777 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2778 // can't do anything about that.
2780 if (!surfaceless_) {
2781 GLint depth_bits = 0;
2782 GLint stencil_bits = 0;
2784 bool default_fb = (GetBackbufferServiceId() == 0);
2786 if (feature_info_->gl_version_info().is_desktop_core_profile) {
2787 glGetFramebufferAttachmentParameterivEXT(
2788 GL_FRAMEBUFFER,
2789 default_fb ? GL_BACK_LEFT : GL_COLOR_ATTACHMENT0,
2790 GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE, &alpha_bits);
2791 glGetFramebufferAttachmentParameterivEXT(
2792 GL_FRAMEBUFFER,
2793 default_fb ? GL_DEPTH : GL_DEPTH_ATTACHMENT,
2794 GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE, &depth_bits);
2795 glGetFramebufferAttachmentParameterivEXT(
2796 GL_FRAMEBUFFER,
2797 default_fb ? GL_STENCIL : GL_STENCIL_ATTACHMENT,
2798 GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE, &stencil_bits);
2799 } else {
2800 glGetIntegerv(GL_ALPHA_BITS, &alpha_bits);
2801 glGetIntegerv(GL_DEPTH_BITS, &depth_bits);
2802 glGetIntegerv(GL_STENCIL_BITS, &stencil_bits);
2805 // This checks if the user requested RGBA and we have RGBA then RGBA. If
2806 // the user requested RGB then RGB. If the user did not specify a
2807 // preference than use whatever we were given. Same for DEPTH and STENCIL.
2808 back_buffer_color_format_ =
2809 (attrib_parser.alpha_size != 0 && alpha_bits > 0) ? GL_RGBA : GL_RGB;
2810 back_buffer_has_depth_ = attrib_parser.depth_size != 0 && depth_bits > 0;
2811 back_buffer_has_stencil_ =
2812 attrib_parser.stencil_size != 0 && stencil_bits > 0;
2815 state_.viewport_width = surface->GetSize().width();
2816 state_.viewport_height = surface->GetSize().height();
2819 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2820 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2821 // isn't well documented; it was discovered in the Khronos OpenGL ES
2822 // mailing list archives. It also implicitly enables the desktop GL
2823 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2824 // variable in fragment shaders.
2825 if (!feature_info_->gl_version_info().BehavesLikeGLES()) {
2826 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
2827 glEnable(GL_POINT_SPRITE);
2830 has_robustness_extension_ =
2831 context->HasExtension("GL_ARB_robustness") ||
2832 context->HasExtension("GL_KHR_robustness") ||
2833 context->HasExtension("GL_EXT_robustness");
2835 if (!InitializeShaderTranslator()) {
2836 return false;
2839 GLint viewport_params[4] = { 0 };
2840 glGetIntegerv(GL_MAX_VIEWPORT_DIMS, viewport_params);
2841 viewport_max_width_ = viewport_params[0];
2842 viewport_max_height_ = viewport_params[1];
2844 state_.scissor_width = state_.viewport_width;
2845 state_.scissor_height = state_.viewport_height;
2847 // Set all the default state because some GL drivers get it wrong.
2848 state_.InitCapabilities(NULL);
2849 state_.InitState(NULL);
2850 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
2852 DoBindBuffer(GL_ARRAY_BUFFER, 0);
2853 DoBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
2854 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2855 DoBindRenderbuffer(GL_RENDERBUFFER, 0);
2856 DoBindValueBufferCHROMIUM(GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM, 0);
2858 bool call_gl_clear = !surfaceless_;
2859 #if defined(OS_ANDROID)
2860 // Temporary workaround for Android WebView because this clear ignores the
2861 // clip and corrupts that external UI of the App. Not calling glClear is ok
2862 // because the system already clears the buffer before each draw. Proper
2863 // fix might be setting the scissor clip properly before initialize. See
2864 // crbug.com/259023 for details.
2865 call_gl_clear = surface_->GetHandle();
2866 #endif
2867 if (call_gl_clear) {
2868 // On configs where we report no alpha, if the underlying surface has
2869 // alpha, clear the surface alpha to 1.0 to be correct on ReadPixels/etc.
2870 bool clear_alpha = back_buffer_color_format_ == GL_RGB && alpha_bits > 0;
2871 if (clear_alpha) {
2872 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
2875 // Clear the backbuffer.
2876 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2878 // Restore alpha clear value if we changed it.
2879 if (clear_alpha) {
2880 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
2884 supports_post_sub_buffer_ = surface->SupportsPostSubBuffer();
2885 if (feature_info_->workarounds()
2886 .disable_post_sub_buffers_for_onscreen_surfaces &&
2887 !surface->IsOffscreen())
2888 supports_post_sub_buffer_ = false;
2890 if (feature_info_->workarounds().reverse_point_sprite_coord_origin) {
2891 glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT);
2894 if (feature_info_->workarounds().unbind_fbo_on_context_switch) {
2895 context_->SetUnbindFboOnMakeCurrent();
2898 // Only compositor contexts are known to use only the subset of GL
2899 // that can be safely migrated between the iGPU and the dGPU. Mark
2900 // those contexts as safe to forcibly transition between the GPUs.
2901 // http://crbug.com/180876, http://crbug.com/227228
2902 if (!offscreen)
2903 context_->SetSafeToForceGpuSwitch();
2905 async_pixel_transfer_manager_.reset(
2906 AsyncPixelTransferManager::Create(context.get()));
2907 async_pixel_transfer_manager_->Initialize(texture_manager());
2909 if (workarounds().gl_clear_broken) {
2910 DCHECK(!clear_framebuffer_blit_.get());
2911 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glClearWorkaroundInit");
2912 clear_framebuffer_blit_.reset(new ClearFramebufferResourceManager(this));
2913 if (LOCAL_PEEK_GL_ERROR("glClearWorkaroundInit") != GL_NO_ERROR)
2914 return false;
2917 framebuffer_manager()->AddObserver(this);
2919 return true;
2922 Capabilities GLES2DecoderImpl::GetCapabilities() {
2923 DCHECK(initialized());
2924 Capabilities caps;
2925 caps.VisitPrecisions([](GLenum shader, GLenum type,
2926 Capabilities::ShaderPrecision* shader_precision) {
2927 GLint range[2] = {0, 0};
2928 GLint precision = 0;
2929 GetShaderPrecisionFormatImpl(shader, type, range, &precision);
2930 shader_precision->min_range = range[0];
2931 shader_precision->max_range = range[1];
2932 shader_precision->precision = precision;
2934 DoGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS,
2935 &caps.max_combined_texture_image_units);
2936 DoGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &caps.max_cube_map_texture_size);
2937 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS,
2938 &caps.max_fragment_uniform_vectors);
2939 DoGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &caps.max_renderbuffer_size);
2940 DoGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &caps.max_texture_image_units);
2941 DoGetIntegerv(GL_MAX_TEXTURE_SIZE, &caps.max_texture_size);
2942 DoGetIntegerv(GL_MAX_VARYING_VECTORS, &caps.max_varying_vectors);
2943 DoGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &caps.max_vertex_attribs);
2944 DoGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS,
2945 &caps.max_vertex_texture_image_units);
2946 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS,
2947 &caps.max_vertex_uniform_vectors);
2948 DoGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS,
2949 &caps.num_compressed_texture_formats);
2950 DoGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS, &caps.num_shader_binary_formats);
2951 DoGetIntegerv(GL_BIND_GENERATES_RESOURCE_CHROMIUM,
2952 &caps.bind_generates_resource_chromium);
2953 if (unsafe_es3_apis_enabled()) {
2954 // TODO(zmo): Note that some parameter values could be more than 32-bit,
2955 // but for now we clamp them to 32-bit max.
2956 DoGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &caps.max_3d_texture_size);
2957 DoGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &caps.max_array_texture_layers);
2958 DoGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &caps.max_color_attachments);
2959 DoGetIntegerv(GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS,
2960 &caps.max_combined_fragment_uniform_components);
2961 DoGetIntegerv(GL_MAX_COMBINED_UNIFORM_BLOCKS,
2962 &caps.max_combined_uniform_blocks);
2963 DoGetIntegerv(GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS,
2964 &caps.max_combined_vertex_uniform_components);
2965 DoGetIntegerv(GL_MAX_DRAW_BUFFERS, &caps.max_draw_buffers);
2966 DoGetIntegerv(GL_MAX_ELEMENT_INDEX, &caps.max_element_index);
2967 DoGetIntegerv(GL_MAX_ELEMENTS_INDICES, &caps.max_elements_indices);
2968 DoGetIntegerv(GL_MAX_ELEMENTS_VERTICES, &caps.max_elements_vertices);
2969 DoGetIntegerv(GL_MAX_FRAGMENT_INPUT_COMPONENTS,
2970 &caps.max_fragment_input_components);
2971 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_BLOCKS,
2972 &caps.max_fragment_uniform_blocks);
2973 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS,
2974 &caps.max_fragment_uniform_components);
2975 DoGetIntegerv(GL_MAX_PROGRAM_TEXEL_OFFSET,
2976 &caps.max_program_texel_offset);
2977 DoGetIntegerv(GL_MAX_SERVER_WAIT_TIMEOUT, &caps.max_server_wait_timeout);
2978 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS,
2979 &caps.max_transform_feedback_interleaved_components);
2980 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS,
2981 &caps.max_transform_feedback_separate_attribs);
2982 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS,
2983 &caps.max_transform_feedback_separate_components);
2984 DoGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &caps.max_uniform_block_size);
2985 DoGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS,
2986 &caps.max_uniform_buffer_bindings);
2987 DoGetIntegerv(GL_MAX_VARYING_COMPONENTS, &caps.max_varying_components);
2988 DoGetIntegerv(GL_MAX_VERTEX_OUTPUT_COMPONENTS,
2989 &caps.max_vertex_output_components);
2990 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_BLOCKS,
2991 &caps.max_vertex_uniform_blocks);
2992 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS,
2993 &caps.max_vertex_uniform_components);
2994 DoGetIntegerv(GL_MIN_PROGRAM_TEXEL_OFFSET, &caps.min_program_texel_offset);
2995 DoGetIntegerv(GL_NUM_EXTENSIONS, &caps.num_extensions);
2996 DoGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS,
2997 &caps.num_program_binary_formats);
2998 DoGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT,
2999 &caps.uniform_buffer_offset_alignment);
3000 // TODO(zmo): once we switch to MANGLE, we should query version numbers.
3001 caps.major_version = 3;
3002 caps.minor_version = 0;
3004 if (feature_info_->feature_flags().multisampled_render_to_texture ||
3005 feature_info_->feature_flags().chromium_framebuffer_multisample ||
3006 unsafe_es3_apis_enabled()) {
3007 DoGetIntegerv(GL_MAX_SAMPLES, &caps.max_samples);
3010 caps.egl_image_external =
3011 feature_info_->feature_flags().oes_egl_image_external;
3012 caps.texture_format_atc =
3013 feature_info_->feature_flags().ext_texture_format_atc;
3014 caps.texture_format_bgra8888 =
3015 feature_info_->feature_flags().ext_texture_format_bgra8888;
3016 caps.texture_format_dxt1 =
3017 feature_info_->feature_flags().ext_texture_format_dxt1;
3018 caps.texture_format_dxt5 =
3019 feature_info_->feature_flags().ext_texture_format_dxt5;
3020 caps.texture_format_etc1 =
3021 feature_info_->feature_flags().oes_compressed_etc1_rgb8_texture;
3022 caps.texture_format_etc1_npot =
3023 caps.texture_format_etc1 && !workarounds().etc1_power_of_two_only;
3024 caps.texture_rectangle = feature_info_->feature_flags().arb_texture_rectangle;
3025 caps.texture_usage = feature_info_->feature_flags().angle_texture_usage;
3026 caps.texture_storage = feature_info_->feature_flags().ext_texture_storage;
3027 caps.discard_framebuffer =
3028 feature_info_->feature_flags().ext_discard_framebuffer;
3029 caps.sync_query = feature_info_->feature_flags().chromium_sync_query;
3031 #if defined(OS_MACOSX)
3032 // This is unconditionally true on mac, no need to test for it at runtime.
3033 caps.iosurface = true;
3034 #endif
3036 caps.post_sub_buffer = supports_post_sub_buffer_;
3037 caps.image = true;
3039 caps.blend_equation_advanced =
3040 feature_info_->feature_flags().blend_equation_advanced;
3041 caps.blend_equation_advanced_coherent =
3042 feature_info_->feature_flags().blend_equation_advanced_coherent;
3043 caps.texture_rg = feature_info_->feature_flags().ext_texture_rg;
3044 return caps;
3047 void GLES2DecoderImpl::UpdateCapabilities() {
3048 util_.set_num_compressed_texture_formats(
3049 validators_->compressed_texture_format.GetValues().size());
3050 util_.set_num_shader_binary_formats(
3051 validators_->shader_binary_format.GetValues().size());
3054 bool GLES2DecoderImpl::InitializeShaderTranslator() {
3055 TRACE_EVENT0("gpu", "GLES2DecoderImpl::InitializeShaderTranslator");
3057 if (!use_shader_translator_) {
3058 return true;
3060 ShBuiltInResources resources;
3061 ShInitBuiltInResources(&resources);
3062 resources.MaxVertexAttribs = group_->max_vertex_attribs();
3063 resources.MaxVertexUniformVectors =
3064 group_->max_vertex_uniform_vectors();
3065 resources.MaxVaryingVectors = group_->max_varying_vectors();
3066 resources.MaxVertexTextureImageUnits =
3067 group_->max_vertex_texture_image_units();
3068 resources.MaxCombinedTextureImageUnits = group_->max_texture_units();
3069 resources.MaxTextureImageUnits = group_->max_texture_image_units();
3070 resources.MaxFragmentUniformVectors =
3071 group_->max_fragment_uniform_vectors();
3072 resources.MaxDrawBuffers = group_->max_draw_buffers();
3073 resources.MaxExpressionComplexity = 256;
3074 resources.MaxCallStackDepth = 256;
3076 GLint range[2] = { 0, 0 };
3077 GLint precision = 0;
3078 GetShaderPrecisionFormatImpl(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT,
3079 range, &precision);
3080 resources.FragmentPrecisionHigh =
3081 PrecisionMeetsSpecForHighpFloat(range[0], range[1], precision);
3083 if (force_webgl_glsl_validation_) {
3084 resources.OES_standard_derivatives = derivatives_explicitly_enabled_;
3085 resources.EXT_frag_depth = frag_depth_explicitly_enabled_;
3086 resources.EXT_draw_buffers = draw_buffers_explicitly_enabled_;
3087 if (!draw_buffers_explicitly_enabled_)
3088 resources.MaxDrawBuffers = 1;
3089 resources.EXT_shader_texture_lod = shader_texture_lod_explicitly_enabled_;
3090 resources.NV_draw_buffers =
3091 draw_buffers_explicitly_enabled_ && features().nv_draw_buffers;
3092 } else {
3093 resources.OES_standard_derivatives =
3094 features().oes_standard_derivatives ? 1 : 0;
3095 resources.ARB_texture_rectangle =
3096 features().arb_texture_rectangle ? 1 : 0;
3097 resources.OES_EGL_image_external =
3098 features().oes_egl_image_external ? 1 : 0;
3099 resources.EXT_draw_buffers =
3100 features().ext_draw_buffers ? 1 : 0;
3101 resources.EXT_frag_depth =
3102 features().ext_frag_depth ? 1 : 0;
3103 resources.EXT_shader_texture_lod =
3104 features().ext_shader_texture_lod ? 1 : 0;
3105 resources.NV_draw_buffers =
3106 features().nv_draw_buffers ? 1 : 0;
3109 ShShaderSpec shader_spec;
3110 if (force_webgl_glsl_validation_) {
3111 shader_spec = unsafe_es3_apis_enabled() ? SH_WEBGL2_SPEC : SH_WEBGL_SPEC;
3112 } else {
3113 shader_spec = unsafe_es3_apis_enabled() ? SH_GLES3_SPEC : SH_GLES2_SPEC;
3116 if ((shader_spec == SH_WEBGL_SPEC || shader_spec == SH_WEBGL2_SPEC) &&
3117 features().enable_shader_name_hashing)
3118 resources.HashFunction = &CityHash64;
3119 else
3120 resources.HashFunction = NULL;
3121 ShaderTranslatorInterface::GlslImplementationType implementation_type =
3122 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 ?
3123 ShaderTranslatorInterface::kGlslES : ShaderTranslatorInterface::kGlsl;
3124 int driver_bug_workarounds = 0;
3125 if (workarounds().needs_glsl_built_in_function_emulation)
3126 driver_bug_workarounds |= SH_EMULATE_BUILT_IN_FUNCTIONS;
3127 if (workarounds().init_gl_position_in_vertex_shader)
3128 driver_bug_workarounds |= SH_INIT_GL_POSITION;
3129 if (workarounds().unfold_short_circuit_as_ternary_operation)
3130 driver_bug_workarounds |= SH_UNFOLD_SHORT_CIRCUIT;
3131 if (workarounds().init_varyings_without_static_use)
3132 driver_bug_workarounds |= SH_INIT_VARYINGS_WITHOUT_STATIC_USE;
3133 if (workarounds().unroll_for_loop_with_sampler_array_index)
3134 driver_bug_workarounds |= SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX;
3135 if (workarounds().scalarize_vec_and_mat_constructor_args)
3136 driver_bug_workarounds |= SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS;
3137 if (workarounds().regenerate_struct_names)
3138 driver_bug_workarounds |= SH_REGENERATE_STRUCT_NAMES;
3140 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
3141 switches::kEmulateShaderPrecision))
3142 resources.WEBGL_debug_shader_precision = true;
3144 vertex_translator_ = shader_translator_cache()->GetTranslator(
3145 GL_VERTEX_SHADER,
3146 shader_spec,
3147 &resources,
3148 implementation_type,
3149 static_cast<ShCompileOptions>(driver_bug_workarounds));
3150 if (!vertex_translator_.get()) {
3151 LOG(ERROR) << "Could not initialize vertex shader translator.";
3152 Destroy(true);
3153 return false;
3156 fragment_translator_ = shader_translator_cache()->GetTranslator(
3157 GL_FRAGMENT_SHADER,
3158 shader_spec,
3159 &resources,
3160 implementation_type,
3161 static_cast<ShCompileOptions>(driver_bug_workarounds));
3162 if (!fragment_translator_.get()) {
3163 LOG(ERROR) << "Could not initialize fragment shader translator.";
3164 Destroy(true);
3165 return false;
3167 return true;
3170 bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
3171 for (GLsizei ii = 0; ii < n; ++ii) {
3172 if (GetBuffer(client_ids[ii])) {
3173 return false;
3176 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3177 glGenBuffersARB(n, service_ids.get());
3178 for (GLsizei ii = 0; ii < n; ++ii) {
3179 CreateBuffer(client_ids[ii], service_ids[ii]);
3181 return true;
3184 bool GLES2DecoderImpl::GenFramebuffersHelper(
3185 GLsizei n, const GLuint* client_ids) {
3186 for (GLsizei ii = 0; ii < n; ++ii) {
3187 if (GetFramebuffer(client_ids[ii])) {
3188 return false;
3191 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3192 glGenFramebuffersEXT(n, service_ids.get());
3193 for (GLsizei ii = 0; ii < n; ++ii) {
3194 CreateFramebuffer(client_ids[ii], service_ids[ii]);
3196 return true;
3199 bool GLES2DecoderImpl::GenRenderbuffersHelper(
3200 GLsizei n, const GLuint* client_ids) {
3201 for (GLsizei ii = 0; ii < n; ++ii) {
3202 if (GetRenderbuffer(client_ids[ii])) {
3203 return false;
3206 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3207 glGenRenderbuffersEXT(n, service_ids.get());
3208 for (GLsizei ii = 0; ii < n; ++ii) {
3209 CreateRenderbuffer(client_ids[ii], service_ids[ii]);
3211 return true;
3214 bool GLES2DecoderImpl::GenValuebuffersCHROMIUMHelper(GLsizei n,
3215 const GLuint* client_ids) {
3216 for (GLsizei ii = 0; ii < n; ++ii) {
3217 if (GetValuebuffer(client_ids[ii])) {
3218 return false;
3221 for (GLsizei ii = 0; ii < n; ++ii) {
3222 CreateValuebuffer(client_ids[ii]);
3224 return true;
3227 bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
3228 for (GLsizei ii = 0; ii < n; ++ii) {
3229 if (GetTexture(client_ids[ii])) {
3230 return false;
3233 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3234 glGenTextures(n, service_ids.get());
3235 for (GLsizei ii = 0; ii < n; ++ii) {
3236 CreateTexture(client_ids[ii], service_ids[ii]);
3238 return true;
3241 void GLES2DecoderImpl::DeleteBuffersHelper(
3242 GLsizei n, const GLuint* client_ids) {
3243 for (GLsizei ii = 0; ii < n; ++ii) {
3244 Buffer* buffer = GetBuffer(client_ids[ii]);
3245 if (buffer && !buffer->IsDeleted()) {
3246 buffer->RemoveMappedRange();
3247 state_.vertex_attrib_manager->Unbind(buffer);
3248 if (state_.bound_array_buffer.get() == buffer) {
3249 state_.bound_array_buffer = NULL;
3251 RemoveBuffer(client_ids[ii]);
3256 void GLES2DecoderImpl::DeleteFramebuffersHelper(
3257 GLsizei n, const GLuint* client_ids) {
3258 bool supports_separate_framebuffer_binds =
3259 features().chromium_framebuffer_multisample;
3261 for (GLsizei ii = 0; ii < n; ++ii) {
3262 Framebuffer* framebuffer =
3263 GetFramebuffer(client_ids[ii]);
3264 if (framebuffer && !framebuffer->IsDeleted()) {
3265 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
3266 GLenum target = supports_separate_framebuffer_binds ?
3267 GL_DRAW_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
3269 // Unbind attachments on FBO before deletion.
3270 if (workarounds().unbind_attachments_on_bound_render_fbo_delete)
3271 framebuffer->DoUnbindGLAttachmentsForWorkaround(target);
3273 glBindFramebufferEXT(target, GetBackbufferServiceId());
3274 framebuffer_state_.bound_draw_framebuffer = NULL;
3275 framebuffer_state_.clear_state_dirty = true;
3277 if (framebuffer == framebuffer_state_.bound_read_framebuffer.get()) {
3278 framebuffer_state_.bound_read_framebuffer = NULL;
3279 GLenum target = supports_separate_framebuffer_binds ?
3280 GL_READ_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
3281 glBindFramebufferEXT(target, GetBackbufferServiceId());
3283 OnFboChanged();
3284 RemoveFramebuffer(client_ids[ii]);
3289 void GLES2DecoderImpl::DeleteRenderbuffersHelper(
3290 GLsizei n, const GLuint* client_ids) {
3291 bool supports_separate_framebuffer_binds =
3292 features().chromium_framebuffer_multisample;
3293 for (GLsizei ii = 0; ii < n; ++ii) {
3294 Renderbuffer* renderbuffer =
3295 GetRenderbuffer(client_ids[ii]);
3296 if (renderbuffer && !renderbuffer->IsDeleted()) {
3297 if (state_.bound_renderbuffer.get() == renderbuffer) {
3298 state_.bound_renderbuffer = NULL;
3300 // Unbind from current framebuffers.
3301 if (supports_separate_framebuffer_binds) {
3302 if (framebuffer_state_.bound_read_framebuffer.get()) {
3303 framebuffer_state_.bound_read_framebuffer
3304 ->UnbindRenderbuffer(GL_READ_FRAMEBUFFER_EXT, renderbuffer);
3306 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3307 framebuffer_state_.bound_draw_framebuffer
3308 ->UnbindRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT, renderbuffer);
3310 } else {
3311 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3312 framebuffer_state_.bound_draw_framebuffer
3313 ->UnbindRenderbuffer(GL_FRAMEBUFFER, renderbuffer);
3316 framebuffer_state_.clear_state_dirty = true;
3317 RemoveRenderbuffer(client_ids[ii]);
3322 void GLES2DecoderImpl::DeleteValuebuffersCHROMIUMHelper(
3323 GLsizei n,
3324 const GLuint* client_ids) {
3325 for (GLsizei ii = 0; ii < n; ++ii) {
3326 Valuebuffer* valuebuffer = GetValuebuffer(client_ids[ii]);
3327 if (valuebuffer) {
3328 if (state_.bound_valuebuffer.get() == valuebuffer) {
3329 state_.bound_valuebuffer = NULL;
3331 RemoveValuebuffer(client_ids[ii]);
3336 void GLES2DecoderImpl::DeleteTexturesHelper(
3337 GLsizei n, const GLuint* client_ids) {
3338 bool supports_separate_framebuffer_binds =
3339 features().chromium_framebuffer_multisample;
3340 for (GLsizei ii = 0; ii < n; ++ii) {
3341 TextureRef* texture_ref = GetTexture(client_ids[ii]);
3342 if (texture_ref) {
3343 Texture* texture = texture_ref->texture();
3344 if (texture->IsAttachedToFramebuffer()) {
3345 framebuffer_state_.clear_state_dirty = true;
3347 // Unbind texture_ref from texture_ref units.
3348 for (size_t jj = 0; jj < state_.texture_units.size(); ++jj) {
3349 state_.texture_units[jj].Unbind(texture_ref);
3351 // Unbind from current framebuffers.
3352 if (supports_separate_framebuffer_binds) {
3353 if (framebuffer_state_.bound_read_framebuffer.get()) {
3354 framebuffer_state_.bound_read_framebuffer
3355 ->UnbindTexture(GL_READ_FRAMEBUFFER_EXT, texture_ref);
3357 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3358 framebuffer_state_.bound_draw_framebuffer
3359 ->UnbindTexture(GL_DRAW_FRAMEBUFFER_EXT, texture_ref);
3361 } else {
3362 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3363 framebuffer_state_.bound_draw_framebuffer
3364 ->UnbindTexture(GL_FRAMEBUFFER, texture_ref);
3367 #if defined(OS_MACOSX)
3368 GLuint service_id = texture->service_id();
3369 if (texture->target() == GL_TEXTURE_RECTANGLE_ARB) {
3370 ReleaseIOSurfaceForTexture(service_id);
3372 #endif
3373 RemoveTexture(client_ids[ii]);
3378 // } // anonymous namespace
3380 bool GLES2DecoderImpl::MakeCurrent() {
3381 if (!context_.get())
3382 return false;
3384 if (WasContextLost()) {
3385 LOG(ERROR) << " GLES2DecoderImpl: Trying to make lost context current.";
3386 return false;
3389 if (!context_->MakeCurrent(surface_.get())) {
3390 LOG(ERROR) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
3391 MarkContextLost(error::kMakeCurrentFailed);
3392 group_->LoseContexts(error::kUnknown);
3393 return false;
3396 if (CheckResetStatus()) {
3397 LOG(ERROR)
3398 << " GLES2DecoderImpl: Context reset detected after MakeCurrent.";
3399 group_->LoseContexts(error::kUnknown);
3400 return false;
3403 ProcessFinishedAsyncTransfers();
3405 // Rebind the FBO if it was unbound by the context.
3406 if (workarounds().unbind_fbo_on_context_switch)
3407 RestoreFramebufferBindings();
3409 framebuffer_state_.clear_state_dirty = true;
3411 return true;
3414 void GLES2DecoderImpl::ProcessFinishedAsyncTransfers() {
3415 ProcessPendingReadPixels();
3416 if (engine() && query_manager_.get())
3417 query_manager_->ProcessPendingTransferQueries();
3419 // TODO(epenner): Is there a better place to do this?
3420 // This needs to occur before we execute any batch of commands
3421 // from the client, as the client may have recieved an async
3422 // completion while issuing those commands.
3423 // "DidFlushStart" would be ideal if we had such a callback.
3424 async_pixel_transfer_manager_->BindCompletedAsyncTransfers();
3427 static void RebindCurrentFramebuffer(
3428 GLenum target,
3429 Framebuffer* framebuffer,
3430 GLuint back_buffer_service_id) {
3431 GLuint framebuffer_id = framebuffer ? framebuffer->service_id() : 0;
3433 if (framebuffer_id == 0) {
3434 framebuffer_id = back_buffer_service_id;
3437 glBindFramebufferEXT(target, framebuffer_id);
3440 void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
3441 framebuffer_state_.clear_state_dirty = true;
3443 if (!features().chromium_framebuffer_multisample) {
3444 RebindCurrentFramebuffer(
3445 GL_FRAMEBUFFER,
3446 framebuffer_state_.bound_draw_framebuffer.get(),
3447 GetBackbufferServiceId());
3448 } else {
3449 RebindCurrentFramebuffer(
3450 GL_READ_FRAMEBUFFER_EXT,
3451 framebuffer_state_.bound_read_framebuffer.get(),
3452 GetBackbufferServiceId());
3453 RebindCurrentFramebuffer(
3454 GL_DRAW_FRAMEBUFFER_EXT,
3455 framebuffer_state_.bound_draw_framebuffer.get(),
3456 GetBackbufferServiceId());
3458 OnFboChanged();
3461 bool GLES2DecoderImpl::CheckFramebufferValid(
3462 Framebuffer* framebuffer,
3463 GLenum target, const char* func_name) {
3464 if (!framebuffer) {
3465 if (surfaceless_)
3466 return false;
3467 if (backbuffer_needs_clear_bits_) {
3468 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3469 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1.f);
3470 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3471 glClearStencil(0);
3472 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
3473 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
3474 glClearDepth(1.0f);
3475 state_.SetDeviceDepthMask(GL_TRUE);
3476 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
3477 bool reset_draw_buffer = false;
3478 if ((backbuffer_needs_clear_bits_ & GL_COLOR_BUFFER_BIT) != 0 &&
3479 group_->draw_buffer() == GL_NONE) {
3480 reset_draw_buffer = true;
3481 GLenum buf = GL_BACK;
3482 if (GetBackbufferServiceId() != 0) // emulated backbuffer
3483 buf = GL_COLOR_ATTACHMENT0;
3484 glDrawBuffersARB(1, &buf);
3486 glClear(backbuffer_needs_clear_bits_);
3487 if (reset_draw_buffer) {
3488 GLenum buf = GL_NONE;
3489 glDrawBuffersARB(1, &buf);
3491 backbuffer_needs_clear_bits_ = 0;
3492 RestoreClearState();
3494 return true;
3497 if (framebuffer_manager()->IsComplete(framebuffer)) {
3498 return true;
3501 GLenum completeness = framebuffer->IsPossiblyComplete();
3502 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
3503 LOCAL_SET_GL_ERROR(
3504 GL_INVALID_FRAMEBUFFER_OPERATION, func_name, "framebuffer incomplete");
3505 return false;
3508 // Are all the attachments cleared?
3509 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
3510 texture_manager()->HaveUnclearedMips()) {
3511 if (!framebuffer->IsCleared()) {
3512 // Can we clear them?
3513 if (framebuffer->GetStatus(texture_manager(), target) !=
3514 GL_FRAMEBUFFER_COMPLETE) {
3515 LOCAL_SET_GL_ERROR(
3516 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
3517 "framebuffer incomplete (clear)");
3518 return false;
3520 ClearUnclearedAttachments(target, framebuffer);
3524 if (!framebuffer_manager()->IsComplete(framebuffer)) {
3525 if (framebuffer->GetStatus(texture_manager(), target) !=
3526 GL_FRAMEBUFFER_COMPLETE) {
3527 LOCAL_SET_GL_ERROR(
3528 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
3529 "framebuffer incomplete (check)");
3530 return false;
3532 framebuffer_manager()->MarkAsComplete(framebuffer);
3535 // NOTE: At this point we don't know if the framebuffer is complete but
3536 // we DO know that everything that needs to be cleared has been cleared.
3537 return true;
3540 bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name) {
3541 if (!features().chromium_framebuffer_multisample) {
3542 bool valid = CheckFramebufferValid(
3543 framebuffer_state_.bound_draw_framebuffer.get(), GL_FRAMEBUFFER_EXT,
3544 func_name);
3546 if (valid)
3547 OnUseFramebuffer();
3549 return valid;
3551 return CheckFramebufferValid(framebuffer_state_.bound_draw_framebuffer.get(),
3552 GL_DRAW_FRAMEBUFFER_EXT,
3553 func_name) &&
3554 CheckFramebufferValid(framebuffer_state_.bound_read_framebuffer.get(),
3555 GL_READ_FRAMEBUFFER_EXT,
3556 func_name);
3559 bool GLES2DecoderImpl::CheckBoundReadFramebufferColorAttachment(
3560 const char* func_name) {
3561 Framebuffer* framebuffer = features().chromium_framebuffer_multisample ?
3562 framebuffer_state_.bound_read_framebuffer.get() :
3563 framebuffer_state_.bound_draw_framebuffer.get();
3564 if (!framebuffer)
3565 return true;
3566 if (framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0) == NULL) {
3567 LOCAL_SET_GL_ERROR(
3568 GL_INVALID_OPERATION, func_name, "no color image attached");
3569 return false;
3571 return true;
3574 bool GLES2DecoderImpl::FormsTextureCopyingFeedbackLoop(
3575 TextureRef* texture, GLint level) {
3576 Framebuffer* framebuffer = features().chromium_framebuffer_multisample ?
3577 framebuffer_state_.bound_read_framebuffer.get() :
3578 framebuffer_state_.bound_draw_framebuffer.get();
3579 if (!framebuffer)
3580 return false;
3581 const Framebuffer::Attachment* attachment = framebuffer->GetAttachment(
3582 GL_COLOR_ATTACHMENT0);
3583 if (!attachment)
3584 return false;
3585 return attachment->FormsFeedbackLoop(texture, level);
3588 gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
3589 Framebuffer* framebuffer =
3590 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3591 if (framebuffer != NULL) {
3592 const Framebuffer::Attachment* attachment =
3593 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
3594 if (attachment) {
3595 return gfx::Size(attachment->width(), attachment->height());
3597 return gfx::Size(0, 0);
3598 } else if (offscreen_target_frame_buffer_.get()) {
3599 return offscreen_size_;
3600 } else {
3601 return surface_->GetSize();
3605 GLenum GLES2DecoderImpl::GetBoundReadFrameBufferTextureType() {
3606 Framebuffer* framebuffer =
3607 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3608 if (framebuffer != NULL) {
3609 return framebuffer->GetColorAttachmentTextureType();
3610 } else {
3611 return GL_UNSIGNED_BYTE;
3615 GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
3616 Framebuffer* framebuffer =
3617 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3618 if (framebuffer != NULL) {
3619 return framebuffer->GetColorAttachmentFormat();
3620 } else if (offscreen_target_frame_buffer_.get()) {
3621 return offscreen_target_color_format_;
3622 } else {
3623 return back_buffer_color_format_;
3627 GLenum GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
3628 Framebuffer* framebuffer =
3629 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3630 if (framebuffer != NULL) {
3631 return framebuffer->GetColorAttachmentFormat();
3632 } else if (offscreen_target_frame_buffer_.get()) {
3633 return offscreen_target_color_format_;
3634 } else {
3635 return back_buffer_color_format_;
3639 void GLES2DecoderImpl::UpdateParentTextureInfo() {
3640 if (!offscreen_saved_color_texture_info_.get())
3641 return;
3642 GLenum target = offscreen_saved_color_texture_info_->texture()->target();
3643 glBindTexture(target, offscreen_saved_color_texture_info_->service_id());
3644 texture_manager()->SetLevelInfo(
3645 offscreen_saved_color_texture_info_.get(),
3646 GL_TEXTURE_2D,
3647 0, // level
3648 GL_RGBA,
3649 offscreen_size_.width(),
3650 offscreen_size_.height(),
3651 1, // depth
3652 0, // border
3653 GL_RGBA,
3654 GL_UNSIGNED_BYTE,
3655 true);
3656 texture_manager()->SetParameteri(
3657 "UpdateParentTextureInfo",
3658 GetErrorState(),
3659 offscreen_saved_color_texture_info_.get(),
3660 GL_TEXTURE_MAG_FILTER,
3661 GL_LINEAR);
3662 texture_manager()->SetParameteri(
3663 "UpdateParentTextureInfo",
3664 GetErrorState(),
3665 offscreen_saved_color_texture_info_.get(),
3666 GL_TEXTURE_MIN_FILTER,
3667 GL_LINEAR);
3668 texture_manager()->SetParameteri(
3669 "UpdateParentTextureInfo",
3670 GetErrorState(),
3671 offscreen_saved_color_texture_info_.get(),
3672 GL_TEXTURE_WRAP_S,
3673 GL_CLAMP_TO_EDGE);
3674 texture_manager()->SetParameteri(
3675 "UpdateParentTextureInfo",
3676 GetErrorState(),
3677 offscreen_saved_color_texture_info_.get(),
3678 GL_TEXTURE_WRAP_T,
3679 GL_CLAMP_TO_EDGE);
3680 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
3681 &state_, target);
3682 glBindTexture(target, texture_ref ? texture_ref->service_id() : 0);
3685 void GLES2DecoderImpl::SetResizeCallback(
3686 const base::Callback<void(gfx::Size, float)>& callback) {
3687 resize_callback_ = callback;
3690 Logger* GLES2DecoderImpl::GetLogger() {
3691 return &logger_;
3694 void GLES2DecoderImpl::BeginDecoding() {
3695 gpu_tracer_->BeginDecoding();
3696 gpu_trace_commands_ = gpu_tracer_->IsTracing() && *gpu_decoder_category_;
3697 gpu_debug_commands_ = log_commands() || debug() || gpu_trace_commands_ ||
3698 (*cb_command_trace_category_ != 0);
3701 void GLES2DecoderImpl::EndDecoding() {
3702 gpu_tracer_->EndDecoding();
3705 ErrorState* GLES2DecoderImpl::GetErrorState() {
3706 return state_.GetErrorState();
3709 void GLES2DecoderImpl::SetShaderCacheCallback(
3710 const ShaderCacheCallback& callback) {
3711 shader_cache_callback_ = callback;
3714 void GLES2DecoderImpl::SetWaitSyncPointCallback(
3715 const WaitSyncPointCallback& callback) {
3716 wait_sync_point_callback_ = callback;
3719 AsyncPixelTransferManager*
3720 GLES2DecoderImpl::GetAsyncPixelTransferManager() {
3721 return async_pixel_transfer_manager_.get();
3724 void GLES2DecoderImpl::ResetAsyncPixelTransferManagerForTest() {
3725 async_pixel_transfer_manager_.reset();
3728 void GLES2DecoderImpl::SetAsyncPixelTransferManagerForTest(
3729 AsyncPixelTransferManager* manager) {
3730 async_pixel_transfer_manager_ = make_scoped_ptr(manager);
3733 bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
3734 uint32* service_texture_id) {
3735 TextureRef* texture_ref = texture_manager()->GetTexture(client_texture_id);
3736 if (texture_ref) {
3737 *service_texture_id = texture_ref->service_id();
3738 return true;
3740 return false;
3743 uint32 GLES2DecoderImpl::GetTextureUploadCount() {
3744 return texture_state_.texture_upload_count +
3745 async_pixel_transfer_manager_->GetTextureUploadCount();
3748 base::TimeDelta GLES2DecoderImpl::GetTotalTextureUploadTime() {
3749 return texture_state_.total_texture_upload_time +
3750 async_pixel_transfer_manager_->GetTotalTextureUploadTime();
3753 base::TimeDelta GLES2DecoderImpl::GetTotalProcessingCommandsTime() {
3754 return total_processing_commands_time_;
3757 void GLES2DecoderImpl::AddProcessingCommandsTime(base::TimeDelta time) {
3758 total_processing_commands_time_ += time;
3761 void GLES2DecoderImpl::Destroy(bool have_context) {
3762 if (!initialized())
3763 return;
3765 DCHECK(!have_context || context_->IsCurrent(NULL));
3767 // Unbind everything.
3768 state_.vertex_attrib_manager = NULL;
3769 state_.default_vertex_attrib_manager = NULL;
3770 state_.texture_units.clear();
3771 state_.bound_array_buffer = NULL;
3772 state_.current_queries.clear();
3773 framebuffer_state_.bound_read_framebuffer = NULL;
3774 framebuffer_state_.bound_draw_framebuffer = NULL;
3775 state_.bound_renderbuffer = NULL;
3776 state_.bound_valuebuffer = NULL;
3778 if (offscreen_saved_color_texture_info_.get()) {
3779 DCHECK(offscreen_target_color_texture_);
3780 DCHECK_EQ(offscreen_saved_color_texture_info_->service_id(),
3781 offscreen_saved_color_texture_->id());
3782 offscreen_saved_color_texture_->Invalidate();
3783 offscreen_saved_color_texture_info_ = NULL;
3785 if (have_context) {
3786 if (copy_texture_CHROMIUM_.get()) {
3787 copy_texture_CHROMIUM_->Destroy();
3788 copy_texture_CHROMIUM_.reset();
3791 clear_framebuffer_blit_.reset();
3793 if (state_.current_program.get()) {
3794 program_manager()->UnuseProgram(shader_manager(),
3795 state_.current_program.get());
3798 if (attrib_0_buffer_id_) {
3799 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
3801 if (fixed_attrib_buffer_id_) {
3802 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_);
3805 if (validation_texture_) {
3806 glDeleteTextures(1, &validation_texture_);
3807 glDeleteFramebuffersEXT(1, &validation_fbo_multisample_);
3808 glDeleteFramebuffersEXT(1, &validation_fbo_);
3811 if (offscreen_target_frame_buffer_.get())
3812 offscreen_target_frame_buffer_->Destroy();
3813 if (offscreen_target_color_texture_.get())
3814 offscreen_target_color_texture_->Destroy();
3815 if (offscreen_target_color_render_buffer_.get())
3816 offscreen_target_color_render_buffer_->Destroy();
3817 if (offscreen_target_depth_render_buffer_.get())
3818 offscreen_target_depth_render_buffer_->Destroy();
3819 if (offscreen_target_stencil_render_buffer_.get())
3820 offscreen_target_stencil_render_buffer_->Destroy();
3821 if (offscreen_saved_frame_buffer_.get())
3822 offscreen_saved_frame_buffer_->Destroy();
3823 if (offscreen_saved_color_texture_.get())
3824 offscreen_saved_color_texture_->Destroy();
3825 if (offscreen_resolved_frame_buffer_.get())
3826 offscreen_resolved_frame_buffer_->Destroy();
3827 if (offscreen_resolved_color_texture_.get())
3828 offscreen_resolved_color_texture_->Destroy();
3829 } else {
3830 if (offscreen_target_frame_buffer_.get())
3831 offscreen_target_frame_buffer_->Invalidate();
3832 if (offscreen_target_color_texture_.get())
3833 offscreen_target_color_texture_->Invalidate();
3834 if (offscreen_target_color_render_buffer_.get())
3835 offscreen_target_color_render_buffer_->Invalidate();
3836 if (offscreen_target_depth_render_buffer_.get())
3837 offscreen_target_depth_render_buffer_->Invalidate();
3838 if (offscreen_target_stencil_render_buffer_.get())
3839 offscreen_target_stencil_render_buffer_->Invalidate();
3840 if (offscreen_saved_frame_buffer_.get())
3841 offscreen_saved_frame_buffer_->Invalidate();
3842 if (offscreen_saved_color_texture_.get())
3843 offscreen_saved_color_texture_->Invalidate();
3844 if (offscreen_resolved_frame_buffer_.get())
3845 offscreen_resolved_frame_buffer_->Invalidate();
3846 if (offscreen_resolved_color_texture_.get())
3847 offscreen_resolved_color_texture_->Invalidate();
3850 // Current program must be cleared after calling ProgramManager::UnuseProgram.
3851 // Otherwise, we can leak objects. http://crbug.com/258772.
3852 // state_.current_program must be reset before group_ is reset because
3853 // the later deletes the ProgramManager object that referred by
3854 // state_.current_program object.
3855 state_.current_program = NULL;
3857 copy_texture_CHROMIUM_.reset();
3858 clear_framebuffer_blit_.reset();
3860 if (query_manager_.get()) {
3861 query_manager_->Destroy(have_context);
3862 query_manager_.reset();
3865 if (vertex_array_manager_ .get()) {
3866 vertex_array_manager_->Destroy(have_context);
3867 vertex_array_manager_.reset();
3870 if (image_manager_.get()) {
3871 image_manager_->Destroy(have_context);
3872 image_manager_.reset();
3875 offscreen_target_frame_buffer_.reset();
3876 offscreen_target_color_texture_.reset();
3877 offscreen_target_color_render_buffer_.reset();
3878 offscreen_target_depth_render_buffer_.reset();
3879 offscreen_target_stencil_render_buffer_.reset();
3880 offscreen_saved_frame_buffer_.reset();
3881 offscreen_saved_color_texture_.reset();
3882 offscreen_resolved_frame_buffer_.reset();
3883 offscreen_resolved_color_texture_.reset();
3885 // Need to release these before releasing |group_| which may own the
3886 // ShaderTranslatorCache.
3887 fragment_translator_ = NULL;
3888 vertex_translator_ = NULL;
3890 // Should destroy the transfer manager before the texture manager held
3891 // by the context group.
3892 async_pixel_transfer_manager_.reset();
3894 // Destroy the GPU Tracer which may own some in process GPU Timings.
3895 if (gpu_tracer_) {
3896 gpu_tracer_->Destroy(have_context);
3897 gpu_tracer_.reset();
3900 if (group_.get()) {
3901 framebuffer_manager()->RemoveObserver(this);
3902 group_->Destroy(this, have_context);
3903 group_ = NULL;
3906 if (context_.get()) {
3907 context_->ReleaseCurrent(NULL);
3908 context_ = NULL;
3911 #if defined(OS_MACOSX)
3912 for (TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.begin();
3913 it != texture_to_io_surface_map_.end(); ++it) {
3914 CFRelease(it->second);
3916 texture_to_io_surface_map_.clear();
3917 #endif
3920 void GLES2DecoderImpl::SetSurface(
3921 const scoped_refptr<gfx::GLSurface>& surface) {
3922 DCHECK(context_->IsCurrent(NULL));
3923 DCHECK(surface_.get());
3924 surface_ = surface;
3925 RestoreCurrentFramebufferBindings();
3928 void GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox& mailbox) {
3929 if (!offscreen_saved_color_texture_.get()) {
3930 LOG(ERROR) << "Called ProduceFrontBuffer on a non-offscreen context";
3931 return;
3933 if (!offscreen_saved_color_texture_info_.get()) {
3934 GLuint service_id = offscreen_saved_color_texture_->id();
3935 offscreen_saved_color_texture_info_ = TextureRef::Create(
3936 texture_manager(), 0, service_id);
3937 texture_manager()->SetTarget(offscreen_saved_color_texture_info_.get(),
3938 GL_TEXTURE_2D);
3939 UpdateParentTextureInfo();
3941 mailbox_manager()->ProduceTexture(
3942 mailbox, offscreen_saved_color_texture_info_->texture());
3945 bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
3946 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
3947 if (!is_offscreen) {
3948 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
3949 << " with an onscreen framebuffer.";
3950 return false;
3953 if (offscreen_size_ == size)
3954 return true;
3956 offscreen_size_ = size;
3957 int w = offscreen_size_.width();
3958 int h = offscreen_size_.height();
3959 if (w < 0 || h < 0 || h >= (INT_MAX / 4) / (w ? w : 1)) {
3960 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3961 << "to allocate storage due to excessive dimensions.";
3962 return false;
3965 // Reallocate the offscreen target buffers.
3966 DCHECK(offscreen_target_color_format_);
3967 if (IsOffscreenBufferMultisampled()) {
3968 if (!offscreen_target_color_render_buffer_->AllocateStorage(
3969 feature_info_.get(),
3970 offscreen_size_,
3971 offscreen_target_color_format_,
3972 offscreen_target_samples_)) {
3973 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3974 << "to allocate storage for offscreen target color buffer.";
3975 return false;
3977 } else {
3978 if (!offscreen_target_color_texture_->AllocateStorage(
3979 offscreen_size_, offscreen_target_color_format_, false)) {
3980 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3981 << "to allocate storage for offscreen target color texture.";
3982 return false;
3985 if (offscreen_target_depth_format_ &&
3986 !offscreen_target_depth_render_buffer_->AllocateStorage(
3987 feature_info_.get(),
3988 offscreen_size_,
3989 offscreen_target_depth_format_,
3990 offscreen_target_samples_)) {
3991 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3992 << "to allocate storage for offscreen target depth buffer.";
3993 return false;
3995 if (offscreen_target_stencil_format_ &&
3996 !offscreen_target_stencil_render_buffer_->AllocateStorage(
3997 feature_info_.get(),
3998 offscreen_size_,
3999 offscreen_target_stencil_format_,
4000 offscreen_target_samples_)) {
4001 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4002 << "to allocate storage for offscreen target stencil buffer.";
4003 return false;
4006 // Attach the offscreen target buffers to the target frame buffer.
4007 if (IsOffscreenBufferMultisampled()) {
4008 offscreen_target_frame_buffer_->AttachRenderBuffer(
4009 GL_COLOR_ATTACHMENT0,
4010 offscreen_target_color_render_buffer_.get());
4011 } else {
4012 offscreen_target_frame_buffer_->AttachRenderTexture(
4013 offscreen_target_color_texture_.get());
4015 if (offscreen_target_depth_format_) {
4016 offscreen_target_frame_buffer_->AttachRenderBuffer(
4017 GL_DEPTH_ATTACHMENT,
4018 offscreen_target_depth_render_buffer_.get());
4020 const bool packed_depth_stencil =
4021 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
4022 if (packed_depth_stencil) {
4023 offscreen_target_frame_buffer_->AttachRenderBuffer(
4024 GL_STENCIL_ATTACHMENT,
4025 offscreen_target_depth_render_buffer_.get());
4026 } else if (offscreen_target_stencil_format_) {
4027 offscreen_target_frame_buffer_->AttachRenderBuffer(
4028 GL_STENCIL_ATTACHMENT,
4029 offscreen_target_stencil_render_buffer_.get());
4032 if (offscreen_target_frame_buffer_->CheckStatus() !=
4033 GL_FRAMEBUFFER_COMPLETE) {
4034 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4035 << "because offscreen FBO was incomplete.";
4036 return false;
4039 // Clear the target frame buffer.
4041 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
4042 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
4043 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1.f);
4044 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4045 glClearStencil(0);
4046 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
4047 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
4048 glClearDepth(0);
4049 state_.SetDeviceDepthMask(GL_TRUE);
4050 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
4051 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
4052 RestoreClearState();
4055 // Destroy the offscreen resolved framebuffers.
4056 if (offscreen_resolved_frame_buffer_.get())
4057 offscreen_resolved_frame_buffer_->Destroy();
4058 if (offscreen_resolved_color_texture_.get())
4059 offscreen_resolved_color_texture_->Destroy();
4060 offscreen_resolved_color_texture_.reset();
4061 offscreen_resolved_frame_buffer_.reset();
4063 return true;
4066 error::Error GLES2DecoderImpl::HandleResizeCHROMIUM(uint32 immediate_data_size,
4067 const void* cmd_data) {
4068 const gles2::cmds::ResizeCHROMIUM& c =
4069 *static_cast<const gles2::cmds::ResizeCHROMIUM*>(cmd_data);
4070 if (!offscreen_target_frame_buffer_.get() && surface_->DeferDraws())
4071 return error::kDeferCommandUntilLater;
4073 GLuint width = static_cast<GLuint>(c.width);
4074 GLuint height = static_cast<GLuint>(c.height);
4075 GLfloat scale_factor = c.scale_factor;
4076 TRACE_EVENT2("gpu", "glResizeChromium", "width", width, "height", height);
4078 width = std::max(1U, width);
4079 height = std::max(1U, height);
4081 #if defined(OS_POSIX) && !defined(OS_MACOSX) && \
4082 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
4083 // Make sure that we are done drawing to the back buffer before resizing.
4084 glFinish();
4085 #endif
4086 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
4087 if (is_offscreen) {
4088 if (!ResizeOffscreenFrameBuffer(gfx::Size(width, height))) {
4089 LOG(ERROR) << "GLES2DecoderImpl: Context lost because "
4090 << "ResizeOffscreenFrameBuffer failed.";
4091 return error::kLostContext;
4095 if (!resize_callback_.is_null()) {
4096 resize_callback_.Run(gfx::Size(width, height), scale_factor);
4097 DCHECK(context_->IsCurrent(surface_.get()));
4098 if (!context_->IsCurrent(surface_.get())) {
4099 LOG(ERROR) << "GLES2DecoderImpl: Context lost because context no longer "
4100 << "current after resize callback.";
4101 return error::kLostContext;
4105 return error::kNoError;
4108 const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
4109 if (command_id > kStartPoint && command_id < kNumCommands) {
4110 return gles2::GetCommandName(static_cast<CommandId>(command_id));
4112 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
4115 // Decode a command, and call the corresponding GL functions.
4116 // NOTE: DoCommand() is slower than calling DoCommands() on larger batches
4117 // of commands at once, and is now only used for tests that need to track
4118 // individual commands.
4119 error::Error GLES2DecoderImpl::DoCommand(unsigned int command,
4120 unsigned int arg_count,
4121 const void* cmd_data) {
4122 return DoCommands(1, cmd_data, arg_count + 1, 0);
4125 // Decode multiple commands, and call the corresponding GL functions.
4126 // NOTE: 'buffer' is a pointer to the command buffer. As such, it could be
4127 // changed by a (malicious) client at any time, so if validation has to happen,
4128 // it should operate on a copy of them.
4129 // NOTE: This is duplicating code from AsyncAPIInterface::DoCommands() in the
4130 // interest of performance in this critical execution loop.
4131 template <bool DebugImpl>
4132 error::Error GLES2DecoderImpl::DoCommandsImpl(unsigned int num_commands,
4133 const void* buffer,
4134 int num_entries,
4135 int* entries_processed) {
4136 commands_to_process_ = num_commands;
4137 error::Error result = error::kNoError;
4138 const CommandBufferEntry* cmd_data =
4139 static_cast<const CommandBufferEntry*>(buffer);
4140 int process_pos = 0;
4141 unsigned int command = 0;
4143 while (process_pos < num_entries && result == error::kNoError &&
4144 commands_to_process_--) {
4145 const unsigned int size = cmd_data->value_header.size;
4146 command = cmd_data->value_header.command;
4148 if (size == 0) {
4149 result = error::kInvalidSize;
4150 break;
4153 if (static_cast<int>(size) + process_pos > num_entries) {
4154 result = error::kOutOfBounds;
4155 break;
4158 if (DebugImpl) {
4159 TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
4160 GetCommandName(command));
4162 if (log_commands()) {
4163 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "]"
4164 << "cmd: " << GetCommandName(command);
4168 const unsigned int arg_count = size - 1;
4169 unsigned int command_index = command - kStartPoint - 1;
4170 if (command_index < arraysize(command_info)) {
4171 const CommandInfo& info = command_info[command_index];
4172 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
4173 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
4174 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
4175 bool doing_gpu_trace = false;
4176 if (DebugImpl && gpu_trace_commands_) {
4177 if (CMD_FLAG_GET_TRACE_LEVEL(info.cmd_flags) <= gpu_trace_level_) {
4178 doing_gpu_trace = true;
4179 gpu_tracer_->Begin(TRACE_DISABLED_BY_DEFAULT("gpu_decoder"),
4180 GetCommandName(command),
4181 kTraceDecoder);
4185 uint32 immediate_data_size = (arg_count - info_arg_count) *
4186 sizeof(CommandBufferEntry); // NOLINT
4188 result = (this->*info.cmd_handler)(immediate_data_size, cmd_data);
4190 if (DebugImpl && doing_gpu_trace)
4191 gpu_tracer_->End(kTraceDecoder);
4193 if (DebugImpl && debug()) {
4194 GLenum error;
4195 while ((error = glGetError()) != GL_NO_ERROR) {
4196 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "] "
4197 << "GL ERROR: " << GLES2Util::GetStringEnum(error)
4198 << " : " << GetCommandName(command);
4199 LOCAL_SET_GL_ERROR(error, "DoCommand", "GL error from driver");
4202 } else {
4203 result = error::kInvalidArguments;
4205 } else {
4206 result = DoCommonCommand(command, arg_count, cmd_data);
4209 if (DebugImpl) {
4210 TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
4211 GetCommandName(command));
4214 if (result == error::kNoError &&
4215 current_decoder_error_ != error::kNoError) {
4216 result = current_decoder_error_;
4217 current_decoder_error_ = error::kNoError;
4220 if (result != error::kDeferCommandUntilLater) {
4221 process_pos += size;
4222 cmd_data += size;
4226 if (entries_processed)
4227 *entries_processed = process_pos;
4229 if (error::IsError(result)) {
4230 LOG(ERROR) << "Error: " << result << " for Command "
4231 << GetCommandName(command);
4234 return result;
4237 error::Error GLES2DecoderImpl::DoCommands(unsigned int num_commands,
4238 const void* buffer,
4239 int num_entries,
4240 int* entries_processed) {
4241 if (gpu_debug_commands_) {
4242 return DoCommandsImpl<true>(
4243 num_commands, buffer, num_entries, entries_processed);
4244 } else {
4245 return DoCommandsImpl<false>(
4246 num_commands, buffer, num_entries, entries_processed);
4250 void GLES2DecoderImpl::RemoveBuffer(GLuint client_id) {
4251 buffer_manager()->RemoveBuffer(client_id);
4254 void GLES2DecoderImpl::DoFinish() {
4255 glFinish();
4256 ProcessPendingReadPixels();
4257 ProcessPendingQueries(true);
4260 void GLES2DecoderImpl::DoFlush() {
4261 glFlush();
4262 ProcessPendingQueries(false);
4265 void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
4266 GLuint texture_index = texture_unit - GL_TEXTURE0;
4267 if (texture_index >= state_.texture_units.size()) {
4268 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4269 "glActiveTexture", texture_unit, "texture_unit");
4270 return;
4272 state_.active_texture_unit = texture_index;
4273 glActiveTexture(texture_unit);
4276 void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
4277 Buffer* buffer = NULL;
4278 GLuint service_id = 0;
4279 if (client_id != 0) {
4280 buffer = GetBuffer(client_id);
4281 if (!buffer) {
4282 if (!group_->bind_generates_resource()) {
4283 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4284 "glBindBuffer",
4285 "id not generated by glGenBuffers");
4286 return;
4289 // It's a new id so make a buffer buffer for it.
4290 glGenBuffersARB(1, &service_id);
4291 CreateBuffer(client_id, service_id);
4292 buffer = GetBuffer(client_id);
4295 LogClientServiceForInfo(buffer, client_id, "glBindBuffer");
4296 if (buffer) {
4297 if (!buffer_manager()->SetTarget(buffer, target)) {
4298 LOCAL_SET_GL_ERROR(
4299 GL_INVALID_OPERATION,
4300 "glBindBuffer", "buffer bound to more than 1 target");
4301 return;
4303 service_id = buffer->service_id();
4305 switch (target) {
4306 case GL_ARRAY_BUFFER:
4307 state_.bound_array_buffer = buffer;
4308 break;
4309 case GL_ELEMENT_ARRAY_BUFFER:
4310 state_.vertex_attrib_manager->SetElementArrayBuffer(buffer);
4311 break;
4312 default:
4313 NOTREACHED(); // Validation should prevent us getting here.
4314 break;
4316 glBindBuffer(target, service_id);
4319 bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha(
4320 bool all_draw_buffers) {
4321 Framebuffer* framebuffer =
4322 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4323 if (!all_draw_buffers || !framebuffer) {
4324 return (GLES2Util::GetChannelsForFormat(
4325 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
4327 return framebuffer->HasAlphaMRT();
4330 bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
4331 Framebuffer* framebuffer =
4332 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4333 if (framebuffer) {
4334 return framebuffer->HasDepthAttachment();
4336 if (offscreen_target_frame_buffer_.get()) {
4337 return offscreen_target_depth_format_ != 0;
4339 return back_buffer_has_depth_;
4342 bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
4343 Framebuffer* framebuffer =
4344 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4345 if (framebuffer) {
4346 return framebuffer->HasStencilAttachment();
4348 if (offscreen_target_frame_buffer_.get()) {
4349 return offscreen_target_stencil_format_ != 0 ||
4350 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
4352 return back_buffer_has_stencil_;
4355 void GLES2DecoderImpl::ApplyDirtyState() {
4356 if (framebuffer_state_.clear_state_dirty) {
4357 bool have_alpha = BoundFramebufferHasColorAttachmentWithAlpha(true);
4358 state_.SetDeviceColorMask(state_.color_mask_red,
4359 state_.color_mask_green,
4360 state_.color_mask_blue,
4361 state_.color_mask_alpha && have_alpha);
4363 bool have_depth = BoundFramebufferHasDepthAttachment();
4364 state_.SetDeviceDepthMask(state_.depth_mask && have_depth);
4366 bool have_stencil = BoundFramebufferHasStencilAttachment();
4367 state_.SetDeviceStencilMaskSeparate(
4368 GL_FRONT, have_stencil ? state_.stencil_front_writemask : 0);
4369 state_.SetDeviceStencilMaskSeparate(
4370 GL_BACK, have_stencil ? state_.stencil_back_writemask : 0);
4372 state_.SetDeviceCapabilityState(
4373 GL_DEPTH_TEST, state_.enable_flags.depth_test && have_depth);
4374 state_.SetDeviceCapabilityState(
4375 GL_STENCIL_TEST, state_.enable_flags.stencil_test && have_stencil);
4376 framebuffer_state_.clear_state_dirty = false;
4380 GLuint GLES2DecoderImpl::GetBackbufferServiceId() const {
4381 return (offscreen_target_frame_buffer_.get())
4382 ? offscreen_target_frame_buffer_->id()
4383 : (surface_.get() ? surface_->GetBackingFrameBufferObject() : 0);
4386 void GLES2DecoderImpl::RestoreState(const ContextState* prev_state) {
4387 TRACE_EVENT1("gpu", "GLES2DecoderImpl::RestoreState",
4388 "context", logger_.GetLogPrefix());
4389 // Restore the Framebuffer first because of bugs in Intel drivers.
4390 // Intel drivers incorrectly clip the viewport settings to
4391 // the size of the current framebuffer object.
4392 RestoreFramebufferBindings();
4393 state_.RestoreState(prev_state);
4396 void GLES2DecoderImpl::RestoreFramebufferBindings() const {
4397 GLuint service_id =
4398 framebuffer_state_.bound_draw_framebuffer.get()
4399 ? framebuffer_state_.bound_draw_framebuffer->service_id()
4400 : GetBackbufferServiceId();
4401 if (!features().chromium_framebuffer_multisample) {
4402 glBindFramebufferEXT(GL_FRAMEBUFFER, service_id);
4403 } else {
4404 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, service_id);
4405 service_id = framebuffer_state_.bound_read_framebuffer.get()
4406 ? framebuffer_state_.bound_read_framebuffer->service_id()
4407 : GetBackbufferServiceId();
4408 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, service_id);
4410 OnFboChanged();
4413 void GLES2DecoderImpl::RestoreRenderbufferBindings() {
4414 state_.RestoreRenderbufferBindings();
4417 void GLES2DecoderImpl::RestoreTextureState(unsigned service_id) const {
4418 Texture* texture = texture_manager()->GetTextureForServiceId(service_id);
4419 if (texture) {
4420 GLenum target = texture->target();
4421 glBindTexture(target, service_id);
4422 glTexParameteri(
4423 target, GL_TEXTURE_WRAP_S, texture->wrap_s());
4424 glTexParameteri(
4425 target, GL_TEXTURE_WRAP_T, texture->wrap_t());
4426 glTexParameteri(
4427 target, GL_TEXTURE_MIN_FILTER, texture->min_filter());
4428 glTexParameteri(
4429 target, GL_TEXTURE_MAG_FILTER, texture->mag_filter());
4430 RestoreTextureUnitBindings(state_.active_texture_unit);
4434 void GLES2DecoderImpl::ClearAllAttributes() const {
4435 // Must use native VAO 0, as RestoreAllAttributes can't fully restore
4436 // other VAOs.
4437 if (feature_info_->feature_flags().native_vertex_array_object)
4438 glBindVertexArrayOES(0);
4440 for (uint32 i = 0; i < group_->max_vertex_attribs(); ++i) {
4441 if (i != 0) // Never disable attribute 0
4442 glDisableVertexAttribArray(i);
4443 if (features().angle_instanced_arrays)
4444 glVertexAttribDivisorANGLE(i, 0);
4448 void GLES2DecoderImpl::RestoreAllAttributes() const {
4449 state_.RestoreVertexAttribs();
4452 void GLES2DecoderImpl::SetIgnoreCachedStateForTest(bool ignore) {
4453 state_.SetIgnoreCachedStateForTest(ignore);
4456 void GLES2DecoderImpl::OnFboChanged() const {
4457 if (workarounds().restore_scissor_on_fbo_change)
4458 state_.fbo_binding_for_scissor_workaround_dirty = true;
4460 if (workarounds().gl_begin_gl_end_on_fbo_change_to_backbuffer) {
4461 GLint bound_fbo_unsigned = -1;
4462 glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &bound_fbo_unsigned);
4463 GLuint bound_fbo = static_cast<GLuint>(bound_fbo_unsigned);
4464 if (surface_ && surface_->GetBackingFrameBufferObject() == bound_fbo)
4465 surface_->NotifyWasBound();
4469 // Called after the FBO is checked for completeness.
4470 void GLES2DecoderImpl::OnUseFramebuffer() const {
4471 if (state_.fbo_binding_for_scissor_workaround_dirty) {
4472 state_.fbo_binding_for_scissor_workaround_dirty = false;
4473 // The driver forgets the correct scissor when modifying the FBO binding.
4474 glScissor(state_.scissor_x,
4475 state_.scissor_y,
4476 state_.scissor_width,
4477 state_.scissor_height);
4479 // crbug.com/222018 - Also on QualComm, the flush here avoids flicker,
4480 // it's unclear how this bug works.
4481 glFlush();
4485 void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
4486 Framebuffer* framebuffer = NULL;
4487 GLuint service_id = 0;
4488 if (client_id != 0) {
4489 framebuffer = GetFramebuffer(client_id);
4490 if (!framebuffer) {
4491 if (!group_->bind_generates_resource()) {
4492 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4493 "glBindFramebuffer",
4494 "id not generated by glGenFramebuffers");
4495 return;
4498 // It's a new id so make a framebuffer framebuffer for it.
4499 glGenFramebuffersEXT(1, &service_id);
4500 CreateFramebuffer(client_id, service_id);
4501 framebuffer = GetFramebuffer(client_id);
4502 } else {
4503 service_id = framebuffer->service_id();
4505 framebuffer->MarkAsValid();
4507 LogClientServiceForInfo(framebuffer, client_id, "glBindFramebuffer");
4509 if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) {
4510 framebuffer_state_.bound_draw_framebuffer = framebuffer;
4513 // vmiura: This looks like dup code
4514 if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) {
4515 framebuffer_state_.bound_read_framebuffer = framebuffer;
4518 framebuffer_state_.clear_state_dirty = true;
4520 // If we are rendering to the backbuffer get the FBO id for any simulated
4521 // backbuffer.
4522 if (framebuffer == NULL) {
4523 service_id = GetBackbufferServiceId();
4526 glBindFramebufferEXT(target, service_id);
4527 OnFboChanged();
4530 void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
4531 Renderbuffer* renderbuffer = NULL;
4532 GLuint service_id = 0;
4533 if (client_id != 0) {
4534 renderbuffer = GetRenderbuffer(client_id);
4535 if (!renderbuffer) {
4536 if (!group_->bind_generates_resource()) {
4537 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4538 "glBindRenderbuffer",
4539 "id not generated by glGenRenderbuffers");
4540 return;
4543 // It's a new id so make a renderbuffer for it.
4544 glGenRenderbuffersEXT(1, &service_id);
4545 CreateRenderbuffer(client_id, service_id);
4546 renderbuffer = GetRenderbuffer(client_id);
4547 } else {
4548 service_id = renderbuffer->service_id();
4550 renderbuffer->MarkAsValid();
4552 LogClientServiceForInfo(renderbuffer, client_id, "glBindRenderbuffer");
4553 state_.bound_renderbuffer = renderbuffer;
4554 state_.bound_renderbuffer_valid = true;
4555 glBindRenderbufferEXT(GL_RENDERBUFFER, service_id);
4558 void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
4559 TextureRef* texture_ref = NULL;
4560 GLuint service_id = 0;
4561 if (client_id != 0) {
4562 texture_ref = GetTexture(client_id);
4563 if (!texture_ref) {
4564 if (!group_->bind_generates_resource()) {
4565 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4566 "glBindTexture",
4567 "id not generated by glGenTextures");
4568 return;
4571 // It's a new id so make a texture texture for it.
4572 glGenTextures(1, &service_id);
4573 DCHECK_NE(0u, service_id);
4574 CreateTexture(client_id, service_id);
4575 texture_ref = GetTexture(client_id);
4577 } else {
4578 texture_ref = texture_manager()->GetDefaultTextureInfo(target);
4581 // Check the texture exists
4582 if (texture_ref) {
4583 Texture* texture = texture_ref->texture();
4584 // Check that we are not trying to bind it to a different target.
4585 if (texture->target() != 0 && texture->target() != target) {
4586 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4587 "glBindTexture",
4588 "texture bound to more than 1 target.");
4589 return;
4591 LogClientServiceForInfo(texture, client_id, "glBindTexture");
4592 if (texture->target() == 0) {
4593 texture_manager()->SetTarget(texture_ref, target);
4595 glBindTexture(target, texture->service_id());
4596 } else {
4597 glBindTexture(target, 0);
4600 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4601 unit.bind_target = target;
4602 switch (target) {
4603 case GL_TEXTURE_2D:
4604 unit.bound_texture_2d = texture_ref;
4605 break;
4606 case GL_TEXTURE_CUBE_MAP:
4607 unit.bound_texture_cube_map = texture_ref;
4608 break;
4609 case GL_TEXTURE_EXTERNAL_OES:
4610 unit.bound_texture_external_oes = texture_ref;
4611 break;
4612 case GL_TEXTURE_RECTANGLE_ARB:
4613 unit.bound_texture_rectangle_arb = texture_ref;
4614 break;
4615 case GL_TEXTURE_3D:
4616 unit.bound_texture_3d = texture_ref;
4617 break;
4618 case GL_TEXTURE_2D_ARRAY:
4619 unit.bound_texture_2d_array = texture_ref;
4620 break;
4621 default:
4622 NOTREACHED(); // Validation should prevent us getting here.
4623 break;
4627 void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
4628 if (state_.vertex_attrib_manager->Enable(index, false)) {
4629 if (index != 0 ||
4630 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
4631 glDisableVertexAttribArray(index);
4633 } else {
4634 LOCAL_SET_GL_ERROR(
4635 GL_INVALID_VALUE,
4636 "glDisableVertexAttribArray", "index out of range");
4640 void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target,
4641 GLsizei numAttachments,
4642 const GLenum* attachments) {
4643 if (workarounds().disable_discard_framebuffer)
4644 return;
4646 Framebuffer* framebuffer =
4647 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4649 // Validates the attachments. If one of them fails
4650 // the whole command fails.
4651 for (GLsizei i = 0; i < numAttachments; ++i) {
4652 if ((framebuffer &&
4653 !validators_->attachment.IsValid(attachments[i])) ||
4654 (!framebuffer &&
4655 !validators_->backbuffer_attachment.IsValid(attachments[i]))) {
4656 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4657 "glDiscardFramebufferEXT", attachments[i], "attachments");
4658 return;
4662 // Marks each one of them as not cleared
4663 for (GLsizei i = 0; i < numAttachments; ++i) {
4664 if (framebuffer) {
4665 framebuffer->MarkAttachmentAsCleared(renderbuffer_manager(),
4666 texture_manager(),
4667 attachments[i],
4668 false);
4669 } else {
4670 switch (attachments[i]) {
4671 case GL_COLOR_EXT:
4672 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
4673 break;
4674 case GL_DEPTH_EXT:
4675 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
4676 case GL_STENCIL_EXT:
4677 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
4678 break;
4679 default:
4680 NOTREACHED();
4681 break;
4686 // If the default framebuffer is bound but we are still rendering to an
4687 // FBO, translate attachment names that refer to default framebuffer
4688 // channels to corresponding framebuffer attachments.
4689 scoped_ptr<GLenum[]> translated_attachments(new GLenum[numAttachments]);
4690 for (GLsizei i = 0; i < numAttachments; ++i) {
4691 GLenum attachment = attachments[i];
4692 if (!framebuffer && GetBackbufferServiceId()) {
4693 switch (attachment) {
4694 case GL_COLOR_EXT:
4695 attachment = GL_COLOR_ATTACHMENT0;
4696 break;
4697 case GL_DEPTH_EXT:
4698 attachment = GL_DEPTH_ATTACHMENT;
4699 break;
4700 case GL_STENCIL_EXT:
4701 attachment = GL_STENCIL_ATTACHMENT;
4702 break;
4703 default:
4704 NOTREACHED();
4705 return;
4708 translated_attachments[i] = attachment;
4711 ScopedRenderTo do_render(framebuffer);
4712 if (feature_info_->gl_version_info().is_es3) {
4713 glInvalidateFramebuffer(
4714 target, numAttachments, translated_attachments.get());
4715 } else {
4716 glDiscardFramebufferEXT(
4717 target, numAttachments, translated_attachments.get());
4721 void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
4722 if (state_.vertex_attrib_manager->Enable(index, true)) {
4723 glEnableVertexAttribArray(index);
4724 } else {
4725 LOCAL_SET_GL_ERROR(
4726 GL_INVALID_VALUE, "glEnableVertexAttribArray", "index out of range");
4730 void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
4731 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
4732 &state_, target);
4733 if (!texture_ref ||
4734 !texture_manager()->CanGenerateMipmaps(texture_ref)) {
4735 LOCAL_SET_GL_ERROR(
4736 GL_INVALID_OPERATION, "glGenerateMipmap", "Can not generate mips");
4737 return;
4740 if (target == GL_TEXTURE_CUBE_MAP) {
4741 for (int i = 0; i < 6; ++i) {
4742 GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;
4743 if (!texture_manager()->ClearTextureLevel(this, texture_ref, face, 0)) {
4744 LOCAL_SET_GL_ERROR(
4745 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
4746 return;
4749 } else {
4750 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, 0)) {
4751 LOCAL_SET_GL_ERROR(
4752 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
4753 return;
4757 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glGenerateMipmap");
4758 // Workaround for Mac driver bug. In the large scheme of things setting
4759 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
4760 // hit so there's probably no need to make this conditional. The bug appears
4761 // to be that if the filtering mode is set to something that doesn't require
4762 // mipmaps for rendering, or is never set to something other than the default,
4763 // then glGenerateMipmap misbehaves.
4764 if (workarounds().set_texture_filter_before_generating_mipmap) {
4765 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
4767 glGenerateMipmapEXT(target);
4768 if (workarounds().set_texture_filter_before_generating_mipmap) {
4769 glTexParameteri(target, GL_TEXTURE_MIN_FILTER,
4770 texture_ref->texture()->min_filter());
4772 GLenum error = LOCAL_PEEK_GL_ERROR("glGenerateMipmap");
4773 if (error == GL_NO_ERROR) {
4774 texture_manager()->MarkMipmapsGenerated(texture_ref);
4778 bool GLES2DecoderImpl::GetHelper(
4779 GLenum pname, GLint* params, GLsizei* num_written) {
4780 DCHECK(num_written);
4781 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
4782 switch (pname) {
4783 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
4784 *num_written = 1;
4785 // Return the GL implementation's preferred format and (see below type)
4786 // if we have the GL extension that exposes this. This allows the GPU
4787 // client to use the implementation's preferred format for glReadPixels
4788 // for optimisation.
4790 // A conflicting extension (GL_ARB_ES2_compatibility) specifies an error
4791 // case when requested on integer/floating point buffers but which is
4792 // acceptable on GLES2 and with the GL_OES_read_format extension.
4794 // Therefore if an error occurs we swallow the error and use the
4795 // internal implementation.
4796 if (params) {
4797 if (context_->HasExtension("GL_OES_read_format")) {
4798 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper",
4799 GetErrorState());
4800 glGetIntegerv(pname, params);
4801 if (glGetError() == GL_NO_ERROR)
4802 return true;
4804 *params = GLES2Util::GetPreferredGLReadPixelsFormat(
4805 GetBoundReadFrameBufferInternalFormat());
4807 return true;
4808 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
4809 *num_written = 1;
4810 if (params) {
4811 if (context_->HasExtension("GL_OES_read_format")) {
4812 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper",
4813 GetErrorState());
4814 glGetIntegerv(pname, params);
4815 if (glGetError() == GL_NO_ERROR)
4816 return true;
4818 *params = GLES2Util::GetPreferredGLReadPixelsType(
4819 GetBoundReadFrameBufferInternalFormat(),
4820 GetBoundReadFrameBufferTextureType());
4822 return true;
4823 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
4824 *num_written = 1;
4825 if (params) {
4826 *params = group_->max_fragment_uniform_vectors();
4828 return true;
4829 case GL_MAX_VARYING_VECTORS:
4830 *num_written = 1;
4831 if (params) {
4832 *params = group_->max_varying_vectors();
4834 return true;
4835 case GL_MAX_VERTEX_UNIFORM_VECTORS:
4836 *num_written = 1;
4837 if (params) {
4838 *params = group_->max_vertex_uniform_vectors();
4840 return true;
4843 switch (pname) {
4844 case GL_MAX_VIEWPORT_DIMS:
4845 if (offscreen_target_frame_buffer_.get()) {
4846 *num_written = 2;
4847 if (params) {
4848 params[0] = renderbuffer_manager()->max_renderbuffer_size();
4849 params[1] = renderbuffer_manager()->max_renderbuffer_size();
4851 return true;
4853 return false;
4854 case GL_MAX_SAMPLES:
4855 *num_written = 1;
4856 if (params) {
4857 params[0] = renderbuffer_manager()->max_samples();
4859 return true;
4860 case GL_MAX_RENDERBUFFER_SIZE:
4861 *num_written = 1;
4862 if (params) {
4863 params[0] = renderbuffer_manager()->max_renderbuffer_size();
4865 return true;
4866 case GL_MAX_TEXTURE_SIZE:
4867 *num_written = 1;
4868 if (params) {
4869 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D);
4871 return true;
4872 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
4873 *num_written = 1;
4874 if (params) {
4875 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP);
4877 return true;
4878 case GL_MAX_COLOR_ATTACHMENTS_EXT:
4879 *num_written = 1;
4880 if (params) {
4881 params[0] = group_->max_color_attachments();
4883 return true;
4884 case GL_MAX_DRAW_BUFFERS_ARB:
4885 *num_written = 1;
4886 if (params) {
4887 params[0] = group_->max_draw_buffers();
4889 return true;
4890 case GL_ALPHA_BITS:
4891 *num_written = 1;
4892 if (params) {
4893 GLint v = 0;
4894 if (feature_info_->gl_version_info().is_desktop_core_profile) {
4895 Framebuffer* framebuffer =
4896 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4897 if (framebuffer) {
4898 glGetFramebufferAttachmentParameterivEXT(
4899 GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
4900 GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE, &v);
4901 } else {
4902 v = (back_buffer_color_format_ == GL_RGBA ? 8 : 0);
4904 } else {
4905 glGetIntegerv(GL_ALPHA_BITS, &v);
4907 params[0] =
4908 BoundFramebufferHasColorAttachmentWithAlpha(false) ? v : 0;
4910 return true;
4911 case GL_DEPTH_BITS:
4912 *num_written = 1;
4913 if (params) {
4914 GLint v = 0;
4915 if (feature_info_->gl_version_info().is_desktop_core_profile) {
4916 Framebuffer* framebuffer =
4917 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4918 if (framebuffer) {
4919 glGetFramebufferAttachmentParameterivEXT(
4920 GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
4921 GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE, &v);
4922 } else {
4923 v = (back_buffer_has_depth_ ? 24 : 0);
4925 } else {
4926 glGetIntegerv(GL_DEPTH_BITS, &v);
4928 params[0] = BoundFramebufferHasDepthAttachment() ? v : 0;
4930 return true;
4931 case GL_RED_BITS:
4932 case GL_GREEN_BITS:
4933 case GL_BLUE_BITS:
4934 *num_written = 1;
4935 if (params) {
4936 GLint v = 0;
4937 if (feature_info_->gl_version_info().is_desktop_core_profile) {
4938 Framebuffer* framebuffer =
4939 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4940 if (framebuffer) {
4941 GLenum framebuffer_enum = 0;
4942 switch (pname) {
4943 case GL_RED_BITS:
4944 framebuffer_enum = GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE;
4945 break;
4946 case GL_GREEN_BITS:
4947 framebuffer_enum = GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE;
4948 break;
4949 case GL_BLUE_BITS:
4950 framebuffer_enum = GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE;
4951 break;
4953 glGetFramebufferAttachmentParameterivEXT(
4954 GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, framebuffer_enum, &v);
4955 } else {
4956 v = 8;
4958 } else {
4959 glGetIntegerv(pname, &v);
4961 params[0] = v;
4963 return true;
4964 case GL_STENCIL_BITS:
4965 *num_written = 1;
4966 if (params) {
4967 GLint v = 0;
4968 if (feature_info_->gl_version_info().is_desktop_core_profile) {
4969 Framebuffer* framebuffer =
4970 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4971 if (framebuffer) {
4972 glGetFramebufferAttachmentParameterivEXT(
4973 GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
4974 GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE, &v);
4975 } else {
4976 v = (back_buffer_has_stencil_ ? 8 : 0);
4978 } else {
4979 glGetIntegerv(GL_STENCIL_BITS, &v);
4981 params[0] = BoundFramebufferHasStencilAttachment() ? v : 0;
4983 return true;
4984 case GL_COMPRESSED_TEXTURE_FORMATS:
4985 *num_written = validators_->compressed_texture_format.GetValues().size();
4986 if (params) {
4987 for (GLint ii = 0; ii < *num_written; ++ii) {
4988 params[ii] = validators_->compressed_texture_format.GetValues()[ii];
4991 return true;
4992 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
4993 *num_written = 1;
4994 if (params) {
4995 *params = validators_->compressed_texture_format.GetValues().size();
4997 return true;
4998 case GL_NUM_SHADER_BINARY_FORMATS:
4999 *num_written = 1;
5000 if (params) {
5001 *params = validators_->shader_binary_format.GetValues().size();
5003 return true;
5004 case GL_SHADER_BINARY_FORMATS:
5005 *num_written = validators_->shader_binary_format.GetValues().size();
5006 if (params) {
5007 for (GLint ii = 0; ii < *num_written; ++ii) {
5008 params[ii] = validators_->shader_binary_format.GetValues()[ii];
5011 return true;
5012 case GL_SHADER_COMPILER:
5013 *num_written = 1;
5014 if (params) {
5015 *params = GL_TRUE;
5017 return true;
5018 case GL_ARRAY_BUFFER_BINDING:
5019 *num_written = 1;
5020 if (params) {
5021 if (state_.bound_array_buffer.get()) {
5022 GLuint client_id = 0;
5023 buffer_manager()->GetClientId(state_.bound_array_buffer->service_id(),
5024 &client_id);
5025 *params = client_id;
5026 } else {
5027 *params = 0;
5030 return true;
5031 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
5032 *num_written = 1;
5033 if (params) {
5034 if (state_.vertex_attrib_manager->element_array_buffer()) {
5035 GLuint client_id = 0;
5036 buffer_manager()->GetClientId(
5037 state_.vertex_attrib_manager->element_array_buffer()->
5038 service_id(), &client_id);
5039 *params = client_id;
5040 } else {
5041 *params = 0;
5044 return true;
5045 case GL_FRAMEBUFFER_BINDING:
5046 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
5047 *num_written = 1;
5048 if (params) {
5049 Framebuffer* framebuffer =
5050 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
5051 if (framebuffer) {
5052 GLuint client_id = 0;
5053 framebuffer_manager()->GetClientId(
5054 framebuffer->service_id(), &client_id);
5055 *params = client_id;
5056 } else {
5057 *params = 0;
5060 return true;
5061 case GL_READ_FRAMEBUFFER_BINDING_EXT:
5062 *num_written = 1;
5063 if (params) {
5064 Framebuffer* framebuffer =
5065 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
5066 if (framebuffer) {
5067 GLuint client_id = 0;
5068 framebuffer_manager()->GetClientId(
5069 framebuffer->service_id(), &client_id);
5070 *params = client_id;
5071 } else {
5072 *params = 0;
5075 return true;
5076 case GL_RENDERBUFFER_BINDING:
5077 *num_written = 1;
5078 if (params) {
5079 Renderbuffer* renderbuffer =
5080 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5081 if (renderbuffer) {
5082 *params = renderbuffer->client_id();
5083 } else {
5084 *params = 0;
5087 return true;
5088 case GL_CURRENT_PROGRAM:
5089 *num_written = 1;
5090 if (params) {
5091 if (state_.current_program.get()) {
5092 GLuint client_id = 0;
5093 program_manager()->GetClientId(
5094 state_.current_program->service_id(), &client_id);
5095 *params = client_id;
5096 } else {
5097 *params = 0;
5100 return true;
5101 case GL_VERTEX_ARRAY_BINDING_OES:
5102 *num_written = 1;
5103 if (params) {
5104 if (state_.vertex_attrib_manager.get() !=
5105 state_.default_vertex_attrib_manager.get()) {
5106 GLuint client_id = 0;
5107 vertex_array_manager_->GetClientId(
5108 state_.vertex_attrib_manager->service_id(), &client_id);
5109 *params = client_id;
5110 } else {
5111 *params = 0;
5114 return true;
5115 case GL_TEXTURE_BINDING_2D:
5116 *num_written = 1;
5117 if (params) {
5118 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
5119 if (unit.bound_texture_2d.get()) {
5120 *params = unit.bound_texture_2d->client_id();
5121 } else {
5122 *params = 0;
5125 return true;
5126 case GL_TEXTURE_BINDING_CUBE_MAP:
5127 *num_written = 1;
5128 if (params) {
5129 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
5130 if (unit.bound_texture_cube_map.get()) {
5131 *params = unit.bound_texture_cube_map->client_id();
5132 } else {
5133 *params = 0;
5136 return true;
5137 case GL_TEXTURE_BINDING_EXTERNAL_OES:
5138 *num_written = 1;
5139 if (params) {
5140 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
5141 if (unit.bound_texture_external_oes.get()) {
5142 *params = unit.bound_texture_external_oes->client_id();
5143 } else {
5144 *params = 0;
5147 return true;
5148 case GL_TEXTURE_BINDING_RECTANGLE_ARB:
5149 *num_written = 1;
5150 if (params) {
5151 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
5152 if (unit.bound_texture_rectangle_arb.get()) {
5153 *params = unit.bound_texture_rectangle_arb->client_id();
5154 } else {
5155 *params = 0;
5158 return true;
5159 case GL_UNPACK_FLIP_Y_CHROMIUM:
5160 *num_written = 1;
5161 if (params) {
5162 params[0] = unpack_flip_y_;
5164 return true;
5165 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
5166 *num_written = 1;
5167 if (params) {
5168 params[0] = unpack_premultiply_alpha_;
5170 return true;
5171 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM:
5172 *num_written = 1;
5173 if (params) {
5174 params[0] = unpack_unpremultiply_alpha_;
5176 return true;
5177 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
5178 *num_written = 1;
5179 if (params) {
5180 params[0] = group_->bind_generates_resource() ? 1 : 0;
5182 return true;
5183 default:
5184 if (pname >= GL_DRAW_BUFFER0_ARB &&
5185 pname < GL_DRAW_BUFFER0_ARB + group_->max_draw_buffers()) {
5186 *num_written = 1;
5187 if (params) {
5188 Framebuffer* framebuffer =
5189 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
5190 if (framebuffer) {
5191 params[0] = framebuffer->GetDrawBuffer(pname);
5192 } else { // backbuffer
5193 if (pname == GL_DRAW_BUFFER0_ARB)
5194 params[0] = group_->draw_buffer();
5195 else
5196 params[0] = GL_NONE;
5199 return true;
5201 *num_written = util_.GLGetNumValuesReturned(pname);
5202 return false;
5206 bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
5207 GLenum pname, GLsizei* num_values) {
5208 if (state_.GetStateAsGLint(pname, NULL, num_values)) {
5209 return true;
5211 return GetHelper(pname, NULL, num_values);
5214 GLenum GLES2DecoderImpl::AdjustGetPname(GLenum pname) {
5215 if (GL_MAX_SAMPLES == pname &&
5216 features().use_img_for_multisampled_render_to_texture) {
5217 return GL_MAX_SAMPLES_IMG;
5219 return pname;
5222 void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
5223 DCHECK(params);
5224 GLsizei num_written = 0;
5225 if (GetNumValuesReturnedForGLGet(pname, &num_written)) {
5226 scoped_ptr<GLint[]> values(new GLint[num_written]);
5227 if (!state_.GetStateAsGLint(pname, values.get(), &num_written)) {
5228 GetHelper(pname, values.get(), &num_written);
5230 for (GLsizei ii = 0; ii < num_written; ++ii) {
5231 params[ii] = static_cast<GLboolean>(values[ii]);
5233 } else {
5234 pname = AdjustGetPname(pname);
5235 glGetBooleanv(pname, params);
5239 void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
5240 DCHECK(params);
5241 GLsizei num_written = 0;
5242 if (!state_.GetStateAsGLfloat(pname, params, &num_written)) {
5243 if (GetHelper(pname, NULL, &num_written)) {
5244 scoped_ptr<GLint[]> values(new GLint[num_written]);
5245 GetHelper(pname, values.get(), &num_written);
5246 for (GLsizei ii = 0; ii < num_written; ++ii) {
5247 params[ii] = static_cast<GLfloat>(values[ii]);
5249 } else {
5250 pname = AdjustGetPname(pname);
5251 glGetFloatv(pname, params);
5256 void GLES2DecoderImpl::DoGetInteger64v(GLenum pname, GLint64* params) {
5257 DCHECK(params);
5258 pname = AdjustGetPname(pname);
5259 glGetInteger64v(pname, params);
5262 void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
5263 DCHECK(params);
5264 GLsizei num_written;
5265 if (!state_.GetStateAsGLint(pname, params, &num_written) &&
5266 !GetHelper(pname, params, &num_written)) {
5267 pname = AdjustGetPname(pname);
5268 glGetIntegerv(pname, params);
5272 void GLES2DecoderImpl::DoGetProgramiv(
5273 GLuint program_id, GLenum pname, GLint* params) {
5274 Program* program = GetProgramInfoNotShader(program_id, "glGetProgramiv");
5275 if (!program) {
5276 return;
5278 program->GetProgramiv(pname, params);
5281 void GLES2DecoderImpl::DoGetBufferParameteriv(
5282 GLenum target, GLenum pname, GLint* params) {
5283 // Just delegate it. Some validation is actually done before this.
5284 buffer_manager()->ValidateAndDoGetBufferParameteriv(
5285 &state_, target, pname, params);
5288 void GLES2DecoderImpl::DoBindAttribLocation(
5289 GLuint program_id, GLuint index, const char* name) {
5290 if (!StringIsValidForGLES(name)) {
5291 LOCAL_SET_GL_ERROR(
5292 GL_INVALID_VALUE, "glBindAttribLocation", "Invalid character");
5293 return;
5295 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
5296 LOCAL_SET_GL_ERROR(
5297 GL_INVALID_OPERATION, "glBindAttribLocation", "reserved prefix");
5298 return;
5300 if (index >= group_->max_vertex_attribs()) {
5301 LOCAL_SET_GL_ERROR(
5302 GL_INVALID_VALUE, "glBindAttribLocation", "index out of range");
5303 return;
5305 Program* program = GetProgramInfoNotShader(
5306 program_id, "glBindAttribLocation");
5307 if (!program) {
5308 return;
5310 // At this point, the program's shaders may not be translated yet,
5311 // therefore, we may not find the hashed attribute name.
5312 // glBindAttribLocation call with original name is useless.
5313 // So instead, we should simply cache the binding, and then call
5314 // Program::ExecuteBindAttribLocationCalls() right before link.
5315 program->SetAttribLocationBinding(name, static_cast<GLint>(index));
5316 // TODO(zmo): Get rid of the following glBindAttribLocation call.
5317 glBindAttribLocation(program->service_id(), index, name);
5320 error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
5321 uint32 immediate_data_size,
5322 const void* cmd_data) {
5323 const gles2::cmds::BindAttribLocationBucket& c =
5324 *static_cast<const gles2::cmds::BindAttribLocationBucket*>(cmd_data);
5325 GLuint program = static_cast<GLuint>(c.program);
5326 GLuint index = static_cast<GLuint>(c.index);
5327 Bucket* bucket = GetBucket(c.name_bucket_id);
5328 if (!bucket || bucket->size() == 0) {
5329 return error::kInvalidArguments;
5331 std::string name_str;
5332 if (!bucket->GetAsString(&name_str)) {
5333 return error::kInvalidArguments;
5335 DoBindAttribLocation(program, index, name_str.c_str());
5336 return error::kNoError;
5339 void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM(
5340 GLuint program_id, GLint location, const char* name) {
5341 if (!StringIsValidForGLES(name)) {
5342 LOCAL_SET_GL_ERROR(
5343 GL_INVALID_VALUE,
5344 "glBindUniformLocationCHROMIUM", "Invalid character");
5345 return;
5347 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
5348 LOCAL_SET_GL_ERROR(
5349 GL_INVALID_OPERATION,
5350 "glBindUniformLocationCHROMIUM", "reserved prefix");
5351 return;
5353 if (location < 0 || static_cast<uint32>(location) >=
5354 (group_->max_fragment_uniform_vectors() +
5355 group_->max_vertex_uniform_vectors()) * 4) {
5356 LOCAL_SET_GL_ERROR(
5357 GL_INVALID_VALUE,
5358 "glBindUniformLocationCHROMIUM", "location out of range");
5359 return;
5361 Program* program = GetProgramInfoNotShader(
5362 program_id, "glBindUniformLocationCHROMIUM");
5363 if (!program) {
5364 return;
5366 if (!program->SetUniformLocationBinding(name, location)) {
5367 LOCAL_SET_GL_ERROR(
5368 GL_INVALID_VALUE,
5369 "glBindUniformLocationCHROMIUM", "location out of range");
5373 error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMBucket(
5374 uint32 immediate_data_size,
5375 const void* cmd_data) {
5376 const gles2::cmds::BindUniformLocationCHROMIUMBucket& c =
5377 *static_cast<const gles2::cmds::BindUniformLocationCHROMIUMBucket*>(
5378 cmd_data);
5379 GLuint program = static_cast<GLuint>(c.program);
5380 GLint location = static_cast<GLint>(c.location);
5381 Bucket* bucket = GetBucket(c.name_bucket_id);
5382 if (!bucket || bucket->size() == 0) {
5383 return error::kInvalidArguments;
5385 std::string name_str;
5386 if (!bucket->GetAsString(&name_str)) {
5387 return error::kInvalidArguments;
5389 DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
5390 return error::kNoError;
5393 error::Error GLES2DecoderImpl::HandleDeleteShader(uint32 immediate_data_size,
5394 const void* cmd_data) {
5395 const gles2::cmds::DeleteShader& c =
5396 *static_cast<const gles2::cmds::DeleteShader*>(cmd_data);
5397 GLuint client_id = c.shader;
5398 if (client_id) {
5399 Shader* shader = GetShader(client_id);
5400 if (shader) {
5401 if (!shader->IsDeleted()) {
5402 shader_manager()->Delete(shader);
5404 } else {
5405 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glDeleteShader", "unknown shader");
5408 return error::kNoError;
5411 error::Error GLES2DecoderImpl::HandleDeleteProgram(uint32 immediate_data_size,
5412 const void* cmd_data) {
5413 const gles2::cmds::DeleteProgram& c =
5414 *static_cast<const gles2::cmds::DeleteProgram*>(cmd_data);
5415 GLuint client_id = c.program;
5416 if (client_id) {
5417 Program* program = GetProgram(client_id);
5418 if (program) {
5419 if (!program->IsDeleted()) {
5420 program_manager()->MarkAsDeleted(shader_manager(), program);
5422 } else {
5423 LOCAL_SET_GL_ERROR(
5424 GL_INVALID_VALUE, "glDeleteProgram", "unknown program");
5427 return error::kNoError;
5430 error::Error GLES2DecoderImpl::DoClear(GLbitfield mask) {
5431 DCHECK(!ShouldDeferDraws());
5432 if (CheckBoundFramebuffersValid("glClear")) {
5433 ApplyDirtyState();
5434 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
5435 if (workarounds().gl_clear_broken) {
5436 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::ClearWorkaround",
5437 GetErrorState());
5438 if (!BoundFramebufferHasDepthAttachment())
5439 mask &= ~GL_DEPTH_BUFFER_BIT;
5440 if (!BoundFramebufferHasStencilAttachment())
5441 mask &= ~GL_STENCIL_BUFFER_BIT;
5442 clear_framebuffer_blit_->ClearFramebuffer(
5443 this, GetBoundReadFrameBufferSize(), mask, state_.color_clear_red,
5444 state_.color_clear_green, state_.color_clear_blue,
5445 state_.color_clear_alpha, state_.depth_clear, state_.stencil_clear);
5446 return error::kNoError;
5448 glClear(mask);
5450 return error::kNoError;
5453 void GLES2DecoderImpl::DoFramebufferRenderbuffer(
5454 GLenum target, GLenum attachment, GLenum renderbuffertarget,
5455 GLuint client_renderbuffer_id) {
5456 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5457 if (!framebuffer) {
5458 LOCAL_SET_GL_ERROR(
5459 GL_INVALID_OPERATION,
5460 "glFramebufferRenderbuffer", "no framebuffer bound");
5461 return;
5463 GLuint service_id = 0;
5464 Renderbuffer* renderbuffer = NULL;
5465 if (client_renderbuffer_id) {
5466 renderbuffer = GetRenderbuffer(client_renderbuffer_id);
5467 if (!renderbuffer) {
5468 LOCAL_SET_GL_ERROR(
5469 GL_INVALID_OPERATION,
5470 "glFramebufferRenderbuffer", "unknown renderbuffer");
5471 return;
5473 service_id = renderbuffer->service_id();
5475 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glFramebufferRenderbuffer");
5476 glFramebufferRenderbufferEXT(
5477 target, attachment, renderbuffertarget, service_id);
5478 GLenum error = LOCAL_PEEK_GL_ERROR("glFramebufferRenderbuffer");
5479 if (error == GL_NO_ERROR) {
5480 framebuffer->AttachRenderbuffer(attachment, renderbuffer);
5482 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
5483 framebuffer_state_.clear_state_dirty = true;
5485 OnFboChanged();
5488 void GLES2DecoderImpl::DoDisable(GLenum cap) {
5489 if (SetCapabilityState(cap, false)) {
5490 glDisable(cap);
5494 void GLES2DecoderImpl::DoEnable(GLenum cap) {
5495 if (SetCapabilityState(cap, true)) {
5496 glEnable(cap);
5500 void GLES2DecoderImpl::DoDepthRangef(GLclampf znear, GLclampf zfar) {
5501 state_.z_near = std::min(1.0f, std::max(0.0f, znear));
5502 state_.z_far = std::min(1.0f, std::max(0.0f, zfar));
5503 glDepthRange(znear, zfar);
5506 void GLES2DecoderImpl::DoSampleCoverage(GLclampf value, GLboolean invert) {
5507 state_.sample_coverage_value = std::min(1.0f, std::max(0.0f, value));
5508 state_.sample_coverage_invert = (invert != 0);
5509 glSampleCoverage(state_.sample_coverage_value, invert);
5512 // Assumes framebuffer is complete.
5513 void GLES2DecoderImpl::ClearUnclearedAttachments(
5514 GLenum target, Framebuffer* framebuffer) {
5515 if (target == GL_READ_FRAMEBUFFER_EXT) {
5516 // bind this to the DRAW point, clear then bind back to READ
5517 // TODO(gman): I don't think there is any guarantee that an FBO that
5518 // is complete on the READ attachment will be complete as a DRAW
5519 // attachment.
5520 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
5521 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, framebuffer->service_id());
5523 GLbitfield clear_bits = 0;
5524 if (framebuffer->HasUnclearedColorAttachments()) {
5525 glClearColor(
5526 0.0f, 0.0f, 0.0f,
5527 (GLES2Util::GetChannelsForFormat(
5528 framebuffer->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0.0f :
5529 1.0f);
5530 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
5531 clear_bits |= GL_COLOR_BUFFER_BIT;
5532 if (feature_info_->feature_flags().ext_draw_buffers)
5533 framebuffer->PrepareDrawBuffersForClear();
5536 if (framebuffer->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) ||
5537 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
5538 glClearStencil(0);
5539 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
5540 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
5541 clear_bits |= GL_STENCIL_BUFFER_BIT;
5544 if (framebuffer->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
5545 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
5546 glClearDepth(1.0f);
5547 state_.SetDeviceDepthMask(GL_TRUE);
5548 clear_bits |= GL_DEPTH_BUFFER_BIT;
5551 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
5552 glClear(clear_bits);
5554 if ((clear_bits & GL_COLOR_BUFFER_BIT) != 0 &&
5555 feature_info_->feature_flags().ext_draw_buffers)
5556 framebuffer->RestoreDrawBuffersAfterClear();
5558 framebuffer_manager()->MarkAttachmentsAsCleared(
5559 framebuffer, renderbuffer_manager(), texture_manager());
5561 RestoreClearState();
5563 if (target == GL_READ_FRAMEBUFFER_EXT) {
5564 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, framebuffer->service_id());
5565 Framebuffer* draw_framebuffer =
5566 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
5567 GLuint service_id = draw_framebuffer ? draw_framebuffer->service_id() :
5568 GetBackbufferServiceId();
5569 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, service_id);
5573 void GLES2DecoderImpl::RestoreClearState() {
5574 framebuffer_state_.clear_state_dirty = true;
5575 glClearColor(
5576 state_.color_clear_red, state_.color_clear_green, state_.color_clear_blue,
5577 state_.color_clear_alpha);
5578 glClearStencil(state_.stencil_clear);
5579 glClearDepth(state_.depth_clear);
5580 if (state_.enable_flags.scissor_test) {
5581 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
5585 GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
5586 Framebuffer* framebuffer =
5587 GetFramebufferInfoForTarget(target);
5588 if (!framebuffer) {
5589 return GL_FRAMEBUFFER_COMPLETE;
5591 GLenum completeness = framebuffer->IsPossiblyComplete();
5592 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
5593 return completeness;
5595 return framebuffer->GetStatus(texture_manager(), target);
5598 void GLES2DecoderImpl::DoFramebufferTexture2D(
5599 GLenum target, GLenum attachment, GLenum textarget,
5600 GLuint client_texture_id, GLint level) {
5601 DoFramebufferTexture2DCommon(
5602 "glFramebufferTexture2D", target, attachment,
5603 textarget, client_texture_id, level, 0);
5606 void GLES2DecoderImpl::DoFramebufferTexture2DMultisample(
5607 GLenum target, GLenum attachment, GLenum textarget,
5608 GLuint client_texture_id, GLint level, GLsizei samples) {
5609 DoFramebufferTexture2DCommon(
5610 "glFramebufferTexture2DMultisample", target, attachment,
5611 textarget, client_texture_id, level, samples);
5614 void GLES2DecoderImpl::DoFramebufferTexture2DCommon(
5615 const char* name, GLenum target, GLenum attachment, GLenum textarget,
5616 GLuint client_texture_id, GLint level, GLsizei samples) {
5617 if (samples > renderbuffer_manager()->max_samples()) {
5618 LOCAL_SET_GL_ERROR(
5619 GL_INVALID_VALUE,
5620 "glFramebufferTexture2DMultisample", "samples too large");
5621 return;
5623 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5624 if (!framebuffer) {
5625 LOCAL_SET_GL_ERROR(
5626 GL_INVALID_OPERATION,
5627 name, "no framebuffer bound.");
5628 return;
5630 GLuint service_id = 0;
5631 TextureRef* texture_ref = NULL;
5632 if (client_texture_id) {
5633 texture_ref = GetTexture(client_texture_id);
5634 if (!texture_ref) {
5635 LOCAL_SET_GL_ERROR(
5636 GL_INVALID_OPERATION,
5637 name, "unknown texture_ref");
5638 return;
5640 service_id = texture_ref->service_id();
5643 if (!texture_manager()->ValidForTarget(textarget, level, 0, 0, 1)) {
5644 LOCAL_SET_GL_ERROR(
5645 GL_INVALID_VALUE,
5646 name, "level out of range");
5647 return;
5650 if (texture_ref)
5651 DoWillUseTexImageIfNeeded(texture_ref->texture(), textarget);
5653 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(name);
5654 if (0 == samples) {
5655 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
5656 } else {
5657 if (features().use_img_for_multisampled_render_to_texture) {
5658 glFramebufferTexture2DMultisampleIMG(target, attachment, textarget,
5659 service_id, level, samples);
5660 } else {
5661 glFramebufferTexture2DMultisampleEXT(target, attachment, textarget,
5662 service_id, level, samples);
5665 GLenum error = LOCAL_PEEK_GL_ERROR(name);
5666 if (error == GL_NO_ERROR) {
5667 framebuffer->AttachTexture(attachment, texture_ref, textarget, level,
5668 samples);
5670 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
5671 framebuffer_state_.clear_state_dirty = true;
5674 if (texture_ref)
5675 DoDidUseTexImageIfNeeded(texture_ref->texture(), textarget);
5677 OnFboChanged();
5680 void GLES2DecoderImpl::DoFramebufferTextureLayer(
5681 GLenum target, GLenum attachment, GLuint client_texture_id,
5682 GLint level, GLint layer) {
5683 // TODO(zmo): Unsafe ES3 API, missing states update.
5684 GLuint service_id = 0;
5685 TextureRef* texture_ref = NULL;
5686 if (client_texture_id) {
5687 texture_ref = GetTexture(client_texture_id);
5688 if (!texture_ref) {
5689 LOCAL_SET_GL_ERROR(
5690 GL_INVALID_OPERATION,
5691 "glFramebufferTextureLayer", "unknown texture_ref");
5692 return;
5694 service_id = texture_ref->service_id();
5696 glFramebufferTextureLayer(target, attachment, service_id, level, layer);
5699 void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
5700 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
5701 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5702 if (!framebuffer) {
5703 LOCAL_SET_GL_ERROR(
5704 GL_INVALID_OPERATION,
5705 "glGetFramebufferAttachmentParameteriv", "no framebuffer bound");
5706 return;
5708 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
5709 const Framebuffer::Attachment* attachment_object =
5710 framebuffer->GetAttachment(attachment);
5711 *params = attachment_object ? attachment_object->object_name() : 0;
5712 } else {
5713 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT &&
5714 features().use_img_for_multisampled_render_to_texture) {
5715 pname = GL_TEXTURE_SAMPLES_IMG;
5717 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
5721 void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
5722 GLenum target, GLenum pname, GLint* params) {
5723 Renderbuffer* renderbuffer =
5724 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5725 if (!renderbuffer) {
5726 LOCAL_SET_GL_ERROR(
5727 GL_INVALID_OPERATION,
5728 "glGetRenderbufferParameteriv", "no renderbuffer bound");
5729 return;
5732 EnsureRenderbufferBound();
5733 switch (pname) {
5734 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5735 *params = renderbuffer->internal_format();
5736 break;
5737 case GL_RENDERBUFFER_WIDTH:
5738 *params = renderbuffer->width();
5739 break;
5740 case GL_RENDERBUFFER_HEIGHT:
5741 *params = renderbuffer->height();
5742 break;
5743 case GL_RENDERBUFFER_SAMPLES_EXT:
5744 if (features().use_img_for_multisampled_render_to_texture) {
5745 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_IMG,
5746 params);
5747 } else {
5748 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_EXT,
5749 params);
5751 default:
5752 glGetRenderbufferParameterivEXT(target, pname, params);
5753 break;
5757 void GLES2DecoderImpl::DoBlitFramebufferCHROMIUM(
5758 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
5759 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
5760 GLbitfield mask, GLenum filter) {
5761 DCHECK(!ShouldDeferReads() && !ShouldDeferDraws());
5763 if (!CheckBoundFramebuffersValid("glBlitFramebufferCHROMIUM")) {
5764 return;
5767 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
5768 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
5769 BlitFramebufferHelper(
5770 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5771 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST,
5772 state_.enable_flags.scissor_test);
5775 void GLES2DecoderImpl::EnsureRenderbufferBound() {
5776 if (!state_.bound_renderbuffer_valid) {
5777 state_.bound_renderbuffer_valid = true;
5778 glBindRenderbufferEXT(GL_RENDERBUFFER,
5779 state_.bound_renderbuffer.get()
5780 ? state_.bound_renderbuffer->service_id()
5781 : 0);
5785 void GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(
5786 const FeatureInfo* feature_info,
5787 GLenum target,
5788 GLsizei samples,
5789 GLenum internal_format,
5790 GLsizei width,
5791 GLsizei height) {
5792 // TODO(sievers): This could be resolved at the GL binding level, but the
5793 // binding process is currently a bit too 'brute force'.
5794 if (feature_info->gl_version_info().is_angle) {
5795 glRenderbufferStorageMultisampleANGLE(
5796 target, samples, internal_format, width, height);
5797 } else if (feature_info->feature_flags().use_core_framebuffer_multisample) {
5798 glRenderbufferStorageMultisample(
5799 target, samples, internal_format, width, height);
5800 } else {
5801 glRenderbufferStorageMultisampleEXT(
5802 target, samples, internal_format, width, height);
5806 void GLES2DecoderImpl::BlitFramebufferHelper(GLint srcX0,
5807 GLint srcY0,
5808 GLint srcX1,
5809 GLint srcY1,
5810 GLint dstX0,
5811 GLint dstY0,
5812 GLint dstX1,
5813 GLint dstY1,
5814 GLbitfield mask,
5815 GLenum filter) {
5816 // TODO(sievers): This could be resolved at the GL binding level, but the
5817 // binding process is currently a bit too 'brute force'.
5818 if (feature_info_->gl_version_info().is_angle) {
5819 glBlitFramebufferANGLE(
5820 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5821 } else if (feature_info_->feature_flags().use_core_framebuffer_multisample) {
5822 glBlitFramebuffer(
5823 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5824 } else {
5825 glBlitFramebufferEXT(
5826 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5830 bool GLES2DecoderImpl::ValidateRenderbufferStorageMultisample(
5831 GLsizei samples,
5832 GLenum internalformat,
5833 GLsizei width,
5834 GLsizei height) {
5835 if (samples > renderbuffer_manager()->max_samples()) {
5836 LOCAL_SET_GL_ERROR(
5837 GL_INVALID_VALUE,
5838 "glRenderbufferStorageMultisample", "samples too large");
5839 return false;
5842 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
5843 height > renderbuffer_manager()->max_renderbuffer_size()) {
5844 LOCAL_SET_GL_ERROR(
5845 GL_INVALID_VALUE,
5846 "glRenderbufferStorageMultisample", "dimensions too large");
5847 return false;
5850 uint32 estimated_size = 0;
5851 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
5852 width, height, samples, internalformat, &estimated_size)) {
5853 LOCAL_SET_GL_ERROR(
5854 GL_OUT_OF_MEMORY,
5855 "glRenderbufferStorageMultisample", "dimensions too large");
5856 return false;
5859 if (!EnsureGPUMemoryAvailable(estimated_size)) {
5860 LOCAL_SET_GL_ERROR(
5861 GL_OUT_OF_MEMORY,
5862 "glRenderbufferStorageMultisample", "out of memory");
5863 return false;
5866 return true;
5869 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleCHROMIUM(
5870 GLenum target, GLsizei samples, GLenum internalformat,
5871 GLsizei width, GLsizei height) {
5872 Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5873 if (!renderbuffer) {
5874 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
5875 "glRenderbufferStorageMultisampleCHROMIUM",
5876 "no renderbuffer bound");
5877 return;
5880 if (!ValidateRenderbufferStorageMultisample(
5881 samples, internalformat, width, height)) {
5882 return;
5885 EnsureRenderbufferBound();
5886 GLenum impl_format =
5887 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5888 internalformat);
5889 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(
5890 "glRenderbufferStorageMultisampleCHROMIUM");
5891 RenderbufferStorageMultisampleHelper(
5892 feature_info_.get(), target, samples, impl_format, width, height);
5893 GLenum error =
5894 LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleCHROMIUM");
5895 if (error == GL_NO_ERROR) {
5896 if (workarounds().validate_multisample_buffer_allocation) {
5897 if (!VerifyMultisampleRenderbufferIntegrity(
5898 renderbuffer->service_id(), impl_format)) {
5899 LOCAL_SET_GL_ERROR(
5900 GL_OUT_OF_MEMORY,
5901 "glRenderbufferStorageMultisampleCHROMIUM", "out of memory");
5902 return;
5906 // TODO(gman): If renderbuffers tracked which framebuffers they were
5907 // attached to we could just mark those framebuffers as not complete.
5908 framebuffer_manager()->IncFramebufferStateChangeCount();
5909 renderbuffer_manager()->SetInfo(
5910 renderbuffer, samples, internalformat, width, height);
5914 // This is the handler for multisampled_render_to_texture extensions.
5915 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleEXT(
5916 GLenum target, GLsizei samples, GLenum internalformat,
5917 GLsizei width, GLsizei height) {
5918 Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5919 if (!renderbuffer) {
5920 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
5921 "glRenderbufferStorageMultisampleEXT",
5922 "no renderbuffer bound");
5923 return;
5926 if (!ValidateRenderbufferStorageMultisample(
5927 samples, internalformat, width, height)) {
5928 return;
5931 EnsureRenderbufferBound();
5932 GLenum impl_format =
5933 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5934 internalformat);
5935 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorageMultisampleEXT");
5936 if (features().use_img_for_multisampled_render_to_texture) {
5937 glRenderbufferStorageMultisampleIMG(
5938 target, samples, impl_format, width, height);
5939 } else {
5940 glRenderbufferStorageMultisampleEXT(
5941 target, samples, impl_format, width, height);
5943 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleEXT");
5944 if (error == GL_NO_ERROR) {
5945 // TODO(gman): If renderbuffers tracked which framebuffers they were
5946 // attached to we could just mark those framebuffers as not complete.
5947 framebuffer_manager()->IncFramebufferStateChangeCount();
5948 renderbuffer_manager()->SetInfo(
5949 renderbuffer, samples, internalformat, width, height);
5953 // This function validates the allocation of a multisampled renderbuffer
5954 // by clearing it to a key color, blitting the contents to a texture, and
5955 // reading back the color to ensure it matches the key.
5956 bool GLES2DecoderImpl::VerifyMultisampleRenderbufferIntegrity(
5957 GLuint renderbuffer, GLenum format) {
5959 // Only validate color buffers.
5960 // These formats have been selected because they are very common or are known
5961 // to be used by the WebGL backbuffer. If problems are observed with other
5962 // color formats they can be added here.
5963 switch (format) {
5964 case GL_RGB:
5965 case GL_RGB8:
5966 case GL_RGBA:
5967 case GL_RGBA8:
5968 break;
5969 default:
5970 return true;
5973 GLint draw_framebuffer, read_framebuffer;
5975 // Cache framebuffer and texture bindings.
5976 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &draw_framebuffer);
5977 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &read_framebuffer);
5979 if (!validation_texture_) {
5980 GLint bound_texture;
5981 glGetIntegerv(GL_TEXTURE_BINDING_2D, &bound_texture);
5983 // Create additional resources needed for the verification.
5984 glGenTextures(1, &validation_texture_);
5985 glGenFramebuffersEXT(1, &validation_fbo_multisample_);
5986 glGenFramebuffersEXT(1, &validation_fbo_);
5988 // Texture only needs to be 1x1.
5989 glBindTexture(GL_TEXTURE_2D, validation_texture_);
5990 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB,
5991 GL_UNSIGNED_BYTE, NULL);
5993 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
5994 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5995 GL_TEXTURE_2D, validation_texture_, 0);
5997 glBindTexture(GL_TEXTURE_2D, bound_texture);
6000 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
6001 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
6002 GL_RENDERBUFFER, renderbuffer);
6004 // Cache current state and reset it to the values we require.
6005 GLboolean scissor_enabled = false;
6006 glGetBooleanv(GL_SCISSOR_TEST, &scissor_enabled);
6007 if (scissor_enabled)
6008 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
6010 GLboolean color_mask[4] = {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE};
6011 glGetBooleanv(GL_COLOR_WRITEMASK, color_mask);
6012 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
6014 GLfloat clear_color[4] = {0.0f, 0.0f, 0.0f, 0.0f};
6015 glGetFloatv(GL_COLOR_CLEAR_VALUE, clear_color);
6016 glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
6018 // Clear the buffer to the desired key color.
6019 glClear(GL_COLOR_BUFFER_BIT);
6021 // Blit from the multisample buffer to a standard texture.
6022 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, validation_fbo_multisample_);
6023 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, validation_fbo_);
6025 BlitFramebufferHelper(
6026 0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
6028 // Read a pixel from the buffer.
6029 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
6031 unsigned char pixel[3] = {0, 0, 0};
6032 glReadPixels(0, 0, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &pixel);
6034 // Detach the renderbuffer.
6035 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
6036 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
6037 GL_RENDERBUFFER, 0);
6039 // Restore cached state.
6040 if (scissor_enabled)
6041 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
6043 state_.SetDeviceColorMask(
6044 color_mask[0], color_mask[1], color_mask[2], color_mask[3]);
6045 glClearColor(clear_color[0], clear_color[1], clear_color[2], clear_color[3]);
6046 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, draw_framebuffer);
6047 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, read_framebuffer);
6049 // Return true if the pixel matched the desired key color.
6050 return (pixel[0] == 0xFF &&
6051 pixel[1] == 0x00 &&
6052 pixel[2] == 0xFF);
6055 void GLES2DecoderImpl::DoRenderbufferStorage(
6056 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
6057 Renderbuffer* renderbuffer =
6058 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
6059 if (!renderbuffer) {
6060 LOCAL_SET_GL_ERROR(
6061 GL_INVALID_OPERATION,
6062 "glRenderbufferStorage", "no renderbuffer bound");
6063 return;
6066 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
6067 height > renderbuffer_manager()->max_renderbuffer_size()) {
6068 LOCAL_SET_GL_ERROR(
6069 GL_INVALID_VALUE, "glRenderbufferStorage", "dimensions too large");
6070 return;
6073 uint32 estimated_size = 0;
6074 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
6075 width, height, 1, internalformat, &estimated_size)) {
6076 LOCAL_SET_GL_ERROR(
6077 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "dimensions too large");
6078 return;
6081 if (!EnsureGPUMemoryAvailable(estimated_size)) {
6082 LOCAL_SET_GL_ERROR(
6083 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "out of memory");
6084 return;
6087 EnsureRenderbufferBound();
6088 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorage");
6089 glRenderbufferStorageEXT(
6090 target,
6091 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
6092 internalformat),
6093 width,
6094 height);
6095 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorage");
6096 if (error == GL_NO_ERROR) {
6097 // TODO(gman): If tetxures tracked which framebuffers they were attached to
6098 // we could just mark those framebuffers as not complete.
6099 framebuffer_manager()->IncFramebufferStateChangeCount();
6100 renderbuffer_manager()->SetInfo(
6101 renderbuffer, 1, internalformat, width, height);
6105 void GLES2DecoderImpl::DoLinkProgram(GLuint program_id) {
6106 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
6107 Program* program = GetProgramInfoNotShader(
6108 program_id, "glLinkProgram");
6109 if (!program) {
6110 return;
6113 LogClientServiceForInfo(program, program_id, "glLinkProgram");
6114 if (program->Link(shader_manager(),
6115 workarounds().count_all_in_varyings_packing ?
6116 Program::kCountAll : Program::kCountOnlyStaticallyUsed,
6117 shader_cache_callback_)) {
6118 if (program == state_.current_program.get()) {
6119 if (workarounds().use_current_program_after_successful_link)
6120 glUseProgram(program->service_id());
6121 if (workarounds().clear_uniforms_before_first_program_use)
6122 program_manager()->ClearUniforms(program);
6126 // LinkProgram can be very slow. Exit command processing to allow for
6127 // context preemption and GPU watchdog checks.
6128 ExitCommandProcessingEarly();
6131 void GLES2DecoderImpl::DoSamplerParameterfv(
6132 GLuint sampler, GLenum pname, const GLfloat* params) {
6133 DCHECK(params);
6134 glSamplerParameterf(sampler, pname, params[0]);
6137 void GLES2DecoderImpl::DoSamplerParameteriv(
6138 GLuint sampler, GLenum pname, const GLint* params) {
6139 DCHECK(params);
6140 glSamplerParameteri(sampler, pname, params[0]);
6143 void GLES2DecoderImpl::DoTexParameterf(
6144 GLenum target, GLenum pname, GLfloat param) {
6145 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
6146 &state_, target);
6147 if (!texture) {
6148 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterf", "unknown texture");
6149 return;
6152 texture_manager()->SetParameterf(
6153 "glTexParameterf", GetErrorState(), texture, pname, param);
6156 void GLES2DecoderImpl::DoTexParameteri(
6157 GLenum target, GLenum pname, GLint param) {
6158 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
6159 &state_, target);
6160 if (!texture) {
6161 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameteri", "unknown texture");
6162 return;
6165 texture_manager()->SetParameteri(
6166 "glTexParameteri", GetErrorState(), texture, pname, param);
6169 void GLES2DecoderImpl::DoTexParameterfv(
6170 GLenum target, GLenum pname, const GLfloat* params) {
6171 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
6172 &state_, target);
6173 if (!texture) {
6174 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterfv", "unknown texture");
6175 return;
6178 texture_manager()->SetParameterf(
6179 "glTexParameterfv", GetErrorState(), texture, pname, *params);
6182 void GLES2DecoderImpl::DoTexParameteriv(
6183 GLenum target, GLenum pname, const GLint* params) {
6184 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
6185 &state_, target);
6186 if (!texture) {
6187 LOCAL_SET_GL_ERROR(
6188 GL_INVALID_VALUE, "glTexParameteriv", "unknown texture");
6189 return;
6192 texture_manager()->SetParameteri(
6193 "glTexParameteriv", GetErrorState(), texture, pname, *params);
6196 bool GLES2DecoderImpl::CheckCurrentValuebuffer(const char* function_name) {
6197 if (!state_.bound_valuebuffer.get()) {
6198 // There is no valuebuffer bound
6199 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
6200 "no valuebuffer in use");
6201 return false;
6203 return true;
6206 bool GLES2DecoderImpl::CheckCurrentValuebufferForSubscription(
6207 GLenum subscription,
6208 const char* function_name) {
6209 if (!CheckCurrentValuebuffer(function_name)) {
6210 return false;
6212 if (!state_.bound_valuebuffer.get()->IsSubscribed(subscription)) {
6213 // The valuebuffer is not subscribed to the target
6214 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
6215 "valuebuffer is not subscribed");
6216 return false;
6218 return true;
6221 bool GLES2DecoderImpl::CheckSubscriptionTarget(GLint location,
6222 GLenum subscription,
6223 const char* function_name) {
6224 if (!CheckCurrentProgramForUniform(location, function_name)) {
6225 return false;
6227 GLint real_location = -1;
6228 GLint array_index = -1;
6229 const Program::UniformInfo* info =
6230 state_.current_program->GetUniformInfoByFakeLocation(
6231 location, &real_location, &array_index);
6232 if (!info) {
6233 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, "unknown location");
6234 return false;
6236 if ((ValuebufferManager::ApiTypeForSubscriptionTarget(subscription) &
6237 info->accepts_api_type) == 0) {
6238 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
6239 "wrong type for subscription");
6240 return false;
6242 return true;
6245 bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
6246 if (!state_.current_program.get()) {
6247 // The program does not exist.
6248 LOCAL_SET_GL_ERROR(
6249 GL_INVALID_OPERATION, function_name, "no program in use");
6250 return false;
6252 if (!state_.current_program->InUse()) {
6253 LOCAL_SET_GL_ERROR(
6254 GL_INVALID_OPERATION, function_name, "program not linked");
6255 return false;
6257 return true;
6260 bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
6261 GLint location, const char* function_name) {
6262 if (!CheckCurrentProgram(function_name)) {
6263 return false;
6265 return location != -1;
6268 bool GLES2DecoderImpl::CheckDrawingFeedbackLoops() {
6269 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
6270 if (!framebuffer)
6271 return false;
6272 const Framebuffer::Attachment* attachment =
6273 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
6274 if (!attachment)
6275 return false;
6277 DCHECK(state_.current_program.get());
6278 const Program::SamplerIndices& sampler_indices =
6279 state_.current_program->sampler_indices();
6280 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6281 const Program::UniformInfo* uniform_info =
6282 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6283 DCHECK(uniform_info);
6284 if (uniform_info->type != GL_SAMPLER_2D)
6285 continue;
6286 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6287 GLuint texture_unit_index = uniform_info->texture_units[jj];
6288 if (texture_unit_index >= state_.texture_units.size())
6289 continue;
6290 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6291 TextureRef* texture_ref =
6292 texture_unit.GetInfoForSamplerType(GL_SAMPLER_2D).get();
6293 if (attachment->IsTexture(texture_ref))
6294 return true;
6297 return false;
6300 bool GLES2DecoderImpl::CheckUniformForApiType(
6301 const Program::UniformInfo* info,
6302 const char* function_name,
6303 Program::UniformApiType api_type) {
6304 DCHECK(info);
6305 if ((api_type & info->accepts_api_type) == 0) {
6306 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
6307 "wrong uniform function for type");
6308 return false;
6310 return true;
6313 bool GLES2DecoderImpl::PrepForSetUniformByLocation(
6314 GLint fake_location,
6315 const char* function_name,
6316 Program::UniformApiType api_type,
6317 GLint* real_location,
6318 GLenum* type,
6319 GLsizei* count) {
6320 DCHECK(type);
6321 DCHECK(count);
6322 DCHECK(real_location);
6324 if (!CheckCurrentProgramForUniform(fake_location, function_name)) {
6325 return false;
6327 GLint array_index = -1;
6328 const Program::UniformInfo* info =
6329 state_.current_program->GetUniformInfoByFakeLocation(
6330 fake_location, real_location, &array_index);
6331 if (!info) {
6332 LOCAL_SET_GL_ERROR(
6333 GL_INVALID_OPERATION, function_name, "unknown location");
6334 return false;
6336 if (!CheckUniformForApiType(info, function_name, api_type)) {
6337 return false;
6339 if (*count > 1 && !info->is_array) {
6340 LOCAL_SET_GL_ERROR(
6341 GL_INVALID_OPERATION, function_name, "count > 1 for non-array");
6342 return false;
6344 *count = std::min(info->size - array_index, *count);
6345 if (*count <= 0) {
6346 return false;
6348 *type = info->type;
6349 return true;
6352 void GLES2DecoderImpl::DoUniform1i(GLint fake_location, GLint v0) {
6353 GLenum type = 0;
6354 GLsizei count = 1;
6355 GLint real_location = -1;
6356 if (!PrepForSetUniformByLocation(fake_location,
6357 "glUniform1i",
6358 Program::kUniform1i,
6359 &real_location,
6360 &type,
6361 &count)) {
6362 return;
6364 if (!state_.current_program->SetSamplers(
6365 state_.texture_units.size(), fake_location, 1, &v0)) {
6366 LOCAL_SET_GL_ERROR(
6367 GL_INVALID_VALUE, "glUniform1i", "texture unit out of range");
6368 return;
6370 glUniform1i(real_location, v0);
6373 void GLES2DecoderImpl::DoUniform1iv(
6374 GLint fake_location, GLsizei count, const GLint *value) {
6375 GLenum type = 0;
6376 GLint real_location = -1;
6377 if (!PrepForSetUniformByLocation(fake_location,
6378 "glUniform1iv",
6379 Program::kUniform1i,
6380 &real_location,
6381 &type,
6382 &count)) {
6383 return;
6385 if (type == GL_SAMPLER_2D || type == GL_SAMPLER_2D_RECT_ARB ||
6386 type == GL_SAMPLER_CUBE || type == GL_SAMPLER_EXTERNAL_OES) {
6387 if (!state_.current_program->SetSamplers(
6388 state_.texture_units.size(), fake_location, count, value)) {
6389 LOCAL_SET_GL_ERROR(
6390 GL_INVALID_VALUE, "glUniform1iv", "texture unit out of range");
6391 return;
6394 glUniform1iv(real_location, count, value);
6397 void GLES2DecoderImpl::DoUniform1fv(
6398 GLint fake_location, GLsizei count, const GLfloat* value) {
6399 GLenum type = 0;
6400 GLint real_location = -1;
6401 if (!PrepForSetUniformByLocation(fake_location,
6402 "glUniform1fv",
6403 Program::kUniform1f,
6404 &real_location,
6405 &type,
6406 &count)) {
6407 return;
6409 if (type == GL_BOOL) {
6410 scoped_ptr<GLint[]> temp(new GLint[count]);
6411 for (GLsizei ii = 0; ii < count; ++ii) {
6412 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6414 DoUniform1iv(real_location, count, temp.get());
6415 } else {
6416 glUniform1fv(real_location, count, value);
6420 void GLES2DecoderImpl::DoUniform2fv(
6421 GLint fake_location, GLsizei count, const GLfloat* value) {
6422 GLenum type = 0;
6423 GLint real_location = -1;
6424 if (!PrepForSetUniformByLocation(fake_location,
6425 "glUniform2fv",
6426 Program::kUniform2f,
6427 &real_location,
6428 &type,
6429 &count)) {
6430 return;
6432 if (type == GL_BOOL_VEC2) {
6433 GLsizei num_values = count * 2;
6434 scoped_ptr<GLint[]> temp(new GLint[num_values]);
6435 for (GLsizei ii = 0; ii < num_values; ++ii) {
6436 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6438 glUniform2iv(real_location, count, temp.get());
6439 } else {
6440 glUniform2fv(real_location, count, value);
6444 void GLES2DecoderImpl::DoUniform3fv(
6445 GLint fake_location, GLsizei count, const GLfloat* value) {
6446 GLenum type = 0;
6447 GLint real_location = -1;
6448 if (!PrepForSetUniformByLocation(fake_location,
6449 "glUniform3fv",
6450 Program::kUniform3f,
6451 &real_location,
6452 &type,
6453 &count)) {
6454 return;
6456 if (type == GL_BOOL_VEC3) {
6457 GLsizei num_values = count * 3;
6458 scoped_ptr<GLint[]> temp(new GLint[num_values]);
6459 for (GLsizei ii = 0; ii < num_values; ++ii) {
6460 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6462 glUniform3iv(real_location, count, temp.get());
6463 } else {
6464 glUniform3fv(real_location, count, value);
6468 void GLES2DecoderImpl::DoUniform4fv(
6469 GLint fake_location, GLsizei count, const GLfloat* value) {
6470 GLenum type = 0;
6471 GLint real_location = -1;
6472 if (!PrepForSetUniformByLocation(fake_location,
6473 "glUniform4fv",
6474 Program::kUniform4f,
6475 &real_location,
6476 &type,
6477 &count)) {
6478 return;
6480 if (type == GL_BOOL_VEC4) {
6481 GLsizei num_values = count * 4;
6482 scoped_ptr<GLint[]> temp(new GLint[num_values]);
6483 for (GLsizei ii = 0; ii < num_values; ++ii) {
6484 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6486 glUniform4iv(real_location, count, temp.get());
6487 } else {
6488 glUniform4fv(real_location, count, value);
6492 void GLES2DecoderImpl::DoUniform2iv(
6493 GLint fake_location, GLsizei count, const GLint* value) {
6494 GLenum type = 0;
6495 GLint real_location = -1;
6496 if (!PrepForSetUniformByLocation(fake_location,
6497 "glUniform2iv",
6498 Program::kUniform2i,
6499 &real_location,
6500 &type,
6501 &count)) {
6502 return;
6504 glUniform2iv(real_location, count, value);
6507 void GLES2DecoderImpl::DoUniform3iv(
6508 GLint fake_location, GLsizei count, const GLint* value) {
6509 GLenum type = 0;
6510 GLint real_location = -1;
6511 if (!PrepForSetUniformByLocation(fake_location,
6512 "glUniform3iv",
6513 Program::kUniform3i,
6514 &real_location,
6515 &type,
6516 &count)) {
6517 return;
6519 glUniform3iv(real_location, count, value);
6522 void GLES2DecoderImpl::DoUniform4iv(
6523 GLint fake_location, GLsizei count, const GLint* value) {
6524 GLenum type = 0;
6525 GLint real_location = -1;
6526 if (!PrepForSetUniformByLocation(fake_location,
6527 "glUniform4iv",
6528 Program::kUniform4i,
6529 &real_location,
6530 &type,
6531 &count)) {
6532 return;
6534 glUniform4iv(real_location, count, value);
6537 void GLES2DecoderImpl::DoUniformMatrix2fv(
6538 GLint fake_location, GLsizei count, GLboolean transpose,
6539 const GLfloat* value) {
6540 GLenum type = 0;
6541 GLint real_location = -1;
6542 if (!PrepForSetUniformByLocation(fake_location,
6543 "glUniformMatrix2fv",
6544 Program::kUniformMatrix2f,
6545 &real_location,
6546 &type,
6547 &count)) {
6548 return;
6550 glUniformMatrix2fv(real_location, count, transpose, value);
6553 void GLES2DecoderImpl::DoUniformMatrix3fv(
6554 GLint fake_location, GLsizei count, GLboolean transpose,
6555 const GLfloat* value) {
6556 GLenum type = 0;
6557 GLint real_location = -1;
6558 if (!PrepForSetUniformByLocation(fake_location,
6559 "glUniformMatrix3fv",
6560 Program::kUniformMatrix3f,
6561 &real_location,
6562 &type,
6563 &count)) {
6564 return;
6566 glUniformMatrix3fv(real_location, count, transpose, value);
6569 void GLES2DecoderImpl::DoUniformMatrix4fv(
6570 GLint fake_location, GLsizei count, GLboolean transpose,
6571 const GLfloat* value) {
6572 GLenum type = 0;
6573 GLint real_location = -1;
6574 if (!PrepForSetUniformByLocation(fake_location,
6575 "glUniformMatrix4fv",
6576 Program::kUniformMatrix4f,
6577 &real_location,
6578 &type,
6579 &count)) {
6580 return;
6582 glUniformMatrix4fv(real_location, count, transpose, value);
6585 void GLES2DecoderImpl::DoUseProgram(GLuint program_id) {
6586 GLuint service_id = 0;
6587 Program* program = NULL;
6588 if (program_id) {
6589 program = GetProgramInfoNotShader(program_id, "glUseProgram");
6590 if (!program) {
6591 return;
6593 if (!program->IsValid()) {
6594 // Program was not linked successfully. (ie, glLinkProgram)
6595 LOCAL_SET_GL_ERROR(
6596 GL_INVALID_OPERATION, "glUseProgram", "program not linked");
6597 return;
6599 service_id = program->service_id();
6601 if (state_.current_program.get()) {
6602 program_manager()->UnuseProgram(shader_manager(),
6603 state_.current_program.get());
6605 state_.current_program = program;
6606 LogClientServiceMapping("glUseProgram", program_id, service_id);
6607 glUseProgram(service_id);
6608 if (state_.current_program.get()) {
6609 program_manager()->UseProgram(state_.current_program.get());
6610 if (workarounds().clear_uniforms_before_first_program_use)
6611 program_manager()->ClearUniforms(program);
6615 void GLES2DecoderImpl::RenderWarning(
6616 const char* filename, int line, const std::string& msg) {
6617 logger_.LogMessage(filename, line, std::string("RENDER WARNING: ") + msg);
6620 void GLES2DecoderImpl::PerformanceWarning(
6621 const char* filename, int line, const std::string& msg) {
6622 logger_.LogMessage(filename, line,
6623 std::string("PERFORMANCE WARNING: ") + msg);
6626 void GLES2DecoderImpl::DoWillUseTexImageIfNeeded(
6627 Texture* texture, GLenum textarget) {
6628 // Image is already in use if texture is attached to a framebuffer.
6629 if (texture && !texture->IsAttachedToFramebuffer()) {
6630 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6631 if (image) {
6632 ScopedGLErrorSuppressor suppressor(
6633 "GLES2DecoderImpl::DoWillUseTexImageIfNeeded",
6634 GetErrorState());
6635 glBindTexture(textarget, texture->service_id());
6636 image->WillUseTexImage();
6637 RestoreCurrentTextureBindings(&state_, textarget);
6642 void GLES2DecoderImpl::DoDidUseTexImageIfNeeded(
6643 Texture* texture, GLenum textarget) {
6644 // Image is still in use if texture is attached to a framebuffer.
6645 if (texture && !texture->IsAttachedToFramebuffer()) {
6646 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6647 if (image) {
6648 ScopedGLErrorSuppressor suppressor(
6649 "GLES2DecoderImpl::DoDidUseTexImageIfNeeded",
6650 GetErrorState());
6651 glBindTexture(textarget, texture->service_id());
6652 image->DidUseTexImage();
6653 RestoreCurrentTextureBindings(&state_, textarget);
6658 bool GLES2DecoderImpl::PrepareTexturesForRender() {
6659 DCHECK(state_.current_program.get());
6660 if (!texture_manager()->HaveUnrenderableTextures() &&
6661 !texture_manager()->HaveImages()) {
6662 return true;
6665 bool textures_set = false;
6666 const Program::SamplerIndices& sampler_indices =
6667 state_.current_program->sampler_indices();
6668 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6669 const Program::UniformInfo* uniform_info =
6670 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6671 DCHECK(uniform_info);
6672 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6673 GLuint texture_unit_index = uniform_info->texture_units[jj];
6674 if (texture_unit_index < state_.texture_units.size()) {
6675 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6676 TextureRef* texture_ref =
6677 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6678 GLenum textarget = GetBindTargetForSamplerType(uniform_info->type);
6679 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
6680 textures_set = true;
6681 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6682 glBindTexture(
6683 textarget,
6684 texture_manager()->black_texture_id(uniform_info->type));
6685 if (!texture_ref) {
6686 LOCAL_RENDER_WARNING(
6687 std::string("there is no texture bound to the unit ") +
6688 base::IntToString(texture_unit_index));
6689 } else {
6690 LOCAL_RENDER_WARNING(
6691 std::string("texture bound to texture unit ") +
6692 base::IntToString(texture_unit_index) +
6693 " is not renderable. It maybe non-power-of-2 and have"
6694 " incompatible texture filtering.");
6696 continue;
6699 if (textarget != GL_TEXTURE_CUBE_MAP) {
6700 Texture* texture = texture_ref->texture();
6701 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6702 if (image && !texture->IsAttachedToFramebuffer()) {
6703 ScopedGLErrorSuppressor suppressor(
6704 "GLES2DecoderImpl::PrepareTexturesForRender", GetErrorState());
6705 textures_set = true;
6706 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6707 image->WillUseTexImage();
6708 continue;
6712 // else: should this be an error?
6715 return !textures_set;
6718 void GLES2DecoderImpl::RestoreStateForTextures() {
6719 DCHECK(state_.current_program.get());
6720 const Program::SamplerIndices& sampler_indices =
6721 state_.current_program->sampler_indices();
6722 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6723 const Program::UniformInfo* uniform_info =
6724 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6725 DCHECK(uniform_info);
6726 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6727 GLuint texture_unit_index = uniform_info->texture_units[jj];
6728 if (texture_unit_index < state_.texture_units.size()) {
6729 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6730 TextureRef* texture_ref =
6731 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6732 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
6733 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6734 // Get the texture_ref info that was previously bound here.
6735 texture_ref = texture_unit.bind_target == GL_TEXTURE_2D
6736 ? texture_unit.bound_texture_2d.get()
6737 : texture_unit.bound_texture_cube_map.get();
6738 glBindTexture(texture_unit.bind_target,
6739 texture_ref ? texture_ref->service_id() : 0);
6740 continue;
6743 if (texture_unit.bind_target != GL_TEXTURE_CUBE_MAP) {
6744 Texture* texture = texture_ref->texture();
6745 gfx::GLImage* image =
6746 texture->GetLevelImage(texture_unit.bind_target, 0);
6747 if (image && !texture->IsAttachedToFramebuffer()) {
6748 ScopedGLErrorSuppressor suppressor(
6749 "GLES2DecoderImpl::RestoreStateForTextures", GetErrorState());
6750 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6751 image->DidUseTexImage();
6752 continue;
6758 // Set the active texture back to whatever the user had it as.
6759 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
6762 bool GLES2DecoderImpl::ClearUnclearedTextures() {
6763 // Only check if there are some uncleared textures.
6764 if (!texture_manager()->HaveUnsafeTextures()) {
6765 return true;
6768 // 1: Check all textures we are about to render with.
6769 if (state_.current_program.get()) {
6770 const Program::SamplerIndices& sampler_indices =
6771 state_.current_program->sampler_indices();
6772 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6773 const Program::UniformInfo* uniform_info =
6774 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6775 DCHECK(uniform_info);
6776 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6777 GLuint texture_unit_index = uniform_info->texture_units[jj];
6778 if (texture_unit_index < state_.texture_units.size()) {
6779 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6780 TextureRef* texture_ref =
6781 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6782 if (texture_ref && !texture_ref->texture()->SafeToRenderFrom()) {
6783 if (!texture_manager()->ClearRenderableLevels(this, texture_ref)) {
6784 return false;
6791 return true;
6794 bool GLES2DecoderImpl::IsDrawValid(
6795 const char* function_name, GLuint max_vertex_accessed, bool instanced,
6796 GLsizei primcount) {
6797 DCHECK(instanced || primcount == 1);
6799 // NOTE: We specifically do not check current_program->IsValid() because
6800 // it could never be invalid since glUseProgram would have failed. While
6801 // glLinkProgram could later mark the program as invalid the previous
6802 // valid program will still function if it is still the current program.
6803 if (!state_.current_program.get()) {
6804 // The program does not exist.
6805 // But GL says no ERROR.
6806 LOCAL_RENDER_WARNING("Drawing with no current shader program.");
6807 return false;
6810 if (CheckDrawingFeedbackLoops()) {
6811 LOCAL_SET_GL_ERROR(
6812 GL_INVALID_OPERATION, function_name,
6813 "Source and destination textures of the draw are the same.");
6814 return false;
6817 return state_.vertex_attrib_manager
6818 ->ValidateBindings(function_name,
6819 this,
6820 feature_info_.get(),
6821 state_.current_program.get(),
6822 max_vertex_accessed,
6823 instanced,
6824 primcount);
6827 bool GLES2DecoderImpl::SimulateAttrib0(
6828 const char* function_name, GLuint max_vertex_accessed, bool* simulated) {
6829 DCHECK(simulated);
6830 *simulated = false;
6832 if (feature_info_->gl_version_info().BehavesLikeGLES())
6833 return true;
6835 const VertexAttrib* attrib =
6836 state_.vertex_attrib_manager->GetVertexAttrib(0);
6837 // If it's enabled or it's not used then we don't need to do anything.
6838 bool attrib_0_used =
6839 state_.current_program->GetAttribInfoByLocation(0) != NULL;
6840 if (attrib->enabled() && attrib_0_used) {
6841 return true;
6844 // Make a buffer with a single repeated vec4 value enough to
6845 // simulate the constant value that is supposed to be here.
6846 // This is required to emulate GLES2 on GL.
6847 GLuint num_vertices = max_vertex_accessed + 1;
6848 uint32 size_needed = 0;
6850 if (num_vertices == 0 ||
6851 !SafeMultiplyUint32(num_vertices, sizeof(Vec4), &size_needed) ||
6852 size_needed > 0x7FFFFFFFU) {
6853 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6854 return false;
6857 LOCAL_PERFORMANCE_WARNING(
6858 "Attribute 0 is disabled. This has signficant performance penalty");
6860 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
6861 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
6863 bool new_buffer = static_cast<GLsizei>(size_needed) > attrib_0_size_;
6864 if (new_buffer) {
6865 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
6866 GLenum error = glGetError();
6867 if (error != GL_NO_ERROR) {
6868 LOCAL_SET_GL_ERROR(
6869 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6870 return false;
6874 const Vec4& value = state_.attrib_values[0];
6875 if (new_buffer ||
6876 (attrib_0_used &&
6877 (!attrib_0_buffer_matches_value_ ||
6878 (value.v[0] != attrib_0_value_.v[0] ||
6879 value.v[1] != attrib_0_value_.v[1] ||
6880 value.v[2] != attrib_0_value_.v[2] ||
6881 value.v[3] != attrib_0_value_.v[3])))) {
6882 std::vector<Vec4> temp(num_vertices, value);
6883 glBufferSubData(GL_ARRAY_BUFFER, 0, size_needed, &temp[0].v[0]);
6884 attrib_0_buffer_matches_value_ = true;
6885 attrib_0_value_ = value;
6886 attrib_0_size_ = size_needed;
6889 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
6891 if (attrib->divisor())
6892 glVertexAttribDivisorANGLE(0, 0);
6894 *simulated = true;
6895 return true;
6898 void GLES2DecoderImpl::RestoreStateForAttrib(
6899 GLuint attrib_index, bool restore_array_binding) {
6900 const VertexAttrib* attrib =
6901 state_.vertex_attrib_manager->GetVertexAttrib(attrib_index);
6902 if (restore_array_binding) {
6903 const void* ptr = reinterpret_cast<const void*>(attrib->offset());
6904 Buffer* buffer = attrib->buffer();
6905 glBindBuffer(GL_ARRAY_BUFFER, buffer ? buffer->service_id() : 0);
6906 glVertexAttribPointer(
6907 attrib_index, attrib->size(), attrib->type(), attrib->normalized(),
6908 attrib->gl_stride(), ptr);
6910 if (attrib->divisor())
6911 glVertexAttribDivisorANGLE(attrib_index, attrib->divisor());
6912 glBindBuffer(
6913 GL_ARRAY_BUFFER, state_.bound_array_buffer.get() ?
6914 state_.bound_array_buffer->service_id() : 0);
6916 // Never touch vertex attribute 0's state (in particular, never
6917 // disable it) when running on desktop GL because it will never be
6918 // re-enabled.
6919 if (attrib_index != 0 ||
6920 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
6921 if (attrib->enabled()) {
6922 glEnableVertexAttribArray(attrib_index);
6923 } else {
6924 glDisableVertexAttribArray(attrib_index);
6929 bool GLES2DecoderImpl::SimulateFixedAttribs(
6930 const char* function_name,
6931 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount) {
6932 DCHECK(simulated);
6933 *simulated = false;
6934 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
6935 return true;
6937 if (!state_.vertex_attrib_manager->HaveFixedAttribs()) {
6938 return true;
6941 LOCAL_PERFORMANCE_WARNING(
6942 "GL_FIXED attributes have a signficant performance penalty");
6944 // NOTE: we could be smart and try to check if a buffer is used
6945 // twice in 2 different attribs, find the overlapping parts and therefore
6946 // duplicate the minimum amount of data but this whole code path is not meant
6947 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
6948 // tests so we just add to the buffer attrib used.
6950 GLuint elements_needed = 0;
6951 const VertexAttribManager::VertexAttribList& enabled_attribs =
6952 state_.vertex_attrib_manager->GetEnabledVertexAttribs();
6953 for (VertexAttribManager::VertexAttribList::const_iterator it =
6954 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
6955 const VertexAttrib* attrib = *it;
6956 const Program::VertexAttrib* attrib_info =
6957 state_.current_program->GetAttribInfoByLocation(attrib->index());
6958 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
6959 max_vertex_accessed);
6960 GLuint num_vertices = max_accessed + 1;
6961 if (num_vertices == 0) {
6962 LOCAL_SET_GL_ERROR(
6963 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6964 return false;
6966 if (attrib_info &&
6967 attrib->CanAccess(max_accessed) &&
6968 attrib->type() == GL_FIXED) {
6969 uint32 elements_used = 0;
6970 if (!SafeMultiplyUint32(num_vertices, attrib->size(), &elements_used) ||
6971 !SafeAddUint32(elements_needed, elements_used, &elements_needed)) {
6972 LOCAL_SET_GL_ERROR(
6973 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
6974 return false;
6979 const uint32 kSizeOfFloat = sizeof(float); // NOLINT
6980 uint32 size_needed = 0;
6981 if (!SafeMultiplyUint32(elements_needed, kSizeOfFloat, &size_needed) ||
6982 size_needed > 0x7FFFFFFFU) {
6983 LOCAL_SET_GL_ERROR(
6984 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
6985 return false;
6988 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
6990 glBindBuffer(GL_ARRAY_BUFFER, fixed_attrib_buffer_id_);
6991 if (static_cast<GLsizei>(size_needed) > fixed_attrib_buffer_size_) {
6992 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
6993 GLenum error = glGetError();
6994 if (error != GL_NO_ERROR) {
6995 LOCAL_SET_GL_ERROR(
6996 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
6997 return false;
7001 // Copy the elements and convert to float
7002 GLintptr offset = 0;
7003 for (VertexAttribManager::VertexAttribList::const_iterator it =
7004 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
7005 const VertexAttrib* attrib = *it;
7006 const Program::VertexAttrib* attrib_info =
7007 state_.current_program->GetAttribInfoByLocation(attrib->index());
7008 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
7009 max_vertex_accessed);
7010 GLuint num_vertices = max_accessed + 1;
7011 if (num_vertices == 0) {
7012 LOCAL_SET_GL_ERROR(
7013 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
7014 return false;
7016 if (attrib_info &&
7017 attrib->CanAccess(max_accessed) &&
7018 attrib->type() == GL_FIXED) {
7019 int num_elements = attrib->size() * num_vertices;
7020 const int src_size = num_elements * sizeof(int32);
7021 const int dst_size = num_elements * sizeof(float);
7022 scoped_ptr<float[]> data(new float[num_elements]);
7023 const int32* src = reinterpret_cast<const int32 *>(
7024 attrib->buffer()->GetRange(attrib->offset(), src_size));
7025 const int32* end = src + num_elements;
7026 float* dst = data.get();
7027 while (src != end) {
7028 *dst++ = static_cast<float>(*src++) / 65536.0f;
7030 glBufferSubData(GL_ARRAY_BUFFER, offset, dst_size, data.get());
7031 glVertexAttribPointer(
7032 attrib->index(), attrib->size(), GL_FLOAT, false, 0,
7033 reinterpret_cast<GLvoid*>(offset));
7034 offset += dst_size;
7037 *simulated = true;
7038 return true;
7041 void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
7042 // There's no need to call glVertexAttribPointer because we shadow all the
7043 // settings and passing GL_FIXED to it will not work.
7044 glBindBuffer(
7045 GL_ARRAY_BUFFER,
7046 state_.bound_array_buffer.get() ? state_.bound_array_buffer->service_id()
7047 : 0);
7050 error::Error GLES2DecoderImpl::DoDrawArrays(
7051 const char* function_name,
7052 bool instanced,
7053 GLenum mode,
7054 GLint first,
7055 GLsizei count,
7056 GLsizei primcount) {
7057 error::Error error = WillAccessBoundFramebufferForDraw();
7058 if (error != error::kNoError)
7059 return error;
7060 if (!validators_->draw_mode.IsValid(mode)) {
7061 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
7062 return error::kNoError;
7064 if (count < 0) {
7065 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
7066 return error::kNoError;
7068 if (primcount < 0) {
7069 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
7070 return error::kNoError;
7072 if (!CheckBoundFramebuffersValid(function_name)) {
7073 return error::kNoError;
7075 // We have to check this here because the prototype for glDrawArrays
7076 // is GLint not GLsizei.
7077 if (first < 0) {
7078 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "first < 0");
7079 return error::kNoError;
7082 if (count == 0 || primcount == 0) {
7083 LOCAL_RENDER_WARNING("Render count or primcount is 0.");
7084 return error::kNoError;
7087 GLuint max_vertex_accessed = first + count - 1;
7088 if (IsDrawValid(function_name, max_vertex_accessed, instanced, primcount)) {
7089 if (!ClearUnclearedTextures()) {
7090 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
7091 return error::kNoError;
7093 bool simulated_attrib_0 = false;
7094 if (!SimulateAttrib0(
7095 function_name, max_vertex_accessed, &simulated_attrib_0)) {
7096 return error::kNoError;
7098 bool simulated_fixed_attribs = false;
7099 if (SimulateFixedAttribs(
7100 function_name, max_vertex_accessed, &simulated_fixed_attribs,
7101 primcount)) {
7102 bool textures_set = !PrepareTexturesForRender();
7103 ApplyDirtyState();
7104 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
7105 if (!instanced) {
7106 glDrawArrays(mode, first, count);
7107 } else {
7108 glDrawArraysInstancedANGLE(mode, first, count, primcount);
7110 if (textures_set) {
7111 RestoreStateForTextures();
7113 if (simulated_fixed_attribs) {
7114 RestoreStateForSimulatedFixedAttribs();
7117 if (simulated_attrib_0) {
7118 // We don't have to restore attrib 0 generic data at the end of this
7119 // function even if it is simulated. This is because we will simulate
7120 // it in each draw call, and attrib 0 generic data queries use cached
7121 // values instead of passing down to the underlying driver.
7122 RestoreStateForAttrib(0, false);
7125 return error::kNoError;
7128 error::Error GLES2DecoderImpl::HandleDrawArrays(uint32 immediate_data_size,
7129 const void* cmd_data) {
7130 // TODO(zmo): crbug.com/481184
7131 // On Desktop GL with versions lower than 4.3, we need to emulate
7132 // GL_PRIMITIVE_RESTART_FIXED_INDEX using glPrimitiveRestartIndex().
7133 const cmds::DrawArrays& c = *static_cast<const cmds::DrawArrays*>(cmd_data);
7134 return DoDrawArrays("glDrawArrays",
7135 false,
7136 static_cast<GLenum>(c.mode),
7137 static_cast<GLint>(c.first),
7138 static_cast<GLsizei>(c.count),
7142 error::Error GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
7143 uint32 immediate_data_size,
7144 const void* cmd_data) {
7145 const gles2::cmds::DrawArraysInstancedANGLE& c =
7146 *static_cast<const gles2::cmds::DrawArraysInstancedANGLE*>(cmd_data);
7147 if (!features().angle_instanced_arrays) {
7148 LOCAL_SET_GL_ERROR(
7149 GL_INVALID_OPERATION,
7150 "glDrawArraysInstancedANGLE", "function not available");
7151 return error::kNoError;
7153 return DoDrawArrays("glDrawArraysIntancedANGLE",
7154 true,
7155 static_cast<GLenum>(c.mode),
7156 static_cast<GLint>(c.first),
7157 static_cast<GLsizei>(c.count),
7158 static_cast<GLsizei>(c.primcount));
7161 error::Error GLES2DecoderImpl::DoDrawElements(
7162 const char* function_name,
7163 bool instanced,
7164 GLenum mode,
7165 GLsizei count,
7166 GLenum type,
7167 int32 offset,
7168 GLsizei primcount) {
7169 error::Error error = WillAccessBoundFramebufferForDraw();
7170 if (error != error::kNoError)
7171 return error;
7172 if (!state_.vertex_attrib_manager->element_array_buffer()) {
7173 LOCAL_SET_GL_ERROR(
7174 GL_INVALID_OPERATION, function_name, "No element array buffer bound");
7175 return error::kNoError;
7178 if (count < 0) {
7179 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
7180 return error::kNoError;
7182 if (offset < 0) {
7183 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "offset < 0");
7184 return error::kNoError;
7186 if (!validators_->draw_mode.IsValid(mode)) {
7187 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
7188 return error::kNoError;
7190 if (!validators_->index_type.IsValid(type)) {
7191 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, type, "type");
7192 return error::kNoError;
7194 if (primcount < 0) {
7195 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
7196 return error::kNoError;
7199 if (!CheckBoundFramebuffersValid(function_name)) {
7200 return error::kNoError;
7203 if (count == 0 || primcount == 0) {
7204 return error::kNoError;
7207 GLuint max_vertex_accessed;
7208 Buffer* element_array_buffer =
7209 state_.vertex_attrib_manager->element_array_buffer();
7211 if (!element_array_buffer->GetMaxValueForRange(
7212 offset, count, type, &max_vertex_accessed)) {
7213 LOCAL_SET_GL_ERROR(
7214 GL_INVALID_OPERATION, function_name, "range out of bounds for buffer");
7215 return error::kNoError;
7218 if (IsDrawValid(function_name, max_vertex_accessed, instanced, primcount)) {
7219 if (!ClearUnclearedTextures()) {
7220 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
7221 return error::kNoError;
7223 bool simulated_attrib_0 = false;
7224 if (!SimulateAttrib0(
7225 function_name, max_vertex_accessed, &simulated_attrib_0)) {
7226 return error::kNoError;
7228 bool simulated_fixed_attribs = false;
7229 if (SimulateFixedAttribs(
7230 function_name, max_vertex_accessed, &simulated_fixed_attribs,
7231 primcount)) {
7232 bool textures_set = !PrepareTexturesForRender();
7233 ApplyDirtyState();
7234 // TODO(gman): Refactor to hide these details in BufferManager or
7235 // VertexAttribManager.
7236 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
7237 bool used_client_side_array = false;
7238 if (element_array_buffer->IsClientSideArray()) {
7239 used_client_side_array = true;
7240 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
7241 indices = element_array_buffer->GetRange(offset, 0);
7244 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
7245 if (!instanced) {
7246 glDrawElements(mode, count, type, indices);
7247 } else {
7248 glDrawElementsInstancedANGLE(mode, count, type, indices, primcount);
7251 if (used_client_side_array) {
7252 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
7253 element_array_buffer->service_id());
7256 if (textures_set) {
7257 RestoreStateForTextures();
7259 if (simulated_fixed_attribs) {
7260 RestoreStateForSimulatedFixedAttribs();
7263 if (simulated_attrib_0) {
7264 // We don't have to restore attrib 0 generic data at the end of this
7265 // function even if it is simulated. This is because we will simulate
7266 // it in each draw call, and attrib 0 generic data queries use cached
7267 // values instead of passing down to the underlying driver.
7268 RestoreStateForAttrib(0, false);
7271 return error::kNoError;
7274 error::Error GLES2DecoderImpl::HandleDrawElements(uint32 immediate_data_size,
7275 const void* cmd_data) {
7276 // TODO(zmo): crbug.com/481184
7277 // On Desktop GL with versions lower than 4.3, we need to emulate
7278 // GL_PRIMITIVE_RESTART_FIXED_INDEX using glPrimitiveRestartIndex().
7279 const gles2::cmds::DrawElements& c =
7280 *static_cast<const gles2::cmds::DrawElements*>(cmd_data);
7281 return DoDrawElements("glDrawElements",
7282 false,
7283 static_cast<GLenum>(c.mode),
7284 static_cast<GLsizei>(c.count),
7285 static_cast<GLenum>(c.type),
7286 static_cast<int32>(c.index_offset),
7290 error::Error GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
7291 uint32 immediate_data_size,
7292 const void* cmd_data) {
7293 const gles2::cmds::DrawElementsInstancedANGLE& c =
7294 *static_cast<const gles2::cmds::DrawElementsInstancedANGLE*>(cmd_data);
7295 if (!features().angle_instanced_arrays) {
7296 LOCAL_SET_GL_ERROR(
7297 GL_INVALID_OPERATION,
7298 "glDrawElementsInstancedANGLE", "function not available");
7299 return error::kNoError;
7301 return DoDrawElements("glDrawElementsInstancedANGLE",
7302 true,
7303 static_cast<GLenum>(c.mode),
7304 static_cast<GLsizei>(c.count),
7305 static_cast<GLenum>(c.type),
7306 static_cast<int32>(c.index_offset),
7307 static_cast<GLsizei>(c.primcount));
7310 GLuint GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
7311 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
7312 GLuint max_vertex_accessed = 0;
7313 Buffer* buffer = GetBuffer(buffer_id);
7314 if (!buffer) {
7315 // TODO(gman): Should this be a GL error or a command buffer error?
7316 LOCAL_SET_GL_ERROR(
7317 GL_INVALID_VALUE, "GetMaxValueInBufferCHROMIUM", "unknown buffer");
7318 } else {
7319 if (!buffer->GetMaxValueForRange(
7320 offset, count, type, &max_vertex_accessed)) {
7321 // TODO(gman): Should this be a GL error or a command buffer error?
7322 LOCAL_SET_GL_ERROR(
7323 GL_INVALID_OPERATION,
7324 "GetMaxValueInBufferCHROMIUM", "range out of bounds for buffer");
7327 return max_vertex_accessed;
7330 void GLES2DecoderImpl::DoShaderSource(
7331 GLuint client_id, GLsizei count, const char** data, const GLint* length) {
7332 std::string str;
7333 for (GLsizei ii = 0; ii < count; ++ii) {
7334 if (length && length[ii] > 0)
7335 str.append(data[ii], length[ii]);
7336 else
7337 str.append(data[ii]);
7339 Shader* shader = GetShaderInfoNotProgram(client_id, "glShaderSource");
7340 if (!shader) {
7341 return;
7343 // Note: We don't actually call glShaderSource here. We wait until
7344 // we actually compile the shader.
7345 shader->set_source(str);
7348 void GLES2DecoderImpl::DoTransformFeedbackVaryings(
7349 GLuint client_program_id, GLsizei count, const char* const* varyings,
7350 GLenum buffer_mode) {
7351 Program* program = GetProgramInfoNotShader(
7352 client_program_id, "glTransformFeedbackVaryings");
7353 if (!program) {
7354 return;
7356 program->TransformFeedbackVaryings(count, varyings, buffer_mode);
7357 glTransformFeedbackVaryings(
7358 program->service_id(), count, varyings, buffer_mode);
7361 void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
7362 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
7363 Shader* shader = GetShaderInfoNotProgram(client_id, "glCompileShader");
7364 if (!shader) {
7365 return;
7368 scoped_refptr<ShaderTranslatorInterface> translator;
7369 if (use_shader_translator_) {
7370 translator = shader->shader_type() == GL_VERTEX_SHADER ?
7371 vertex_translator_ : fragment_translator_;
7374 const Shader::TranslatedShaderSourceType source_type =
7375 feature_info_->feature_flags().angle_translated_shader_source ?
7376 Shader::kANGLE : Shader::kGL;
7377 shader->RequestCompile(translator, source_type);
7380 void GLES2DecoderImpl::DoGetShaderiv(
7381 GLuint shader_id, GLenum pname, GLint* params) {
7382 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderiv");
7383 if (!shader) {
7384 return;
7387 // Compile now for statuses that require it.
7388 switch (pname) {
7389 case GL_COMPILE_STATUS:
7390 case GL_INFO_LOG_LENGTH:
7391 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
7392 shader->DoCompile();
7393 break;
7395 default:
7396 break;
7399 switch (pname) {
7400 case GL_SHADER_SOURCE_LENGTH:
7401 *params = shader->source().size();
7402 if (*params)
7403 ++(*params);
7404 return;
7405 case GL_COMPILE_STATUS:
7406 *params = compile_shader_always_succeeds_ ? true : shader->valid();
7407 return;
7408 case GL_INFO_LOG_LENGTH:
7409 *params = shader->log_info().size();
7410 if (*params)
7411 ++(*params);
7412 return;
7413 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
7414 *params = shader->translated_source().size();
7415 if (*params)
7416 ++(*params);
7417 return;
7418 default:
7419 break;
7421 glGetShaderiv(shader->service_id(), pname, params);
7424 error::Error GLES2DecoderImpl::HandleGetShaderSource(uint32 immediate_data_size,
7425 const void* cmd_data) {
7426 const gles2::cmds::GetShaderSource& c =
7427 *static_cast<const gles2::cmds::GetShaderSource*>(cmd_data);
7428 GLuint shader_id = c.shader;
7429 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
7430 Bucket* bucket = CreateBucket(bucket_id);
7431 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderSource");
7432 if (!shader || shader->source().empty()) {
7433 bucket->SetSize(0);
7434 return error::kNoError;
7436 bucket->SetFromString(shader->source().c_str());
7437 return error::kNoError;
7440 error::Error GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
7441 uint32 immediate_data_size,
7442 const void* cmd_data) {
7443 const gles2::cmds::GetTranslatedShaderSourceANGLE& c =
7444 *static_cast<const gles2::cmds::GetTranslatedShaderSourceANGLE*>(
7445 cmd_data);
7446 GLuint shader_id = c.shader;
7447 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
7448 Bucket* bucket = CreateBucket(bucket_id);
7449 Shader* shader = GetShaderInfoNotProgram(
7450 shader_id, "glGetTranslatedShaderSourceANGLE");
7451 if (!shader) {
7452 bucket->SetSize(0);
7453 return error::kNoError;
7456 // Make sure translator has been utilized in compile.
7457 shader->DoCompile();
7459 bucket->SetFromString(shader->translated_source().c_str());
7460 return error::kNoError;
7463 error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
7464 uint32 immediate_data_size,
7465 const void* cmd_data) {
7466 const gles2::cmds::GetProgramInfoLog& c =
7467 *static_cast<const gles2::cmds::GetProgramInfoLog*>(cmd_data);
7468 GLuint program_id = c.program;
7469 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
7470 Bucket* bucket = CreateBucket(bucket_id);
7471 Program* program = GetProgramInfoNotShader(
7472 program_id, "glGetProgramInfoLog");
7473 if (!program || !program->log_info()) {
7474 bucket->SetFromString("");
7475 return error::kNoError;
7477 bucket->SetFromString(program->log_info()->c_str());
7478 return error::kNoError;
7481 error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
7482 uint32 immediate_data_size,
7483 const void* cmd_data) {
7484 const gles2::cmds::GetShaderInfoLog& c =
7485 *static_cast<const gles2::cmds::GetShaderInfoLog*>(cmd_data);
7486 GLuint shader_id = c.shader;
7487 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
7488 Bucket* bucket = CreateBucket(bucket_id);
7489 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderInfoLog");
7490 if (!shader) {
7491 bucket->SetFromString("");
7492 return error::kNoError;
7495 // Shader must be compiled in order to get the info log.
7496 shader->DoCompile();
7498 bucket->SetFromString(shader->log_info().c_str());
7499 return error::kNoError;
7502 bool GLES2DecoderImpl::DoIsEnabled(GLenum cap) {
7503 return state_.GetEnabled(cap);
7506 bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
7507 const Buffer* buffer = GetBuffer(client_id);
7508 return buffer && buffer->IsValid() && !buffer->IsDeleted();
7511 bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
7512 const Framebuffer* framebuffer =
7513 GetFramebuffer(client_id);
7514 return framebuffer && framebuffer->IsValid() && !framebuffer->IsDeleted();
7517 bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
7518 // IsProgram is true for programs as soon as they are created, until they are
7519 // deleted and no longer in use.
7520 const Program* program = GetProgram(client_id);
7521 return program != NULL && !program->IsDeleted();
7524 bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
7525 const Renderbuffer* renderbuffer =
7526 GetRenderbuffer(client_id);
7527 return renderbuffer && renderbuffer->IsValid() && !renderbuffer->IsDeleted();
7530 bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
7531 // IsShader is true for shaders as soon as they are created, until they
7532 // are deleted and not attached to any programs.
7533 const Shader* shader = GetShader(client_id);
7534 return shader != NULL && !shader->IsDeleted();
7537 bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
7538 const TextureRef* texture_ref = GetTexture(client_id);
7539 return texture_ref && texture_ref->texture()->IsValid();
7542 void GLES2DecoderImpl::DoAttachShader(
7543 GLuint program_client_id, GLint shader_client_id) {
7544 Program* program = GetProgramInfoNotShader(
7545 program_client_id, "glAttachShader");
7546 if (!program) {
7547 return;
7549 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glAttachShader");
7550 if (!shader) {
7551 return;
7553 if (!program->AttachShader(shader_manager(), shader)) {
7554 LOCAL_SET_GL_ERROR(
7555 GL_INVALID_OPERATION,
7556 "glAttachShader",
7557 "can not attach more than one shader of the same type.");
7558 return;
7560 glAttachShader(program->service_id(), shader->service_id());
7563 void GLES2DecoderImpl::DoDetachShader(
7564 GLuint program_client_id, GLint shader_client_id) {
7565 Program* program = GetProgramInfoNotShader(
7566 program_client_id, "glDetachShader");
7567 if (!program) {
7568 return;
7570 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glDetachShader");
7571 if (!shader) {
7572 return;
7574 if (!program->DetachShader(shader_manager(), shader)) {
7575 LOCAL_SET_GL_ERROR(
7576 GL_INVALID_OPERATION,
7577 "glDetachShader", "shader not attached to program");
7578 return;
7580 glDetachShader(program->service_id(), shader->service_id());
7583 void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
7584 Program* program = GetProgramInfoNotShader(
7585 program_client_id, "glValidateProgram");
7586 if (!program) {
7587 return;
7589 program->Validate();
7592 void GLES2DecoderImpl::GetVertexAttribHelper(
7593 const VertexAttrib* attrib, GLenum pname, GLint* params) {
7594 switch (pname) {
7595 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
7596 Buffer* buffer = attrib->buffer();
7597 if (buffer && !buffer->IsDeleted()) {
7598 GLuint client_id;
7599 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
7600 *params = client_id;
7602 break;
7604 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
7605 *params = attrib->enabled();
7606 break;
7607 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
7608 *params = attrib->size();
7609 break;
7610 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
7611 *params = attrib->gl_stride();
7612 break;
7613 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
7614 *params = attrib->type();
7615 break;
7616 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
7617 *params = attrib->normalized();
7618 break;
7619 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE:
7620 *params = attrib->divisor();
7621 break;
7622 default:
7623 NOTREACHED();
7624 break;
7628 void GLES2DecoderImpl::DoGetTexParameterfv(
7629 GLenum target, GLenum pname, GLfloat* params) {
7630 InitTextureMaxAnisotropyIfNeeded(target, pname);
7631 glGetTexParameterfv(target, pname, params);
7634 void GLES2DecoderImpl::DoGetTexParameteriv(
7635 GLenum target, GLenum pname, GLint* params) {
7636 InitTextureMaxAnisotropyIfNeeded(target, pname);
7637 glGetTexParameteriv(target, pname, params);
7640 void GLES2DecoderImpl::InitTextureMaxAnisotropyIfNeeded(
7641 GLenum target, GLenum pname) {
7642 if (!workarounds().init_texture_max_anisotropy)
7643 return;
7644 if (pname != GL_TEXTURE_MAX_ANISOTROPY_EXT ||
7645 !validators_->texture_parameter.IsValid(pname)) {
7646 return;
7649 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
7650 &state_, target);
7651 if (!texture_ref) {
7652 LOCAL_SET_GL_ERROR(
7653 GL_INVALID_OPERATION,
7654 "glGetTexParamter{fi}v", "unknown texture for target");
7655 return;
7657 Texture* texture = texture_ref->texture();
7658 texture->InitTextureMaxAnisotropyIfNeeded(target);
7661 void GLES2DecoderImpl::DoGetVertexAttribfv(
7662 GLuint index, GLenum pname, GLfloat* params) {
7663 VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(index);
7664 if (!attrib) {
7665 LOCAL_SET_GL_ERROR(
7666 GL_INVALID_VALUE, "glGetVertexAttribfv", "index out of range");
7667 return;
7669 switch (pname) {
7670 case GL_CURRENT_VERTEX_ATTRIB: {
7671 const Vec4& value = state_.attrib_values[index];
7672 params[0] = value.v[0];
7673 params[1] = value.v[1];
7674 params[2] = value.v[2];
7675 params[3] = value.v[3];
7676 break;
7678 default: {
7679 GLint value = 0;
7680 GetVertexAttribHelper(attrib, pname, &value);
7681 *params = static_cast<GLfloat>(value);
7682 break;
7687 void GLES2DecoderImpl::DoGetVertexAttribiv(
7688 GLuint index, GLenum pname, GLint* params) {
7689 VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(index);
7690 if (!attrib) {
7691 LOCAL_SET_GL_ERROR(
7692 GL_INVALID_VALUE, "glGetVertexAttribiv", "index out of range");
7693 return;
7695 switch (pname) {
7696 case GL_CURRENT_VERTEX_ATTRIB: {
7697 const Vec4& value = state_.attrib_values[index];
7698 params[0] = static_cast<GLint>(value.v[0]);
7699 params[1] = static_cast<GLint>(value.v[1]);
7700 params[2] = static_cast<GLint>(value.v[2]);
7701 params[3] = static_cast<GLint>(value.v[3]);
7702 break;
7704 default:
7705 GetVertexAttribHelper(attrib, pname, params);
7706 break;
7710 bool GLES2DecoderImpl::SetVertexAttribValue(
7711 const char* function_name, GLuint index, const GLfloat* value) {
7712 if (index >= state_.attrib_values.size()) {
7713 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "index out of range");
7714 return false;
7716 Vec4& v = state_.attrib_values[index];
7717 v.v[0] = value[0];
7718 v.v[1] = value[1];
7719 v.v[2] = value[2];
7720 v.v[3] = value[3];
7721 return true;
7724 void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
7725 GLfloat v[4] = { v0, 0.0f, 0.0f, 1.0f, };
7726 if (SetVertexAttribValue("glVertexAttrib1f", index, v)) {
7727 glVertexAttrib1f(index, v0);
7731 void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
7732 GLfloat v[4] = { v0, v1, 0.0f, 1.0f, };
7733 if (SetVertexAttribValue("glVertexAttrib2f", index, v)) {
7734 glVertexAttrib2f(index, v0, v1);
7738 void GLES2DecoderImpl::DoVertexAttrib3f(
7739 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
7740 GLfloat v[4] = { v0, v1, v2, 1.0f, };
7741 if (SetVertexAttribValue("glVertexAttrib3f", index, v)) {
7742 glVertexAttrib3f(index, v0, v1, v2);
7746 void GLES2DecoderImpl::DoVertexAttrib4f(
7747 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
7748 GLfloat v[4] = { v0, v1, v2, v3, };
7749 if (SetVertexAttribValue("glVertexAttrib4f", index, v)) {
7750 glVertexAttrib4f(index, v0, v1, v2, v3);
7754 void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
7755 GLfloat t[4] = { v[0], 0.0f, 0.0f, 1.0f, };
7756 if (SetVertexAttribValue("glVertexAttrib1fv", index, t)) {
7757 glVertexAttrib1fv(index, v);
7761 void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
7762 GLfloat t[4] = { v[0], v[1], 0.0f, 1.0f, };
7763 if (SetVertexAttribValue("glVertexAttrib2fv", index, t)) {
7764 glVertexAttrib2fv(index, v);
7768 void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
7769 GLfloat t[4] = { v[0], v[1], v[2], 1.0f, };
7770 if (SetVertexAttribValue("glVertexAttrib3fv", index, t)) {
7771 glVertexAttrib3fv(index, v);
7775 void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
7776 if (SetVertexAttribValue("glVertexAttrib4fv", index, v)) {
7777 glVertexAttrib4fv(index, v);
7781 error::Error GLES2DecoderImpl::HandleVertexAttribIPointer(
7782 uint32 immediate_data_size,
7783 const void* cmd_data) {
7784 if (!unsafe_es3_apis_enabled())
7785 return error::kUnknownCommand;
7786 const gles2::cmds::VertexAttribIPointer& c =
7787 *static_cast<const gles2::cmds::VertexAttribIPointer*>(cmd_data);
7789 if (!state_.bound_array_buffer.get() ||
7790 state_.bound_array_buffer->IsDeleted()) {
7791 if (state_.vertex_attrib_manager.get() ==
7792 state_.default_vertex_attrib_manager.get()) {
7793 LOCAL_SET_GL_ERROR(
7794 GL_INVALID_VALUE, "glVertexAttribIPointer", "no array buffer bound");
7795 return error::kNoError;
7796 } else if (c.offset != 0) {
7797 LOCAL_SET_GL_ERROR(
7798 GL_INVALID_VALUE,
7799 "glVertexAttribIPointer", "client side arrays are not allowed");
7800 return error::kNoError;
7804 GLuint indx = c.indx;
7805 GLint size = c.size;
7806 GLenum type = c.type;
7807 GLsizei stride = c.stride;
7808 GLsizei offset = c.offset;
7809 const void* ptr = reinterpret_cast<const void*>(offset);
7810 if (!validators_->vertex_attrib_i_type.IsValid(type)) {
7811 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribIPointer", type, "type");
7812 return error::kNoError;
7814 if (!validators_->vertex_attrib_size.IsValid(size)) {
7815 LOCAL_SET_GL_ERROR(
7816 GL_INVALID_VALUE, "glVertexAttribIPointer", "size GL_INVALID_VALUE");
7817 return error::kNoError;
7819 if (indx >= group_->max_vertex_attribs()) {
7820 LOCAL_SET_GL_ERROR(
7821 GL_INVALID_VALUE, "glVertexAttribIPointer", "index out of range");
7822 return error::kNoError;
7824 if (stride < 0) {
7825 LOCAL_SET_GL_ERROR(
7826 GL_INVALID_VALUE, "glVertexAttribIPointer", "stride < 0");
7827 return error::kNoError;
7829 if (stride > 255) {
7830 LOCAL_SET_GL_ERROR(
7831 GL_INVALID_VALUE, "glVertexAttribIPointer", "stride > 255");
7832 return error::kNoError;
7834 if (offset < 0) {
7835 LOCAL_SET_GL_ERROR(
7836 GL_INVALID_VALUE, "glVertexAttribIPointer", "offset < 0");
7837 return error::kNoError;
7839 GLsizei component_size =
7840 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
7841 // component_size must be a power of two to use & as optimized modulo.
7842 DCHECK(GLES2Util::IsPOT(component_size));
7843 if (offset & (component_size - 1)) {
7844 LOCAL_SET_GL_ERROR(
7845 GL_INVALID_OPERATION,
7846 "glVertexAttribIPointer", "offset not valid for type");
7847 return error::kNoError;
7849 if (stride & (component_size - 1)) {
7850 LOCAL_SET_GL_ERROR(
7851 GL_INVALID_OPERATION,
7852 "glVertexAttribIPointer", "stride not valid for type");
7853 return error::kNoError;
7855 state_.vertex_attrib_manager
7856 ->SetAttribInfo(indx,
7857 state_.bound_array_buffer.get(),
7858 size,
7859 type,
7860 GL_FALSE,
7861 stride,
7862 stride != 0 ? stride : component_size * size,
7863 offset);
7864 glVertexAttribIPointer(indx, size, type, stride, ptr);
7865 return error::kNoError;
7868 error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
7869 uint32 immediate_data_size,
7870 const void* cmd_data) {
7871 const gles2::cmds::VertexAttribPointer& c =
7872 *static_cast<const gles2::cmds::VertexAttribPointer*>(cmd_data);
7874 if (!state_.bound_array_buffer.get() ||
7875 state_.bound_array_buffer->IsDeleted()) {
7876 if (state_.vertex_attrib_manager.get() ==
7877 state_.default_vertex_attrib_manager.get()) {
7878 LOCAL_SET_GL_ERROR(
7879 GL_INVALID_VALUE, "glVertexAttribPointer", "no array buffer bound");
7880 return error::kNoError;
7881 } else if (c.offset != 0) {
7882 LOCAL_SET_GL_ERROR(
7883 GL_INVALID_VALUE,
7884 "glVertexAttribPointer", "client side arrays are not allowed");
7885 return error::kNoError;
7889 GLuint indx = c.indx;
7890 GLint size = c.size;
7891 GLenum type = c.type;
7892 GLboolean normalized = static_cast<GLboolean>(c.normalized);
7893 GLsizei stride = c.stride;
7894 GLsizei offset = c.offset;
7895 const void* ptr = reinterpret_cast<const void*>(offset);
7896 if (!validators_->vertex_attrib_type.IsValid(type)) {
7897 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribPointer", type, "type");
7898 return error::kNoError;
7900 if (!validators_->vertex_attrib_size.IsValid(size)) {
7901 LOCAL_SET_GL_ERROR(
7902 GL_INVALID_VALUE, "glVertexAttribPointer", "size GL_INVALID_VALUE");
7903 return error::kNoError;
7905 if (indx >= group_->max_vertex_attribs()) {
7906 LOCAL_SET_GL_ERROR(
7907 GL_INVALID_VALUE, "glVertexAttribPointer", "index out of range");
7908 return error::kNoError;
7910 if (stride < 0) {
7911 LOCAL_SET_GL_ERROR(
7912 GL_INVALID_VALUE, "glVertexAttribPointer", "stride < 0");
7913 return error::kNoError;
7915 if (stride > 255) {
7916 LOCAL_SET_GL_ERROR(
7917 GL_INVALID_VALUE, "glVertexAttribPointer", "stride > 255");
7918 return error::kNoError;
7920 if (offset < 0) {
7921 LOCAL_SET_GL_ERROR(
7922 GL_INVALID_VALUE, "glVertexAttribPointer", "offset < 0");
7923 return error::kNoError;
7925 GLsizei component_size =
7926 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
7927 // component_size must be a power of two to use & as optimized modulo.
7928 DCHECK(GLES2Util::IsPOT(component_size));
7929 if (offset & (component_size - 1)) {
7930 LOCAL_SET_GL_ERROR(
7931 GL_INVALID_OPERATION,
7932 "glVertexAttribPointer", "offset not valid for type");
7933 return error::kNoError;
7935 if (stride & (component_size - 1)) {
7936 LOCAL_SET_GL_ERROR(
7937 GL_INVALID_OPERATION,
7938 "glVertexAttribPointer", "stride not valid for type");
7939 return error::kNoError;
7941 state_.vertex_attrib_manager
7942 ->SetAttribInfo(indx,
7943 state_.bound_array_buffer.get(),
7944 size,
7945 type,
7946 normalized,
7947 stride,
7948 stride != 0 ? stride : component_size * size,
7949 offset);
7950 // We support GL_FIXED natively on EGL/GLES2 implementations
7951 if (type != GL_FIXED || feature_info_->gl_version_info().is_es) {
7952 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
7954 return error::kNoError;
7957 void GLES2DecoderImpl::DoViewport(GLint x, GLint y, GLsizei width,
7958 GLsizei height) {
7959 state_.viewport_x = x;
7960 state_.viewport_y = y;
7961 state_.viewport_width = std::min(width, viewport_max_width_);
7962 state_.viewport_height = std::min(height, viewport_max_height_);
7963 glViewport(x, y, width, height);
7966 error::Error GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
7967 uint32 immediate_data_size,
7968 const void* cmd_data) {
7969 const gles2::cmds::VertexAttribDivisorANGLE& c =
7970 *static_cast<const gles2::cmds::VertexAttribDivisorANGLE*>(cmd_data);
7971 if (!features().angle_instanced_arrays) {
7972 LOCAL_SET_GL_ERROR(
7973 GL_INVALID_OPERATION,
7974 "glVertexAttribDivisorANGLE", "function not available");
7975 return error::kNoError;
7977 GLuint index = c.index;
7978 GLuint divisor = c.divisor;
7979 if (index >= group_->max_vertex_attribs()) {
7980 LOCAL_SET_GL_ERROR(
7981 GL_INVALID_VALUE,
7982 "glVertexAttribDivisorANGLE", "index out of range");
7983 return error::kNoError;
7986 state_.vertex_attrib_manager->SetDivisor(
7987 index,
7988 divisor);
7989 glVertexAttribDivisorANGLE(index, divisor);
7990 return error::kNoError;
7993 template <typename pixel_data_type>
7994 static void WriteAlphaData(
7995 void* pixels, uint32 row_count, uint32 channel_count,
7996 uint32 alpha_channel_index, uint32 unpadded_row_size,
7997 uint32 padded_row_size, pixel_data_type alpha_value) {
7998 DCHECK_GT(channel_count, 0U);
7999 DCHECK_EQ(unpadded_row_size % sizeof(pixel_data_type), 0U);
8000 uint32 unpadded_row_size_in_elements =
8001 unpadded_row_size / sizeof(pixel_data_type);
8002 DCHECK_EQ(padded_row_size % sizeof(pixel_data_type), 0U);
8003 uint32 padded_row_size_in_elements =
8004 padded_row_size / sizeof(pixel_data_type);
8005 pixel_data_type* dst =
8006 static_cast<pixel_data_type*>(pixels) + alpha_channel_index;
8007 for (uint32 yy = 0; yy < row_count; ++yy) {
8008 pixel_data_type* end = dst + unpadded_row_size_in_elements;
8009 for (pixel_data_type* d = dst; d < end; d += channel_count) {
8010 *d = alpha_value;
8012 dst += padded_row_size_in_elements;
8016 void GLES2DecoderImpl::FinishReadPixels(
8017 const cmds::ReadPixels& c,
8018 GLuint buffer) {
8019 TRACE_EVENT0("gpu", "GLES2DecoderImpl::FinishReadPixels");
8020 GLsizei width = c.width;
8021 GLsizei height = c.height;
8022 GLenum format = c.format;
8023 GLenum type = c.type;
8024 typedef cmds::ReadPixels::Result Result;
8025 uint32 pixels_size;
8026 Result* result = NULL;
8027 if (c.result_shm_id != 0) {
8028 result = GetSharedMemoryAs<Result*>(
8029 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8030 if (!result) {
8031 if (buffer != 0) {
8032 glDeleteBuffersARB(1, &buffer);
8034 return;
8037 GLES2Util::ComputeImageDataSizes(
8038 width, height, 1, format, type, state_.pack_alignment, &pixels_size,
8039 NULL, NULL);
8040 void* pixels = GetSharedMemoryAs<void*>(
8041 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
8042 if (!pixels) {
8043 if (buffer != 0) {
8044 glDeleteBuffersARB(1, &buffer);
8046 return;
8049 if (buffer != 0) {
8050 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
8051 void* data;
8052 if (features().map_buffer_range) {
8053 data = glMapBufferRange(
8054 GL_PIXEL_PACK_BUFFER_ARB, 0, pixels_size, GL_MAP_READ_BIT);
8055 } else {
8056 data = glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
8058 if (!data) {
8059 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glMapBuffer",
8060 "Unable to map memory for readback.");
8061 return;
8063 memcpy(pixels, data, pixels_size);
8064 // GL_PIXEL_PACK_BUFFER_ARB is currently unused, so we don't
8065 // have to restore the state.
8066 glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB);
8067 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
8068 glDeleteBuffersARB(1, &buffer);
8071 if (result != NULL) {
8072 *result = true;
8075 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
8076 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
8077 if ((channels_exist & 0x0008) == 0 &&
8078 workarounds().clear_alpha_in_readpixels) {
8079 // Set the alpha to 255 because some drivers are buggy in this regard.
8080 uint32 temp_size;
8082 uint32 unpadded_row_size;
8083 uint32 padded_row_size;
8084 if (!GLES2Util::ComputeImageDataSizes(
8085 width, 2, 1, format, type, state_.pack_alignment, &temp_size,
8086 &unpadded_row_size, &padded_row_size)) {
8087 return;
8090 uint32 channel_count = 0;
8091 uint32 alpha_channel = 0;
8092 switch (format) {
8093 case GL_RGBA:
8094 case GL_BGRA_EXT:
8095 channel_count = 4;
8096 alpha_channel = 3;
8097 break;
8098 case GL_ALPHA:
8099 channel_count = 1;
8100 alpha_channel = 0;
8101 break;
8104 if (channel_count > 0) {
8105 switch (type) {
8106 case GL_UNSIGNED_BYTE:
8107 WriteAlphaData<uint8>(
8108 pixels, height, channel_count, alpha_channel, unpadded_row_size,
8109 padded_row_size, 0xFF);
8110 break;
8111 case GL_FLOAT:
8112 WriteAlphaData<float>(
8113 pixels, height, channel_count, alpha_channel, unpadded_row_size,
8114 padded_row_size, 1.0f);
8115 break;
8116 case GL_HALF_FLOAT:
8117 WriteAlphaData<uint16>(
8118 pixels, height, channel_count, alpha_channel, unpadded_row_size,
8119 padded_row_size, 0x3C00);
8120 break;
8126 error::Error GLES2DecoderImpl::HandleReadPixels(uint32 immediate_data_size,
8127 const void* cmd_data) {
8128 const gles2::cmds::ReadPixels& c =
8129 *static_cast<const gles2::cmds::ReadPixels*>(cmd_data);
8130 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleReadPixels");
8131 error::Error fbo_error = WillAccessBoundFramebufferForRead();
8132 if (fbo_error != error::kNoError)
8133 return fbo_error;
8134 GLint x = c.x;
8135 GLint y = c.y;
8136 GLsizei width = c.width;
8137 GLsizei height = c.height;
8138 GLenum format = c.format;
8139 GLenum type = c.type;
8140 GLboolean async = static_cast<GLboolean>(c.async);
8141 if (width < 0 || height < 0) {
8142 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glReadPixels", "dimensions < 0");
8143 return error::kNoError;
8145 typedef cmds::ReadPixels::Result Result;
8146 uint32 pixels_size;
8147 if (!GLES2Util::ComputeImageDataSizes(
8148 width, height, 1, format, type, state_.pack_alignment, &pixels_size,
8149 NULL, NULL)) {
8150 return error::kOutOfBounds;
8152 void* pixels = GetSharedMemoryAs<void*>(
8153 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
8154 if (!pixels) {
8155 return error::kOutOfBounds;
8157 Result* result = NULL;
8158 if (c.result_shm_id != 0) {
8159 result = GetSharedMemoryAs<Result*>(
8160 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8161 if (!result) {
8162 return error::kOutOfBounds;
8166 if (!validators_->read_pixel_format.IsValid(format)) {
8167 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", format, "format");
8168 return error::kNoError;
8170 if (!validators_->read_pixel_type.IsValid(type)) {
8171 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", type, "type");
8172 return error::kNoError;
8174 if ((format != GL_RGBA && format != GL_BGRA_EXT && format != GL_RGB &&
8175 format != GL_ALPHA) || type != GL_UNSIGNED_BYTE) {
8176 // format and type are acceptable enums but not guaranteed to be supported
8177 // for this framebuffer. Have to ask gl if they are valid.
8178 GLint preferred_format = 0;
8179 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &preferred_format);
8180 GLint preferred_type = 0;
8181 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &preferred_type);
8182 if (format != static_cast<GLenum>(preferred_format) ||
8183 type != static_cast<GLenum>(preferred_type)) {
8184 LOCAL_SET_GL_ERROR(
8185 GL_INVALID_OPERATION, "glReadPixels", "format and type incompatible "
8186 "with the current read framebuffer");
8187 return error::kNoError;
8190 if (width == 0 || height == 0) {
8191 return error::kNoError;
8194 // Get the size of the current fbo or backbuffer.
8195 gfx::Size max_size = GetBoundReadFrameBufferSize();
8197 int32 max_x;
8198 int32 max_y;
8199 if (!SafeAddInt32(x, width, &max_x) || !SafeAddInt32(y, height, &max_y)) {
8200 LOCAL_SET_GL_ERROR(
8201 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
8202 return error::kNoError;
8205 if (!CheckBoundReadFramebufferColorAttachment("glReadPixels")) {
8206 return error::kNoError;
8209 if (!CheckBoundFramebuffersValid("glReadPixels")) {
8210 return error::kNoError;
8213 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixels");
8215 ScopedResolvedFrameBufferBinder binder(this, false, true);
8217 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
8218 // The user requested an out of range area. Get the results 1 line
8219 // at a time.
8220 uint32 temp_size;
8221 uint32 unpadded_row_size;
8222 uint32 padded_row_size;
8223 if (!GLES2Util::ComputeImageDataSizes(
8224 width, 2, 1, format, type, state_.pack_alignment, &temp_size,
8225 &unpadded_row_size, &padded_row_size)) {
8226 LOCAL_SET_GL_ERROR(
8227 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
8228 return error::kNoError;
8231 GLint dest_x_offset = std::max(-x, 0);
8232 uint32 dest_row_offset;
8233 if (!GLES2Util::ComputeImageDataSizes(
8234 dest_x_offset, 1, 1, format, type, state_.pack_alignment,
8235 &dest_row_offset, NULL, NULL)) {
8236 LOCAL_SET_GL_ERROR(
8237 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
8238 return error::kNoError;
8241 // Copy each row into the larger dest rect.
8242 int8* dst = static_cast<int8*>(pixels);
8243 GLint read_x = std::max(0, x);
8244 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
8245 GLint read_width = read_end_x - read_x;
8246 for (GLint yy = 0; yy < height; ++yy) {
8247 GLint ry = y + yy;
8249 // Clear the row.
8250 memset(dst, 0, unpadded_row_size);
8252 // If the row is in range, copy it.
8253 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
8254 glReadPixels(
8255 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
8257 dst += padded_row_size;
8259 } else {
8260 if (async && features().use_async_readpixels) {
8261 GLuint buffer = 0;
8262 glGenBuffersARB(1, &buffer);
8263 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
8264 // For ANGLE client version 2, GL_STREAM_READ is not available.
8265 const GLenum usage_hint = feature_info_->gl_version_info().is_angle ?
8266 GL_STATIC_DRAW : GL_STREAM_READ;
8267 glBufferData(GL_PIXEL_PACK_BUFFER_ARB, pixels_size, NULL, usage_hint);
8268 GLenum error = glGetError();
8269 if (error == GL_NO_ERROR) {
8270 glReadPixels(x, y, width, height, format, type, 0);
8271 pending_readpixel_fences_.push(linked_ptr<FenceCallback>(
8272 new FenceCallback()));
8273 WaitForReadPixels(base::Bind(
8274 &GLES2DecoderImpl::FinishReadPixels,
8275 base::internal::SupportsWeakPtrBase::StaticAsWeakPtr
8276 <GLES2DecoderImpl>(this),
8277 c, buffer));
8278 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
8279 return error::kNoError;
8280 } else {
8281 // On error, unbind pack buffer and fall through to sync readpixels
8282 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
8283 glDeleteBuffersARB(1, &buffer);
8286 glReadPixels(x, y, width, height, format, type, pixels);
8288 GLenum error = LOCAL_PEEK_GL_ERROR("glReadPixels");
8289 if (error == GL_NO_ERROR) {
8290 if (result != NULL) {
8291 *result = true;
8293 FinishReadPixels(c, 0);
8296 return error::kNoError;
8299 error::Error GLES2DecoderImpl::HandlePixelStorei(uint32 immediate_data_size,
8300 const void* cmd_data) {
8301 const gles2::cmds::PixelStorei& c =
8302 *static_cast<const gles2::cmds::PixelStorei*>(cmd_data);
8303 GLenum pname = c.pname;
8304 GLenum param = c.param;
8305 if (!validators_->pixel_store.IsValid(pname)) {
8306 LOCAL_SET_GL_ERROR_INVALID_ENUM("glPixelStorei", pname, "pname");
8307 return error::kNoError;
8309 switch (pname) {
8310 case GL_PACK_ALIGNMENT:
8311 case GL_UNPACK_ALIGNMENT:
8312 if (!validators_->pixel_store_alignment.IsValid(param)) {
8313 LOCAL_SET_GL_ERROR(
8314 GL_INVALID_VALUE, "glPixelStorei", "param GL_INVALID_VALUE");
8315 return error::kNoError;
8317 break;
8318 case GL_UNPACK_FLIP_Y_CHROMIUM:
8319 unpack_flip_y_ = (param != 0);
8320 return error::kNoError;
8321 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
8322 unpack_premultiply_alpha_ = (param != 0);
8323 return error::kNoError;
8324 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM:
8325 unpack_unpremultiply_alpha_ = (param != 0);
8326 return error::kNoError;
8327 default:
8328 break;
8330 glPixelStorei(pname, param);
8331 switch (pname) {
8332 case GL_PACK_ALIGNMENT:
8333 state_.pack_alignment = param;
8334 break;
8335 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
8336 state_.pack_reverse_row_order = (param != 0);
8337 break;
8338 case GL_UNPACK_ALIGNMENT:
8339 state_.unpack_alignment = param;
8340 break;
8341 default:
8342 // Validation should have prevented us from getting here.
8343 NOTREACHED();
8344 break;
8346 return error::kNoError;
8349 error::Error GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
8350 uint32 immediate_data_size,
8351 const void* cmd_data) {
8352 const gles2::cmds::PostSubBufferCHROMIUM& c =
8353 *static_cast<const gles2::cmds::PostSubBufferCHROMIUM*>(cmd_data);
8354 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
8356 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
8358 if (!supports_post_sub_buffer_) {
8359 LOCAL_SET_GL_ERROR(
8360 GL_INVALID_OPERATION,
8361 "glPostSubBufferCHROMIUM", "command not supported by surface");
8362 return error::kNoError;
8364 bool is_tracing;
8365 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
8366 &is_tracing);
8367 if (is_tracing) {
8368 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
8369 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
8370 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
8371 is_offscreen ? offscreen_size_ : surface_->GetSize());
8373 if (surface_->PostSubBuffer(c.x, c.y, c.width, c.height)) {
8374 return error::kNoError;
8375 } else {
8376 LOG(ERROR) << "Context lost because PostSubBuffer failed.";
8377 return error::kLostContext;
8381 error::Error GLES2DecoderImpl::HandleScheduleOverlayPlaneCHROMIUM(
8382 uint32 immediate_data_size,
8383 const void* cmd_data) {
8384 const gles2::cmds::ScheduleOverlayPlaneCHROMIUM& c =
8385 *static_cast<const gles2::cmds::ScheduleOverlayPlaneCHROMIUM*>(cmd_data);
8386 TextureRef* ref = texture_manager()->GetTexture(c.overlay_texture_id);
8387 if (!ref) {
8388 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
8389 "glScheduleOverlayPlaneCHROMIUM",
8390 "unknown texture");
8391 return error::kNoError;
8393 gfx::GLImage* image =
8394 ref->texture()->GetLevelImage(ref->texture()->target(), 0);
8395 if (!image) {
8396 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
8397 "glScheduleOverlayPlaneCHROMIUM",
8398 "unsupported texture format");
8399 return error::kNoError;
8401 gfx::OverlayTransform transform = GetGFXOverlayTransform(c.plane_transform);
8402 if (transform == gfx::OVERLAY_TRANSFORM_INVALID) {
8403 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM,
8404 "glScheduleOverlayPlaneCHROMIUM",
8405 "invalid transform enum");
8406 return error::kNoError;
8408 if (!surface_->ScheduleOverlayPlane(
8409 c.plane_z_order,
8410 transform,
8411 image,
8412 gfx::Rect(c.bounds_x, c.bounds_y, c.bounds_width, c.bounds_height),
8413 gfx::RectF(c.uv_x, c.uv_y, c.uv_width, c.uv_height))) {
8414 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
8415 "glScheduleOverlayPlaneCHROMIUM",
8416 "failed to schedule overlay");
8418 return error::kNoError;
8421 error::Error GLES2DecoderImpl::GetAttribLocationHelper(
8422 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
8423 const std::string& name_str) {
8424 if (!StringIsValidForGLES(name_str.c_str())) {
8425 LOCAL_SET_GL_ERROR(
8426 GL_INVALID_VALUE, "glGetAttribLocation", "Invalid character");
8427 return error::kNoError;
8429 Program* program = GetProgramInfoNotShader(
8430 client_id, "glGetAttribLocation");
8431 if (!program) {
8432 return error::kNoError;
8434 if (!program->IsValid()) {
8435 LOCAL_SET_GL_ERROR(
8436 GL_INVALID_OPERATION, "glGetAttribLocation", "program not linked");
8437 return error::kNoError;
8439 GLint* location = GetSharedMemoryAs<GLint*>(
8440 location_shm_id, location_shm_offset, sizeof(GLint));
8441 if (!location) {
8442 return error::kOutOfBounds;
8444 // Require the client to init this incase the context is lost and we are no
8445 // longer executing commands.
8446 if (*location != -1) {
8447 return error::kGenericError;
8449 *location = program->GetAttribLocation(name_str);
8450 return error::kNoError;
8453 error::Error GLES2DecoderImpl::HandleGetAttribLocation(
8454 uint32 immediate_data_size,
8455 const void* cmd_data) {
8456 const gles2::cmds::GetAttribLocation& c =
8457 *static_cast<const gles2::cmds::GetAttribLocation*>(cmd_data);
8458 Bucket* bucket = GetBucket(c.name_bucket_id);
8459 if (!bucket) {
8460 return error::kInvalidArguments;
8462 std::string name_str;
8463 if (!bucket->GetAsString(&name_str)) {
8464 return error::kInvalidArguments;
8466 return GetAttribLocationHelper(
8467 c.program, c.location_shm_id, c.location_shm_offset, name_str);
8470 error::Error GLES2DecoderImpl::GetUniformLocationHelper(
8471 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
8472 const std::string& name_str) {
8473 if (!StringIsValidForGLES(name_str.c_str())) {
8474 LOCAL_SET_GL_ERROR(
8475 GL_INVALID_VALUE, "glGetUniformLocation", "Invalid character");
8476 return error::kNoError;
8478 Program* program = GetProgramInfoNotShader(
8479 client_id, "glGetUniformLocation");
8480 if (!program) {
8481 return error::kNoError;
8483 if (!program->IsValid()) {
8484 LOCAL_SET_GL_ERROR(
8485 GL_INVALID_OPERATION, "glGetUniformLocation", "program not linked");
8486 return error::kNoError;
8488 GLint* location = GetSharedMemoryAs<GLint*>(
8489 location_shm_id, location_shm_offset, sizeof(GLint));
8490 if (!location) {
8491 return error::kOutOfBounds;
8493 // Require the client to init this incase the context is lost an we are no
8494 // longer executing commands.
8495 if (*location != -1) {
8496 return error::kGenericError;
8498 *location = program->GetUniformFakeLocation(name_str);
8499 return error::kNoError;
8502 error::Error GLES2DecoderImpl::HandleGetUniformLocation(
8503 uint32 immediate_data_size,
8504 const void* cmd_data) {
8505 const gles2::cmds::GetUniformLocation& c =
8506 *static_cast<const gles2::cmds::GetUniformLocation*>(cmd_data);
8507 Bucket* bucket = GetBucket(c.name_bucket_id);
8508 if (!bucket) {
8509 return error::kInvalidArguments;
8511 std::string name_str;
8512 if (!bucket->GetAsString(&name_str)) {
8513 return error::kInvalidArguments;
8515 return GetUniformLocationHelper(
8516 c.program, c.location_shm_id, c.location_shm_offset, name_str);
8519 error::Error GLES2DecoderImpl::HandleGetUniformIndices(
8520 uint32 immediate_data_size,
8521 const void* cmd_data) {
8522 if (!unsafe_es3_apis_enabled())
8523 return error::kUnknownCommand;
8524 const gles2::cmds::GetUniformIndices& c =
8525 *static_cast<const gles2::cmds::GetUniformIndices*>(cmd_data);
8526 Bucket* bucket = GetBucket(c.names_bucket_id);
8527 if (!bucket) {
8528 return error::kInvalidArguments;
8530 GLsizei count = 0;
8531 std::vector<char*> names;
8532 std::vector<GLint> len;
8533 if (!bucket->GetAsStrings(&count, &names, &len) || count <= 0) {
8534 return error::kInvalidArguments;
8536 typedef cmds::GetUniformIndices::Result Result;
8537 Result* result = GetSharedMemoryAs<Result*>(
8538 c.indices_shm_id, c.indices_shm_offset,
8539 Result::ComputeSize(static_cast<size_t>(count)));
8540 GLuint* indices = result ? result->GetData() : NULL;
8541 if (indices == NULL) {
8542 return error::kOutOfBounds;
8544 // Check that the client initialized the result.
8545 if (result->size != 0) {
8546 return error::kInvalidArguments;
8548 Program* program = GetProgramInfoNotShader(c.program, "glGetUniformIndices");
8549 if (!program) {
8550 return error::kNoError;
8552 GLuint service_id = program->service_id();
8553 GLint link_status = GL_FALSE;
8554 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
8555 if (link_status != GL_TRUE) {
8556 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
8557 "glGetUniformIndices", "program not linked");
8558 return error::kNoError;
8560 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetUniformIndices");
8561 glGetUniformIndices(service_id, count, &names[0], indices);
8562 GLenum error = glGetError();
8563 if (error == GL_NO_ERROR) {
8564 result->SetNumResults(count);
8565 } else {
8566 LOCAL_SET_GL_ERROR(error, "GetUniformIndices", "");
8568 return error::kNoError;
8571 error::Error GLES2DecoderImpl::GetFragDataLocationHelper(
8572 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
8573 const std::string& name_str) {
8574 GLint* location = GetSharedMemoryAs<GLint*>(
8575 location_shm_id, location_shm_offset, sizeof(GLint));
8576 if (!location) {
8577 return error::kOutOfBounds;
8579 // Require the client to init this incase the context is lost and we are no
8580 // longer executing commands.
8581 if (*location != -1) {
8582 return error::kGenericError;
8584 Program* program = GetProgramInfoNotShader(
8585 client_id, "glGetFragDataLocation");
8586 if (!program) {
8587 return error::kNoError;
8589 *location = glGetFragDataLocation(program->service_id(), name_str.c_str());
8590 return error::kNoError;
8593 error::Error GLES2DecoderImpl::HandleGetFragDataLocation(
8594 uint32 immediate_data_size,
8595 const void* cmd_data) {
8596 if (!unsafe_es3_apis_enabled())
8597 return error::kUnknownCommand;
8598 const gles2::cmds::GetFragDataLocation& c =
8599 *static_cast<const gles2::cmds::GetFragDataLocation*>(cmd_data);
8600 Bucket* bucket = GetBucket(c.name_bucket_id);
8601 if (!bucket) {
8602 return error::kInvalidArguments;
8604 std::string name_str;
8605 if (!bucket->GetAsString(&name_str)) {
8606 return error::kInvalidArguments;
8608 return GetFragDataLocationHelper(
8609 c.program, c.location_shm_id, c.location_shm_offset, name_str);
8612 error::Error GLES2DecoderImpl::HandleGetUniformBlockIndex(
8613 uint32 immediate_data_size, const void* cmd_data) {
8614 if (!unsafe_es3_apis_enabled())
8615 return error::kUnknownCommand;
8616 const gles2::cmds::GetUniformBlockIndex& c =
8617 *static_cast<const gles2::cmds::GetUniformBlockIndex*>(cmd_data);
8618 Bucket* bucket = GetBucket(c.name_bucket_id);
8619 if (!bucket) {
8620 return error::kInvalidArguments;
8622 std::string name_str;
8623 if (!bucket->GetAsString(&name_str)) {
8624 return error::kInvalidArguments;
8626 GLuint* index = GetSharedMemoryAs<GLuint*>(
8627 c.index_shm_id, c.index_shm_offset, sizeof(GLuint));
8628 if (!index) {
8629 return error::kOutOfBounds;
8631 // Require the client to init this in case the context is lost and we are no
8632 // longer executing commands.
8633 if (*index != GL_INVALID_INDEX) {
8634 return error::kGenericError;
8636 Program* program = GetProgramInfoNotShader(
8637 c.program, "glGetUniformBlockIndex");
8638 if (!program) {
8639 return error::kNoError;
8641 *index = glGetUniformBlockIndex(program->service_id(), name_str.c_str());
8642 return error::kNoError;
8645 error::Error GLES2DecoderImpl::HandleGetString(uint32 immediate_data_size,
8646 const void* cmd_data) {
8647 const gles2::cmds::GetString& c =
8648 *static_cast<const gles2::cmds::GetString*>(cmd_data);
8649 GLenum name = static_cast<GLenum>(c.name);
8650 if (!validators_->string_type.IsValid(name)) {
8651 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetString", name, "name");
8652 return error::kNoError;
8655 const char* str = nullptr;
8656 std::string extensions;
8657 switch (name) {
8658 case GL_VERSION:
8659 str = "OpenGL ES 2.0 Chromium";
8660 break;
8661 case GL_SHADING_LANGUAGE_VERSION:
8662 str = "OpenGL ES GLSL ES 1.0 Chromium";
8663 break;
8664 case GL_RENDERER:
8665 case GL_VENDOR:
8666 // Return the unmasked VENDOR/RENDERER string for WebGL contexts.
8667 // They are used by WEBGL_debug_renderer_info.
8668 if (!force_webgl_glsl_validation_)
8669 str = "Chromium";
8670 else
8671 str = reinterpret_cast<const char*>(glGetString(name));
8672 break;
8673 case GL_EXTENSIONS:
8675 // For WebGL contexts, strip out the OES derivatives and
8676 // EXT frag depth extensions if they have not been enabled.
8677 if (force_webgl_glsl_validation_) {
8678 extensions = feature_info_->extensions();
8679 if (!derivatives_explicitly_enabled_) {
8680 size_t offset = extensions.find(kOESDerivativeExtension);
8681 if (std::string::npos != offset) {
8682 extensions.replace(offset, arraysize(kOESDerivativeExtension),
8683 std::string());
8686 if (!frag_depth_explicitly_enabled_) {
8687 size_t offset = extensions.find(kEXTFragDepthExtension);
8688 if (std::string::npos != offset) {
8689 extensions.replace(offset, arraysize(kEXTFragDepthExtension),
8690 std::string());
8693 if (!draw_buffers_explicitly_enabled_) {
8694 size_t offset = extensions.find(kEXTDrawBuffersExtension);
8695 if (std::string::npos != offset) {
8696 extensions.replace(offset, arraysize(kEXTDrawBuffersExtension),
8697 std::string());
8700 if (!shader_texture_lod_explicitly_enabled_) {
8701 size_t offset = extensions.find(kEXTShaderTextureLodExtension);
8702 if (std::string::npos != offset) {
8703 extensions.replace(offset,
8704 arraysize(kEXTShaderTextureLodExtension),
8705 std::string());
8708 } else {
8709 extensions = feature_info_->extensions().c_str();
8711 if (supports_post_sub_buffer_)
8712 extensions += " GL_CHROMIUM_post_sub_buffer";
8713 str = extensions.c_str();
8715 break;
8716 default:
8717 str = reinterpret_cast<const char*>(glGetString(name));
8718 break;
8720 Bucket* bucket = CreateBucket(c.bucket_id);
8721 bucket->SetFromString(str);
8722 return error::kNoError;
8725 error::Error GLES2DecoderImpl::HandleBufferData(uint32 immediate_data_size,
8726 const void* cmd_data) {
8727 const gles2::cmds::BufferData& c =
8728 *static_cast<const gles2::cmds::BufferData*>(cmd_data);
8729 GLenum target = static_cast<GLenum>(c.target);
8730 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
8731 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
8732 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
8733 GLenum usage = static_cast<GLenum>(c.usage);
8734 const void* data = NULL;
8735 if (data_shm_id != 0 || data_shm_offset != 0) {
8736 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
8737 if (!data) {
8738 return error::kOutOfBounds;
8741 buffer_manager()->ValidateAndDoBufferData(&state_, target, size, data, usage);
8742 return error::kNoError;
8745 void GLES2DecoderImpl::DoBufferSubData(
8746 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
8747 // Just delegate it. Some validation is actually done before this.
8748 buffer_manager()->ValidateAndDoBufferSubData(
8749 &state_, target, offset, size, data);
8752 bool GLES2DecoderImpl::ClearLevel(
8753 Texture* texture,
8754 unsigned target,
8755 int level,
8756 unsigned internal_format,
8757 unsigned format,
8758 unsigned type,
8759 int width,
8760 int height,
8761 bool is_texture_immutable) {
8762 uint32 channels = GLES2Util::GetChannelsForFormat(format);
8763 if (feature_info_->feature_flags().angle_depth_texture &&
8764 (channels & GLES2Util::kDepth) != 0) {
8765 // It's a depth format and ANGLE doesn't allow texImage2D or texSubImage2D
8766 // on depth formats.
8767 GLuint fb = 0;
8768 glGenFramebuffersEXT(1, &fb);
8769 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb);
8771 bool have_stencil = (channels & GLES2Util::kStencil) != 0;
8772 GLenum attachment = have_stencil ? GL_DEPTH_STENCIL_ATTACHMENT :
8773 GL_DEPTH_ATTACHMENT;
8775 glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, attachment, target,
8776 texture->service_id(), level);
8777 // ANGLE promises a depth only attachment ok.
8778 if (glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT) !=
8779 GL_FRAMEBUFFER_COMPLETE) {
8780 return false;
8782 glClearStencil(0);
8783 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
8784 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
8785 glClearDepth(1.0f);
8786 state_.SetDeviceDepthMask(GL_TRUE);
8787 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
8788 glClear(GL_DEPTH_BUFFER_BIT | (have_stencil ? GL_STENCIL_BUFFER_BIT : 0));
8790 RestoreClearState();
8792 glDeleteFramebuffersEXT(1, &fb);
8793 Framebuffer* framebuffer =
8794 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
8795 GLuint fb_service_id =
8796 framebuffer ? framebuffer->service_id() : GetBackbufferServiceId();
8797 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb_service_id);
8798 return true;
8801 static const uint32 kMaxZeroSize = 1024 * 1024 * 4;
8803 uint32 size;
8804 uint32 padded_row_size;
8805 if (!GLES2Util::ComputeImageDataSizes(
8806 width, height, 1, format, type, state_.unpack_alignment, &size,
8807 NULL, &padded_row_size)) {
8808 return false;
8811 TRACE_EVENT1("gpu", "GLES2DecoderImpl::ClearLevel", "size", size);
8813 int tile_height;
8815 if (size > kMaxZeroSize) {
8816 if (kMaxZeroSize < padded_row_size) {
8817 // That'd be an awfully large texture.
8818 return false;
8820 // We should never have a large total size with a zero row size.
8821 DCHECK_GT(padded_row_size, 0U);
8822 tile_height = kMaxZeroSize / padded_row_size;
8823 if (!GLES2Util::ComputeImageDataSizes(
8824 width, tile_height, 1, format, type, state_.unpack_alignment, &size,
8825 NULL, NULL)) {
8826 return false;
8828 } else {
8829 tile_height = height;
8832 // Assumes the size has already been checked.
8833 scoped_ptr<char[]> zero(new char[size]);
8834 memset(zero.get(), 0, size);
8835 glBindTexture(texture->target(), texture->service_id());
8837 bool has_images = texture->HasImages();
8838 GLint y = 0;
8839 while (y < height) {
8840 GLint h = y + tile_height > height ? height - y : tile_height;
8841 if (is_texture_immutable || h != height || has_images) {
8842 glTexSubImage2D(target, level, 0, y, width, h, format, type, zero.get());
8843 } else {
8844 glTexImage2D(
8845 target, level, internal_format, width, h, 0, format, type,
8846 zero.get());
8848 y += tile_height;
8850 TextureRef* bound_texture =
8851 texture_manager()->GetTextureInfoForTarget(&state_, texture->target());
8852 glBindTexture(texture->target(),
8853 bound_texture ? bound_texture->service_id() : 0);
8854 return true;
8857 namespace {
8859 const int kS3TCBlockWidth = 4;
8860 const int kS3TCBlockHeight = 4;
8861 const int kS3TCDXT1BlockSize = 8;
8862 const int kS3TCDXT3AndDXT5BlockSize = 16;
8863 const int kEACAndETC2BlockSize = 4;
8865 bool IsValidDXTSize(GLint level, GLsizei size) {
8866 return (size == 1) ||
8867 (size == 2) || !(size % kS3TCBlockWidth);
8870 bool IsValidPVRTCSize(GLint level, GLsizei size) {
8871 return GLES2Util::IsPOT(size);
8874 } // anonymous namespace.
8876 bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
8877 const char* function_name, GLsizei width, GLsizei height, GLsizei depth,
8878 GLenum format, GLsizei size) {
8879 base::CheckedNumeric<GLsizei> bytes_required(0);
8881 switch (format) {
8882 case GL_ATC_RGB_AMD:
8883 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
8884 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
8885 case GL_ETC1_RGB8_OES:
8886 bytes_required =
8887 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
8888 bytes_required *=
8889 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
8890 bytes_required *= kS3TCDXT1BlockSize;
8891 break;
8892 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
8893 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
8894 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
8895 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
8896 bytes_required =
8897 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
8898 bytes_required *=
8899 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
8900 bytes_required *= kS3TCDXT3AndDXT5BlockSize;
8901 break;
8902 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
8903 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
8904 bytes_required = std::max(width, 8);
8905 bytes_required *= std::max(height, 8);
8906 bytes_required *= 4;
8907 bytes_required += 7;
8908 bytes_required /= 8;
8909 break;
8910 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
8911 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
8912 bytes_required = std::max(width, 16);
8913 bytes_required *= std::max(height, 8);
8914 bytes_required *= 2;
8915 bytes_required += 7;
8916 bytes_required /= 8;
8917 break;
8919 // ES3 formats.
8920 case GL_COMPRESSED_R11_EAC:
8921 case GL_COMPRESSED_SIGNED_R11_EAC:
8922 case GL_COMPRESSED_RGB8_ETC2:
8923 case GL_COMPRESSED_SRGB8_ETC2:
8924 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
8925 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
8926 bytes_required =
8927 (width + kEACAndETC2BlockSize - 1) / kEACAndETC2BlockSize;
8928 bytes_required *=
8929 (height + kEACAndETC2BlockSize - 1) / kEACAndETC2BlockSize;
8930 bytes_required *= 8;
8931 bytes_required *= depth;
8932 break;
8933 case GL_COMPRESSED_RG11_EAC:
8934 case GL_COMPRESSED_SIGNED_RG11_EAC:
8935 case GL_COMPRESSED_RGBA8_ETC2_EAC:
8936 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
8937 bytes_required =
8938 (width + kEACAndETC2BlockSize - 1) / kEACAndETC2BlockSize;
8939 bytes_required *=
8940 (height + kEACAndETC2BlockSize - 1) / kEACAndETC2BlockSize;
8941 bytes_required *= 16;
8942 bytes_required *= depth;
8943 break;
8944 default:
8945 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, format, "format");
8946 return false;
8949 if (!bytes_required.IsValid() || size != bytes_required.ValueOrDefault(0)) {
8950 LOCAL_SET_GL_ERROR(
8951 GL_INVALID_VALUE, function_name, "size is not correct for dimensions");
8952 return false;
8955 return true;
8958 bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
8959 const char* function_name, GLenum target, GLint level,
8960 GLsizei width, GLsizei height, GLsizei depth, GLenum format) {
8961 switch (format) {
8962 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
8963 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
8964 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
8965 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
8966 DCHECK_EQ(1, depth); // 2D formats.
8967 if (!IsValidDXTSize(level, width) || !IsValidDXTSize(level, height)) {
8968 LOCAL_SET_GL_ERROR(
8969 GL_INVALID_OPERATION, function_name,
8970 "width or height invalid for level");
8971 return false;
8973 return true;
8974 case GL_ATC_RGB_AMD:
8975 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
8976 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
8977 case GL_ETC1_RGB8_OES:
8978 DCHECK_EQ(1, depth); // 2D formats.
8979 if (width <= 0 || height <= 0) {
8980 LOCAL_SET_GL_ERROR(
8981 GL_INVALID_OPERATION, function_name,
8982 "width or height invalid for level");
8983 return false;
8985 return true;
8986 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
8987 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
8988 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
8989 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
8990 DCHECK_EQ(1, depth); // 2D formats.
8991 if (!IsValidPVRTCSize(level, width) ||
8992 !IsValidPVRTCSize(level, height)) {
8993 LOCAL_SET_GL_ERROR(
8994 GL_INVALID_OPERATION, function_name,
8995 "width or height invalid for level");
8996 return false;
8998 return true;
9000 // ES3 formats.
9001 case GL_COMPRESSED_R11_EAC:
9002 case GL_COMPRESSED_SIGNED_R11_EAC:
9003 case GL_COMPRESSED_RG11_EAC:
9004 case GL_COMPRESSED_SIGNED_RG11_EAC:
9005 case GL_COMPRESSED_RGB8_ETC2:
9006 case GL_COMPRESSED_SRGB8_ETC2:
9007 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9008 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9009 case GL_COMPRESSED_RGBA8_ETC2_EAC:
9010 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
9011 if (width <= 0 || height <= 0 || depth <= 0) {
9012 LOCAL_SET_GL_ERROR(
9013 GL_INVALID_OPERATION, function_name,
9014 "width, height, or depth invalid");
9015 return false;
9017 if (target == GL_TEXTURE_3D) {
9018 LOCAL_SET_GL_ERROR(
9019 GL_INVALID_OPERATION, function_name,
9020 "target invalid for format");
9021 return false;
9023 return true;
9024 default:
9025 return false;
9029 bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
9030 const char* function_name,
9031 GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
9032 GLsizei width, GLsizei height, GLsizei depth, GLenum format,
9033 Texture* texture) {
9034 if (xoffset < 0 || yoffset < 0 || zoffset < 0) {
9035 LOCAL_SET_GL_ERROR(
9036 GL_INVALID_VALUE, function_name, "x/y/z offset < 0");
9037 return false;
9040 switch (format) {
9041 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
9042 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
9043 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
9044 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
9045 const int kBlockWidth = 4;
9046 const int kBlockHeight = 4;
9047 if ((xoffset % kBlockWidth) || (yoffset % kBlockHeight)) {
9048 LOCAL_SET_GL_ERROR(
9049 GL_INVALID_OPERATION, function_name,
9050 "xoffset or yoffset not multiple of 4");
9051 return false;
9053 GLsizei tex_width = 0;
9054 GLsizei tex_height = 0;
9055 if (!texture->GetLevelSize(target, level,
9056 &tex_width, &tex_height, nullptr) ||
9057 width - xoffset > tex_width ||
9058 height - yoffset > tex_height) {
9059 LOCAL_SET_GL_ERROR(
9060 GL_INVALID_OPERATION, function_name, "dimensions out of range");
9061 return false;
9063 return ValidateCompressedTexDimensions(
9064 function_name, target, level, width, height, 1, format);
9066 case GL_ATC_RGB_AMD:
9067 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
9068 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD: {
9069 LOCAL_SET_GL_ERROR(
9070 GL_INVALID_OPERATION, function_name,
9071 "not supported for ATC textures");
9072 return false;
9074 case GL_ETC1_RGB8_OES: {
9075 LOCAL_SET_GL_ERROR(
9076 GL_INVALID_OPERATION, function_name,
9077 "not supported for ECT1_RGB8_OES textures");
9078 return false;
9080 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
9081 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
9082 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
9083 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
9084 if ((xoffset != 0) || (yoffset != 0)) {
9085 LOCAL_SET_GL_ERROR(
9086 GL_INVALID_OPERATION, function_name,
9087 "xoffset and yoffset must be zero");
9088 return false;
9090 GLsizei tex_width = 0;
9091 GLsizei tex_height = 0;
9092 if (!texture->GetLevelSize(target, level,
9093 &tex_width, &tex_height, nullptr) ||
9094 width != tex_width ||
9095 height != tex_height) {
9096 LOCAL_SET_GL_ERROR(
9097 GL_INVALID_OPERATION, function_name,
9098 "dimensions must match existing texture level dimensions");
9099 return false;
9101 return ValidateCompressedTexDimensions(
9102 function_name, target, level, width, height, 1, format);
9105 // ES3 formats
9106 case GL_COMPRESSED_R11_EAC:
9107 case GL_COMPRESSED_SIGNED_R11_EAC:
9108 case GL_COMPRESSED_RG11_EAC:
9109 case GL_COMPRESSED_SIGNED_RG11_EAC:
9110 case GL_COMPRESSED_RGB8_ETC2:
9111 case GL_COMPRESSED_SRGB8_ETC2:
9112 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9113 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9114 case GL_COMPRESSED_RGBA8_ETC2_EAC:
9115 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
9117 const int kBlockSize = 4;
9118 GLsizei tex_width, tex_height;
9119 if (target == GL_TEXTURE_3D ||
9120 !texture->GetLevelSize(target, level,
9121 &tex_width, &tex_height, nullptr) ||
9122 (xoffset % kBlockSize) || (yoffset % kBlockSize) ||
9123 ((width % kBlockSize) && xoffset + width != tex_width) ||
9124 ((height % kBlockSize) && yoffset + height != tex_height)) {
9125 LOCAL_SET_GL_ERROR(
9126 GL_INVALID_OPERATION, function_name,
9127 "dimensions must match existing texture level dimensions");
9128 return false;
9130 return true;
9132 default:
9133 return false;
9137 error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
9138 GLenum target,
9139 GLint level,
9140 GLenum internal_format,
9141 GLsizei width,
9142 GLsizei height,
9143 GLint border,
9144 GLsizei image_size,
9145 const void* data) {
9146 if (!validators_->texture_target.IsValid(target)) {
9147 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9148 "glCompressedTexImage2D", target, "target");
9149 return error::kNoError;
9151 if (!validators_->compressed_texture_format.IsValid(
9152 internal_format)) {
9153 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9154 "glCompressedTexImage2D", internal_format, "internal_format");
9155 return error::kNoError;
9157 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
9158 border != 0) {
9159 LOCAL_SET_GL_ERROR(
9160 GL_INVALID_VALUE,
9161 "glCompressedTexImage2D", "dimensions out of range");
9162 return error::kNoError;
9164 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9165 &state_, target);
9166 if (!texture_ref) {
9167 LOCAL_SET_GL_ERROR(
9168 GL_INVALID_VALUE,
9169 "glCompressedTexImage2D", "unknown texture target");
9170 return error::kNoError;
9172 Texture* texture = texture_ref->texture();
9173 if (texture->IsImmutable()) {
9174 LOCAL_SET_GL_ERROR(
9175 GL_INVALID_OPERATION,
9176 "glCompressedTexImage2D", "texture is immutable");
9177 return error::kNoError;
9180 if (!ValidateCompressedTexDimensions("glCompressedTexImage2D", target, level,
9181 width, height, 1, internal_format) ||
9182 !ValidateCompressedTexFuncData("glCompressedTexImage2D", width, height,
9183 1, internal_format, image_size)) {
9184 return error::kNoError;
9187 if (!EnsureGPUMemoryAvailable(image_size)) {
9188 LOCAL_SET_GL_ERROR(
9189 GL_OUT_OF_MEMORY, "glCompressedTexImage2D", "out of memory");
9190 return error::kNoError;
9193 if (texture->IsAttachedToFramebuffer()) {
9194 framebuffer_state_.clear_state_dirty = true;
9197 scoped_ptr<int8[]> zero;
9198 if (!data) {
9199 zero.reset(new int8[image_size]);
9200 memset(zero.get(), 0, image_size);
9201 data = zero.get();
9203 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage2D");
9204 glCompressedTexImage2D(
9205 target, level, internal_format, width, height, border, image_size, data);
9206 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedTexImage2D");
9207 if (error == GL_NO_ERROR) {
9208 texture_manager()->SetLevelInfo(
9209 texture_ref, target, level, internal_format,
9210 width, height, 1, border, 0, 0, true);
9213 // This may be a slow command. Exit command processing to allow for
9214 // context preemption and GPU watchdog checks.
9215 ExitCommandProcessingEarly();
9216 return error::kNoError;
9219 error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
9220 uint32 immediate_data_size,
9221 const void* cmd_data) {
9222 const gles2::cmds::CompressedTexImage2D& c =
9223 *static_cast<const gles2::cmds::CompressedTexImage2D*>(cmd_data);
9224 GLenum target = static_cast<GLenum>(c.target);
9225 GLint level = static_cast<GLint>(c.level);
9226 GLenum internal_format = static_cast<GLenum>(c.internalformat);
9227 GLsizei width = static_cast<GLsizei>(c.width);
9228 GLsizei height = static_cast<GLsizei>(c.height);
9229 GLint border = static_cast<GLint>(c.border);
9230 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
9231 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
9232 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
9233 const void* data = NULL;
9234 if (data_shm_id != 0 || data_shm_offset != 0) {
9235 data = GetSharedMemoryAs<const void*>(
9236 data_shm_id, data_shm_offset, image_size);
9237 if (!data) {
9238 return error::kOutOfBounds;
9241 return DoCompressedTexImage2D(
9242 target, level, internal_format, width, height, border, image_size, data);
9245 error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
9246 uint32 immediate_data_size,
9247 const void* cmd_data) {
9248 const gles2::cmds::CompressedTexImage2DBucket& c =
9249 *static_cast<const gles2::cmds::CompressedTexImage2DBucket*>(cmd_data);
9250 GLenum target = static_cast<GLenum>(c.target);
9251 GLint level = static_cast<GLint>(c.level);
9252 GLenum internal_format = static_cast<GLenum>(c.internalformat);
9253 GLsizei width = static_cast<GLsizei>(c.width);
9254 GLsizei height = static_cast<GLsizei>(c.height);
9255 GLint border = static_cast<GLint>(c.border);
9256 Bucket* bucket = GetBucket(c.bucket_id);
9257 if (!bucket) {
9258 return error::kInvalidArguments;
9260 uint32 data_size = bucket->size();
9261 GLsizei imageSize = data_size;
9262 const void* data = bucket->GetData(0, data_size);
9263 if (!data) {
9264 return error::kInvalidArguments;
9266 return DoCompressedTexImage2D(
9267 target, level, internal_format, width, height, border,
9268 imageSize, data);
9271 error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
9272 uint32 immediate_data_size,
9273 const void* cmd_data) {
9274 const gles2::cmds::CompressedTexSubImage2DBucket& c =
9275 *static_cast<const gles2::cmds::CompressedTexSubImage2DBucket*>(cmd_data);
9276 GLenum target = static_cast<GLenum>(c.target);
9277 GLint level = static_cast<GLint>(c.level);
9278 GLint xoffset = static_cast<GLint>(c.xoffset);
9279 GLint yoffset = static_cast<GLint>(c.yoffset);
9280 GLsizei width = static_cast<GLsizei>(c.width);
9281 GLsizei height = static_cast<GLsizei>(c.height);
9282 GLenum format = static_cast<GLenum>(c.format);
9283 Bucket* bucket = GetBucket(c.bucket_id);
9284 if (!bucket) {
9285 return error::kInvalidArguments;
9287 uint32 data_size = bucket->size();
9288 GLsizei imageSize = data_size;
9289 const void* data = bucket->GetData(0, data_size);
9290 if (!data) {
9291 return error::kInvalidArguments;
9293 if (!validators_->texture_target.IsValid(target)) {
9294 LOCAL_SET_GL_ERROR(
9295 GL_INVALID_ENUM, "glCompressedTexSubImage2D", "target");
9296 return error::kNoError;
9298 if (!validators_->compressed_texture_format.IsValid(format)) {
9299 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9300 "glCompressedTexSubImage2D", format, "format");
9301 return error::kNoError;
9303 if (width < 0) {
9304 LOCAL_SET_GL_ERROR(
9305 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "width < 0");
9306 return error::kNoError;
9308 if (height < 0) {
9309 LOCAL_SET_GL_ERROR(
9310 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "height < 0");
9311 return error::kNoError;
9313 if (imageSize < 0) {
9314 LOCAL_SET_GL_ERROR(
9315 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "imageSize < 0");
9316 return error::kNoError;
9318 DoCompressedTexSubImage2D(
9319 target, level, xoffset, yoffset, width, height, format, imageSize, data);
9320 return error::kNoError;
9323 error::Error GLES2DecoderImpl::DoCompressedTexImage3D(
9324 GLenum target,
9325 GLint level,
9326 GLenum internal_format,
9327 GLsizei width,
9328 GLsizei height,
9329 GLsizei depth,
9330 GLint border,
9331 GLsizei image_size,
9332 const void* data) {
9333 if (!validators_->texture_3_d_target.IsValid(target)) {
9334 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9335 "glCompressedTexImage3D", target, "target");
9336 return error::kNoError;
9338 if (!validators_->compressed_texture_format.IsValid(
9339 internal_format)) {
9340 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9341 "glCompressedTexImage3D", internal_format, "internal_format");
9342 return error::kNoError;
9344 if (!texture_manager()->ValidForTarget(target, level, width, height, depth) ||
9345 border != 0) {
9346 LOCAL_SET_GL_ERROR(
9347 GL_INVALID_VALUE,
9348 "glCompressedTexImage3D", "dimensions out of range");
9349 return error::kNoError;
9351 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9352 &state_, target);
9353 if (!texture_ref) {
9354 LOCAL_SET_GL_ERROR(
9355 GL_INVALID_VALUE,
9356 "glCompressedTexImage3D", "unknown texture target");
9357 return error::kNoError;
9359 Texture* texture = texture_ref->texture();
9360 if (texture->IsImmutable()) {
9361 LOCAL_SET_GL_ERROR(
9362 GL_INVALID_OPERATION,
9363 "glCompressedTexImage3D", "texture is immutable");
9364 return error::kNoError;
9367 if (!ValidateCompressedTexDimensions("glCompressedTexImage3D", target, level,
9368 width, height, depth, internal_format) ||
9369 !ValidateCompressedTexFuncData("glCompressedTexImage3D", width, height,
9370 depth, internal_format, image_size)) {
9371 return error::kNoError;
9374 if (!EnsureGPUMemoryAvailable(image_size)) {
9375 LOCAL_SET_GL_ERROR(
9376 GL_OUT_OF_MEMORY, "glCompressedTexImage3D", "out of memory");
9377 return error::kNoError;
9380 if (texture->IsAttachedToFramebuffer()) {
9381 framebuffer_state_.clear_state_dirty = true;
9384 scoped_ptr<int8[]> zero;
9385 if (!data) {
9386 zero.reset(new int8[image_size]);
9387 memset(zero.get(), 0, image_size);
9388 data = zero.get();
9390 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage3D");
9391 glCompressedTexImage3D(target, level, internal_format, width, height, depth,
9392 border, image_size, data);
9393 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedTexImage3D");
9394 if (error == GL_NO_ERROR) {
9395 texture_manager()->SetLevelInfo(
9396 texture_ref, target, level, internal_format,
9397 width, height, depth, border, 0, 0, true);
9400 // This may be a slow command. Exit command processing to allow for
9401 // context preemption and GPU watchdog checks.
9402 ExitCommandProcessingEarly();
9403 return error::kNoError;
9406 error::Error GLES2DecoderImpl::HandleCompressedTexImage3D(
9407 uint32 immediate_data_size, const void* cmd_data) {
9408 if (!unsafe_es3_apis_enabled())
9409 return error::kUnknownCommand;
9411 const gles2::cmds::CompressedTexImage3D& c =
9412 *static_cast<const gles2::cmds::CompressedTexImage3D*>(cmd_data);
9413 GLenum target = static_cast<GLenum>(c.target);
9414 GLint level = static_cast<GLint>(c.level);
9415 GLenum internal_format = static_cast<GLenum>(c.internalformat);
9416 GLsizei width = static_cast<GLsizei>(c.width);
9417 GLsizei height = static_cast<GLsizei>(c.height);
9418 GLsizei depth = static_cast<GLsizei>(c.depth);
9419 GLint border = static_cast<GLint>(c.border);
9420 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
9421 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
9422 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
9423 const void* data = NULL;
9424 if (data_shm_id != 0 || data_shm_offset != 0) {
9425 data = GetSharedMemoryAs<const void*>(
9426 data_shm_id, data_shm_offset, image_size);
9427 if (!data) {
9428 return error::kOutOfBounds;
9431 return DoCompressedTexImage3D(target, level, internal_format, width, height,
9432 depth, border, image_size, data);
9435 error::Error GLES2DecoderImpl::HandleCompressedTexImage3DBucket(
9436 uint32 immediate_data_size, const void* cmd_data) {
9437 if (!unsafe_es3_apis_enabled())
9438 return error::kUnknownCommand;
9440 const gles2::cmds::CompressedTexImage3DBucket& c =
9441 *static_cast<const gles2::cmds::CompressedTexImage3DBucket*>(cmd_data);
9442 GLenum target = static_cast<GLenum>(c.target);
9443 GLint level = static_cast<GLint>(c.level);
9444 GLenum internal_format = static_cast<GLenum>(c.internalformat);
9445 GLsizei width = static_cast<GLsizei>(c.width);
9446 GLsizei height = static_cast<GLsizei>(c.height);
9447 GLsizei depth = static_cast<GLsizei>(c.depth);
9448 GLint border = static_cast<GLint>(c.border);
9449 Bucket* bucket = GetBucket(c.bucket_id);
9450 if (!bucket) {
9451 return error::kInvalidArguments;
9453 uint32 data_size = bucket->size();
9454 GLsizei imageSize = data_size;
9455 const void* data = bucket->GetData(0, data_size);
9456 if (!data) {
9457 return error::kInvalidArguments;
9459 return DoCompressedTexImage3D(target, level, internal_format, width, height,
9460 depth, border, imageSize, data);
9463 void GLES2DecoderImpl::DoCompressedTexSubImage3D(
9464 GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
9465 GLsizei width, GLsizei height, GLsizei depth, GLenum format,
9466 GLsizei image_size, const void* data) {
9467 if (!validators_->texture_3_d_target.IsValid(target)) {
9468 LOCAL_SET_GL_ERROR(
9469 GL_INVALID_ENUM, "glCompressedTexSubImage3D", "target");
9470 return;
9472 if (!validators_->compressed_texture_format.IsValid(format)) {
9473 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9474 "glCompressedTexSubImage3D", format, "format");
9475 return;
9477 if (width < 0 || height < 0 || depth < 0) {
9478 LOCAL_SET_GL_ERROR(
9479 GL_INVALID_VALUE, "glCompressedTexSubImage3D", "size < 0");
9480 return;
9482 if (image_size < 0) {
9483 LOCAL_SET_GL_ERROR(
9484 GL_INVALID_VALUE, "glCompressedTexSubImage3D", "imageSize < 0");
9485 return;
9487 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9488 &state_, target);
9489 if (!texture_ref) {
9490 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCompressedTexSubImage3D",
9491 "unknown texture for target");
9492 return;
9494 Texture* texture = texture_ref->texture();
9495 GLenum type = 0, internal_format = 0;
9496 if (!texture->GetLevelType(target, level, &type, &internal_format)) {
9497 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCompressedTexSubImage3D",
9498 "level does not exist");
9499 return;
9501 if (internal_format != format) {
9502 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCompressedTexSubImage3D",
9503 "format does not match internal format");
9504 return;
9506 if (!texture->ValidForTexture(target, level, xoffset, yoffset, zoffset,
9507 width, height, depth, type)) {
9508 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCompressedTexSubImage3D",
9509 "bad dimensions");
9510 return;
9512 if (!ValidateCompressedTexFuncData("glCompressedTexSubImage3D",
9513 width, height, depth, format,
9514 image_size) ||
9515 !ValidateCompressedTexSubDimensions("glCompressedTexSubImage3D",
9516 target, level, xoffset, yoffset,
9517 zoffset, width, height, depth,
9518 format, texture)) {
9519 return;
9522 // Note: There is no need to deal with texture cleared tracking here
9523 // because the validation above means you can only get here if the level
9524 // is already a matching compressed format and in that case
9525 // CompressedTexImage3D already cleared the texture.
9526 glCompressedTexSubImage3D(
9527 target, level, xoffset, yoffset, zoffset, width, height, depth, format,
9528 image_size, data);
9530 // This may be a slow command. Exit command processing to allow for
9531 // context preemption and GPU watchdog checks.
9532 ExitCommandProcessingEarly();
9535 error::Error GLES2DecoderImpl::HandleCompressedTexSubImage3DBucket(
9536 uint32 immediate_data_size, const void* cmd_data) {
9537 if (!unsafe_es3_apis_enabled())
9538 return error::kUnknownCommand;
9539 const gles2::cmds::CompressedTexSubImage3DBucket& c =
9540 *static_cast<const gles2::cmds::CompressedTexSubImage3DBucket*>(cmd_data);
9541 GLenum target = static_cast<GLenum>(c.target);
9542 GLint level = static_cast<GLint>(c.level);
9543 GLint xoffset = static_cast<GLint>(c.xoffset);
9544 GLint yoffset = static_cast<GLint>(c.yoffset);
9545 GLint zoffset = static_cast<GLint>(c.zoffset);
9546 GLsizei width = static_cast<GLsizei>(c.width);
9547 GLsizei height = static_cast<GLsizei>(c.height);
9548 GLsizei depth = static_cast<GLsizei>(c.depth);
9549 GLenum format = static_cast<GLenum>(c.format);
9550 Bucket* bucket = GetBucket(c.bucket_id);
9551 if (!bucket) {
9552 return error::kInvalidArguments;
9554 uint32 data_size = bucket->size();
9555 GLsizei image_size = data_size;
9556 const void* data = bucket->GetData(0, data_size);
9557 if (!data) {
9558 return error::kInvalidArguments;
9560 DoCompressedTexSubImage3D(
9561 target, level, xoffset, yoffset, zoffset, width, height, depth, format,
9562 image_size, data);
9563 return error::kNoError;
9566 error::Error GLES2DecoderImpl::HandleTexImage2D(uint32 immediate_data_size,
9567 const void* cmd_data) {
9568 const gles2::cmds::TexImage2D& c =
9569 *static_cast<const gles2::cmds::TexImage2D*>(cmd_data);
9570 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage2D",
9571 "width", c.width, "height", c.height);
9572 // Set as failed for now, but if it successed, this will be set to not failed.
9573 texture_state_.tex_image_2d_failed = true;
9574 GLenum target = static_cast<GLenum>(c.target);
9575 GLint level = static_cast<GLint>(c.level);
9576 // TODO(kloveless): Change TexImage2D command to use unsigned integer
9577 // for internalformat.
9578 GLenum internal_format = static_cast<GLenum>(c.internalformat);
9579 GLsizei width = static_cast<GLsizei>(c.width);
9580 GLsizei height = static_cast<GLsizei>(c.height);
9581 GLint border = static_cast<GLint>(c.border);
9582 GLenum format = static_cast<GLenum>(c.format);
9583 GLenum type = static_cast<GLenum>(c.type);
9584 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
9585 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
9586 uint32 pixels_size;
9587 if (!GLES2Util::ComputeImageDataSizes(
9588 width, height, 1, format, type, state_.unpack_alignment, &pixels_size,
9589 NULL, NULL)) {
9590 return error::kOutOfBounds;
9592 const void* pixels = NULL;
9593 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
9594 pixels = GetSharedMemoryAs<const void*>(
9595 pixels_shm_id, pixels_shm_offset, pixels_size);
9596 if (!pixels) {
9597 return error::kOutOfBounds;
9601 // For testing only. Allows us to stress the ability to respond to OOM errors.
9602 if (workarounds().simulate_out_of_memory_on_large_textures &&
9603 (width * height >= 4096 * 4096)) {
9604 LOCAL_SET_GL_ERROR(
9605 GL_OUT_OF_MEMORY,
9606 "glTexImage2D", "synthetic out of memory");
9607 return error::kNoError;
9610 TextureManager::DoTextImage2DArguments args = {
9611 target, level, internal_format, width, height, border, format, type,
9612 pixels, pixels_size};
9613 texture_manager()->ValidateAndDoTexImage2D(
9614 &texture_state_, &state_, &framebuffer_state_, args);
9616 // This may be a slow command. Exit command processing to allow for
9617 // context preemption and GPU watchdog checks.
9618 ExitCommandProcessingEarly();
9619 return error::kNoError;
9622 error::Error GLES2DecoderImpl::HandleTexImage3D(uint32 immediate_data_size,
9623 const void* cmd_data) {
9624 // TODO(zmo): Unsafe ES3 API.
9625 if (!unsafe_es3_apis_enabled())
9626 return error::kUnknownCommand;
9628 const gles2::cmds::TexImage3D& c =
9629 *static_cast<const gles2::cmds::TexImage3D*>(cmd_data);
9630 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage3D",
9631 "widthXheight", c.width * c.height, "depth", c.depth);
9632 GLenum target = static_cast<GLenum>(c.target);
9633 GLint level = static_cast<GLint>(c.level);
9634 GLenum internal_format = static_cast<GLenum>(c.internalformat);
9635 GLsizei width = static_cast<GLsizei>(c.width);
9636 GLsizei height = static_cast<GLsizei>(c.height);
9637 GLsizei depth = static_cast<GLsizei>(c.depth);
9638 GLint border = static_cast<GLint>(c.border);
9639 GLenum format = static_cast<GLenum>(c.format);
9640 GLenum type = static_cast<GLenum>(c.type);
9641 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
9642 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
9643 uint32 pixels_size;
9644 if (!GLES2Util::ComputeImageDataSizes(
9645 width, height, depth, format, type, state_.unpack_alignment, &pixels_size,
9646 NULL, NULL)) {
9647 return error::kOutOfBounds;
9649 const void* pixels = NULL;
9650 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
9651 pixels = GetSharedMemoryAs<const void*>(
9652 pixels_shm_id, pixels_shm_offset, pixels_size);
9653 if (!pixels) {
9654 return error::kOutOfBounds;
9658 glTexImage3D(target, level, internal_format, width, height, depth, border,
9659 format, type, pixels);
9661 // This may be a slow command. Exit command processing to allow for
9662 // context preemption and GPU watchdog checks.
9663 ExitCommandProcessingEarly();
9664 return error::kNoError;
9667 void GLES2DecoderImpl::DoCompressedTexSubImage2D(
9668 GLenum target,
9669 GLint level,
9670 GLint xoffset,
9671 GLint yoffset,
9672 GLsizei width,
9673 GLsizei height,
9674 GLenum format,
9675 GLsizei image_size,
9676 const void * data) {
9677 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9678 &state_, target);
9679 if (!texture_ref) {
9680 LOCAL_SET_GL_ERROR(
9681 GL_INVALID_OPERATION,
9682 "glCompressedTexSubImage2D", "unknown texture for target");
9683 return;
9685 Texture* texture = texture_ref->texture();
9686 GLenum type = 0;
9687 GLenum internal_format = 0;
9688 if (!texture->GetLevelType(target, level, &type, &internal_format)) {
9689 LOCAL_SET_GL_ERROR(
9690 GL_INVALID_OPERATION,
9691 "glCompressedTexSubImage2D", "level does not exist.");
9692 return;
9694 if (internal_format != format) {
9695 LOCAL_SET_GL_ERROR(
9696 GL_INVALID_OPERATION,
9697 "glCompressedTexSubImage2D", "format does not match internal format.");
9698 return;
9700 if (!texture->ValidForTexture(target, level, xoffset, yoffset, 0, width,
9701 height, 1, type)) {
9702 LOCAL_SET_GL_ERROR(
9703 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "bad dimensions.");
9704 return;
9707 if (!ValidateCompressedTexFuncData("glCompressedTexSubImage2D",
9708 width, height, 1, format, image_size) ||
9709 !ValidateCompressedTexSubDimensions("glCompressedTexSubImage2D",
9710 target, level, xoffset, yoffset, 0,
9711 width, height, 1, format, texture)) {
9712 return;
9716 // Note: There is no need to deal with texture cleared tracking here
9717 // because the validation above means you can only get here if the level
9718 // is already a matching compressed format and in that case
9719 // CompressedTexImage2D already cleared the texture.
9720 glCompressedTexSubImage2D(
9721 target, level, xoffset, yoffset, width, height, format, image_size, data);
9723 // This may be a slow command. Exit command processing to allow for
9724 // context preemption and GPU watchdog checks.
9725 ExitCommandProcessingEarly();
9728 static void Clip(
9729 GLint start, GLint range, GLint sourceRange,
9730 GLint* out_start, GLint* out_range) {
9731 DCHECK(out_start);
9732 DCHECK(out_range);
9733 if (start < 0) {
9734 range += start;
9735 start = 0;
9737 GLint end = start + range;
9738 if (end > sourceRange) {
9739 range -= end - sourceRange;
9741 *out_start = start;
9742 *out_range = range;
9745 void GLES2DecoderImpl::DoCopyTexImage2D(
9746 GLenum target,
9747 GLint level,
9748 GLenum internal_format,
9749 GLint x,
9750 GLint y,
9751 GLsizei width,
9752 GLsizei height,
9753 GLint border) {
9754 DCHECK(!ShouldDeferReads());
9755 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9756 &state_, target);
9757 if (!texture_ref) {
9758 LOCAL_SET_GL_ERROR(
9759 GL_INVALID_OPERATION,
9760 "glCopyTexImage2D", "unknown texture for target");
9761 return;
9763 Texture* texture = texture_ref->texture();
9764 if (texture->IsImmutable()) {
9765 LOCAL_SET_GL_ERROR(
9766 GL_INVALID_OPERATION, "glCopyTexImage2D", "texture is immutable");
9767 return;
9769 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
9770 border != 0) {
9771 LOCAL_SET_GL_ERROR(
9772 GL_INVALID_VALUE, "glCopyTexImage2D", "dimensions out of range");
9773 return;
9775 if (!texture_manager()->ValidateFormatAndTypeCombination(
9776 state_.GetErrorState(), "glCopyTexImage2D", internal_format,
9777 GL_UNSIGNED_BYTE)) {
9778 return;
9781 // Check we have compatible formats.
9782 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
9783 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
9784 uint32 channels_needed = GLES2Util::GetChannelsForFormat(internal_format);
9786 if ((channels_needed & channels_exist) != channels_needed) {
9787 LOCAL_SET_GL_ERROR(
9788 GL_INVALID_OPERATION, "glCopyTexImage2D", "incompatible format");
9789 return;
9792 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
9793 LOCAL_SET_GL_ERROR(
9794 GL_INVALID_OPERATION,
9795 "glCopyTexImage2D", "can not be used with depth or stencil textures");
9796 return;
9799 uint32 estimated_size = 0;
9800 if (!GLES2Util::ComputeImageDataSizes(
9801 width, height, 1, internal_format, GL_UNSIGNED_BYTE,
9802 state_.unpack_alignment, &estimated_size, NULL, NULL)) {
9803 LOCAL_SET_GL_ERROR(
9804 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too large");
9805 return;
9808 if (!EnsureGPUMemoryAvailable(estimated_size)) {
9809 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexImage2D", "out of memory");
9810 return;
9813 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexImage2D")) {
9814 return;
9817 if (FormsTextureCopyingFeedbackLoop(texture_ref, level)) {
9818 LOCAL_SET_GL_ERROR(
9819 GL_INVALID_OPERATION,
9820 "glCopyTexImage2D", "source and destination textures are the same");
9821 return;
9824 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
9825 return;
9828 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTexImage2D");
9829 ScopedResolvedFrameBufferBinder binder(this, false, true);
9830 gfx::Size size = GetBoundReadFrameBufferSize();
9832 if (texture->IsAttachedToFramebuffer()) {
9833 framebuffer_state_.clear_state_dirty = true;
9836 // Clip to size to source dimensions
9837 GLint copyX = 0;
9838 GLint copyY = 0;
9839 GLint copyWidth = 0;
9840 GLint copyHeight = 0;
9841 Clip(x, width, size.width(), &copyX, &copyWidth);
9842 Clip(y, height, size.height(), &copyY, &copyHeight);
9844 if (copyX != x ||
9845 copyY != y ||
9846 copyWidth != width ||
9847 copyHeight != height) {
9848 // some part was clipped so clear the texture.
9849 if (!ClearLevel(texture, target, level, internal_format, internal_format,
9850 GL_UNSIGNED_BYTE, width, height, texture->IsImmutable())) {
9851 LOCAL_SET_GL_ERROR(
9852 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too big");
9853 return;
9855 if (copyHeight > 0 && copyWidth > 0) {
9856 GLint dx = copyX - x;
9857 GLint dy = copyY - y;
9858 GLint destX = dx;
9859 GLint destY = dy;
9860 ScopedModifyPixels modify(texture_ref);
9861 glCopyTexSubImage2D(target, level,
9862 destX, destY, copyX, copyY,
9863 copyWidth, copyHeight);
9865 } else {
9866 ScopedModifyPixels modify(texture_ref);
9867 glCopyTexImage2D(target, level, internal_format,
9868 copyX, copyY, copyWidth, copyHeight, border);
9870 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTexImage2D");
9871 if (error == GL_NO_ERROR) {
9872 texture_manager()->SetLevelInfo(
9873 texture_ref, target, level, internal_format, width, height, 1,
9874 border, internal_format, GL_UNSIGNED_BYTE, true);
9877 // This may be a slow command. Exit command processing to allow for
9878 // context preemption and GPU watchdog checks.
9879 ExitCommandProcessingEarly();
9882 void GLES2DecoderImpl::DoCopyTexSubImage2D(
9883 GLenum target,
9884 GLint level,
9885 GLint xoffset,
9886 GLint yoffset,
9887 GLint x,
9888 GLint y,
9889 GLsizei width,
9890 GLsizei height) {
9891 DCHECK(!ShouldDeferReads());
9892 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9893 &state_, target);
9894 if (!texture_ref) {
9895 LOCAL_SET_GL_ERROR(
9896 GL_INVALID_OPERATION,
9897 "glCopyTexSubImage2D", "unknown texture for target");
9898 return;
9900 Texture* texture = texture_ref->texture();
9901 GLenum type = 0;
9902 GLenum format = 0;
9903 if (!texture->GetLevelType(target, level, &type, &format) ||
9904 !texture->ValidForTexture(
9905 target, level, xoffset, yoffset, 0, width, height, 1, type)) {
9906 LOCAL_SET_GL_ERROR(
9907 GL_INVALID_VALUE, "glCopyTexSubImage2D", "bad dimensions.");
9908 return;
9910 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
9911 LOCAL_SET_GL_ERROR(
9912 GL_INVALID_OPERATION,
9913 "glCopyTexSubImage2D", "async upload pending for texture");
9914 return;
9917 // Check we have compatible formats.
9918 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
9919 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
9920 uint32 channels_needed = GLES2Util::GetChannelsForFormat(format);
9922 if (!channels_needed ||
9923 (channels_needed & channels_exist) != channels_needed) {
9924 LOCAL_SET_GL_ERROR(
9925 GL_INVALID_OPERATION, "glCopyTexSubImage2D", "incompatible format");
9926 return;
9929 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
9930 LOCAL_SET_GL_ERROR(
9931 GL_INVALID_OPERATION,
9932 "glCopySubImage2D", "can not be used with depth or stencil textures");
9933 return;
9936 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexSubImage2D")) {
9937 return;
9940 if (FormsTextureCopyingFeedbackLoop(texture_ref, level)) {
9941 LOCAL_SET_GL_ERROR(
9942 GL_INVALID_OPERATION,
9943 "glCopyTexSubImage2D", "source and destination textures are the same");
9944 return;
9947 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
9948 return;
9951 ScopedResolvedFrameBufferBinder binder(this, false, true);
9952 gfx::Size size = GetBoundReadFrameBufferSize();
9953 GLint copyX = 0;
9954 GLint copyY = 0;
9955 GLint copyWidth = 0;
9956 GLint copyHeight = 0;
9957 Clip(x, width, size.width(), &copyX, &copyWidth);
9958 Clip(y, height, size.height(), &copyY, &copyHeight);
9960 if (xoffset != 0 || yoffset != 0 || width != size.width() ||
9961 height != size.height()) {
9962 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target,
9963 level)) {
9964 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexSubImage2D",
9965 "dimensions too big");
9966 return;
9968 } else {
9969 // Write all pixels in below.
9970 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
9973 if (copyX != x ||
9974 copyY != y ||
9975 copyWidth != width ||
9976 copyHeight != height) {
9977 // some part was clipped so clear the sub rect.
9978 uint32 pixels_size = 0;
9979 if (!GLES2Util::ComputeImageDataSizes(
9980 width, height, 1, format, type, state_.unpack_alignment, &pixels_size,
9981 NULL, NULL)) {
9982 LOCAL_SET_GL_ERROR(
9983 GL_INVALID_VALUE, "glCopyTexSubImage2D", "dimensions too large");
9984 return;
9986 scoped_ptr<char[]> zero(new char[pixels_size]);
9987 memset(zero.get(), 0, pixels_size);
9988 ScopedModifyPixels modify(texture_ref);
9989 glTexSubImage2D(
9990 target, level, xoffset, yoffset, width, height,
9991 format, type, zero.get());
9994 if (copyHeight > 0 && copyWidth > 0) {
9995 GLint dx = copyX - x;
9996 GLint dy = copyY - y;
9997 GLint destX = xoffset + dx;
9998 GLint destY = yoffset + dy;
9999 ScopedModifyPixels modify(texture_ref);
10000 glCopyTexSubImage2D(target, level,
10001 destX, destY, copyX, copyY,
10002 copyWidth, copyHeight);
10005 // This may be a slow command. Exit command processing to allow for
10006 // context preemption and GPU watchdog checks.
10007 ExitCommandProcessingEarly();
10010 bool GLES2DecoderImpl::ValidateTexSubImage2D(
10011 error::Error* error,
10012 const char* function_name,
10013 GLenum target,
10014 GLint level,
10015 GLint xoffset,
10016 GLint yoffset,
10017 GLsizei width,
10018 GLsizei height,
10019 GLenum format,
10020 GLenum type,
10021 const void * data) {
10022 (*error) = error::kNoError;
10023 if (!validators_->texture_target.IsValid(target)) {
10024 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
10025 return false;
10027 if (width < 0) {
10028 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "width < 0");
10029 return false;
10031 if (height < 0) {
10032 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "height < 0");
10033 return false;
10035 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10036 &state_, target);
10037 if (!texture_ref) {
10038 LOCAL_SET_GL_ERROR(
10039 GL_INVALID_OPERATION,
10040 function_name, "unknown texture for target");
10041 return false;
10043 Texture* texture = texture_ref->texture();
10044 GLenum current_type = 0;
10045 GLenum internal_format = 0;
10046 if (!texture->GetLevelType(target, level, &current_type, &internal_format)) {
10047 LOCAL_SET_GL_ERROR(
10048 GL_INVALID_OPERATION, function_name, "level does not exist.");
10049 return false;
10051 if (!texture_manager()->ValidateTextureParameters(state_.GetErrorState(),
10052 function_name, format, type, internal_format, level)) {
10053 return false;
10055 if (type != current_type) {
10056 LOCAL_SET_GL_ERROR(
10057 GL_INVALID_OPERATION,
10058 function_name, "type does not match type of texture.");
10059 return false;
10061 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
10062 LOCAL_SET_GL_ERROR(
10063 GL_INVALID_OPERATION,
10064 function_name, "async upload pending for texture");
10065 return false;
10067 if (!texture->ValidForTexture(
10068 target, level, xoffset, yoffset, 0, width, height, 1, type)) {
10069 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "bad dimensions.");
10070 return false;
10072 if ((GLES2Util::GetChannelsForFormat(format) &
10073 (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
10074 LOCAL_SET_GL_ERROR(
10075 GL_INVALID_OPERATION,
10076 function_name, "can not supply data for depth or stencil textures");
10077 return false;
10079 if (data == NULL) {
10080 (*error) = error::kOutOfBounds;
10081 return false;
10083 return true;
10086 error::Error GLES2DecoderImpl::DoTexSubImage2D(
10087 GLenum target,
10088 GLint level,
10089 GLint xoffset,
10090 GLint yoffset,
10091 GLsizei width,
10092 GLsizei height,
10093 GLenum format,
10094 GLenum type,
10095 const void * data) {
10096 error::Error error = error::kNoError;
10097 if (!ValidateTexSubImage2D(&error, "glTexSubImage2D", target, level,
10098 xoffset, yoffset, width, height, format, type, data)) {
10099 return error;
10101 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10102 &state_, target);
10103 Texture* texture = texture_ref->texture();
10104 GLsizei tex_width = 0;
10105 GLsizei tex_height = 0;
10106 bool ok = texture->GetLevelSize(
10107 target, level, &tex_width, &tex_height, nullptr);
10108 DCHECK(ok);
10109 if (xoffset != 0 || yoffset != 0 ||
10110 width != tex_width || height != tex_height) {
10111 if (!texture_manager()->ClearTextureLevel(this, texture_ref,
10112 target, level)) {
10113 LOCAL_SET_GL_ERROR(
10114 GL_OUT_OF_MEMORY, "glTexSubImage2D", "dimensions too big");
10115 return error::kNoError;
10117 ScopedTextureUploadTimer timer(&texture_state_);
10118 glTexSubImage2D(
10119 target, level, xoffset, yoffset, width, height, format, type, data);
10120 return error::kNoError;
10123 if (!texture_state_.texsubimage2d_faster_than_teximage2d &&
10124 !texture->IsImmutable() &&
10125 !texture->HasImages()) {
10126 ScopedTextureUploadTimer timer(&texture_state_);
10127 GLenum internal_format;
10128 GLenum tex_type;
10129 texture->GetLevelType(target, level, &tex_type, &internal_format);
10130 // NOTE: In OpenGL ES 2.0 border is always zero. If that changes we'll need
10131 // to look it up.
10132 glTexImage2D(
10133 target, level, internal_format, width, height, 0, format, type, data);
10134 } else {
10135 ScopedTextureUploadTimer timer(&texture_state_);
10136 glTexSubImage2D(
10137 target, level, xoffset, yoffset, width, height, format, type, data);
10139 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
10141 // This may be a slow command. Exit command processing to allow for
10142 // context preemption and GPU watchdog checks.
10143 ExitCommandProcessingEarly();
10144 return error::kNoError;
10147 error::Error GLES2DecoderImpl::HandleTexSubImage2D(uint32 immediate_data_size,
10148 const void* cmd_data) {
10149 const gles2::cmds::TexSubImage2D& c =
10150 *static_cast<const gles2::cmds::TexSubImage2D*>(cmd_data);
10151 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage2D",
10152 "width", c.width, "height", c.height);
10153 GLboolean internal = static_cast<GLboolean>(c.internal);
10154 if (internal == GL_TRUE && texture_state_.tex_image_2d_failed)
10155 return error::kNoError;
10157 GLenum target = static_cast<GLenum>(c.target);
10158 GLint level = static_cast<GLint>(c.level);
10159 GLint xoffset = static_cast<GLint>(c.xoffset);
10160 GLint yoffset = static_cast<GLint>(c.yoffset);
10161 GLsizei width = static_cast<GLsizei>(c.width);
10162 GLsizei height = static_cast<GLsizei>(c.height);
10163 GLenum format = static_cast<GLenum>(c.format);
10164 GLenum type = static_cast<GLenum>(c.type);
10165 uint32 data_size;
10166 if (!GLES2Util::ComputeImageDataSizes(
10167 width, height, 1, format, type, state_.unpack_alignment, &data_size,
10168 NULL, NULL)) {
10169 return error::kOutOfBounds;
10171 const void* pixels = GetSharedMemoryAs<const void*>(
10172 c.pixels_shm_id, c.pixels_shm_offset, data_size);
10173 return DoTexSubImage2D(
10174 target, level, xoffset, yoffset, width, height, format, type, pixels);
10177 error::Error GLES2DecoderImpl::HandleTexSubImage3D(uint32 immediate_data_size,
10178 const void* cmd_data) {
10179 // TODO(zmo): Unsafe ES3 API.
10180 if (!unsafe_es3_apis_enabled())
10181 return error::kUnknownCommand;
10183 const gles2::cmds::TexSubImage3D& c =
10184 *static_cast<const gles2::cmds::TexSubImage3D*>(cmd_data);
10185 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage3D",
10186 "widthXheight", c.width * c.height, "depth", c.depth);
10187 GLenum target = static_cast<GLenum>(c.target);
10188 GLint level = static_cast<GLint>(c.level);
10189 GLint xoffset = static_cast<GLint>(c.xoffset);
10190 GLint yoffset = static_cast<GLint>(c.yoffset);
10191 GLint zoffset = static_cast<GLint>(c.zoffset);
10192 GLsizei width = static_cast<GLsizei>(c.width);
10193 GLsizei height = static_cast<GLsizei>(c.height);
10194 GLsizei depth = static_cast<GLsizei>(c.depth);
10195 GLenum format = static_cast<GLenum>(c.format);
10196 GLenum type = static_cast<GLenum>(c.type);
10197 uint32 data_size;
10198 if (!GLES2Util::ComputeImageDataSizes(
10199 width, height, depth, format, type, state_.unpack_alignment, &data_size,
10200 NULL, NULL)) {
10201 return error::kOutOfBounds;
10203 const void* pixels = GetSharedMemoryAs<const void*>(
10204 c.pixels_shm_id, c.pixels_shm_offset, data_size);
10205 glTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height,
10206 depth, format, type, pixels);
10207 return error::kNoError;
10210 error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
10211 uint32 immediate_data_size,
10212 const void* cmd_data) {
10213 const gles2::cmds::GetVertexAttribPointerv& c =
10214 *static_cast<const gles2::cmds::GetVertexAttribPointerv*>(cmd_data);
10215 GLuint index = static_cast<GLuint>(c.index);
10216 GLenum pname = static_cast<GLenum>(c.pname);
10217 typedef cmds::GetVertexAttribPointerv::Result Result;
10218 Result* result = GetSharedMemoryAs<Result*>(
10219 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
10220 if (!result) {
10221 return error::kOutOfBounds;
10223 // Check that the client initialized the result.
10224 if (result->size != 0) {
10225 return error::kInvalidArguments;
10227 if (!validators_->vertex_pointer.IsValid(pname)) {
10228 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10229 "glGetVertexAttribPointerv", pname, "pname");
10230 return error::kNoError;
10232 if (index >= group_->max_vertex_attribs()) {
10233 LOCAL_SET_GL_ERROR(
10234 GL_INVALID_VALUE, "glGetVertexAttribPointerv", "index out of range.");
10235 return error::kNoError;
10237 result->SetNumResults(1);
10238 *result->GetData() =
10239 state_.vertex_attrib_manager->GetVertexAttrib(index)->offset();
10240 return error::kNoError;
10243 template <class T>
10244 bool GLES2DecoderImpl::GetUniformSetup(GLuint program_id,
10245 GLint fake_location,
10246 uint32 shm_id,
10247 uint32 shm_offset,
10248 error::Error* error,
10249 GLint* real_location,
10250 GLuint* service_id,
10251 SizedResult<T>** result_pointer,
10252 GLenum* result_type,
10253 GLsizei* result_size) {
10254 DCHECK(error);
10255 DCHECK(service_id);
10256 DCHECK(result_pointer);
10257 DCHECK(result_type);
10258 DCHECK(result_size);
10259 DCHECK(real_location);
10260 *error = error::kNoError;
10261 // Make sure we have enough room for the result on failure.
10262 SizedResult<T>* result;
10263 result = GetSharedMemoryAs<SizedResult<T>*>(
10264 shm_id, shm_offset, SizedResult<T>::ComputeSize(0));
10265 if (!result) {
10266 *error = error::kOutOfBounds;
10267 return false;
10269 *result_pointer = result;
10270 // Set the result size to 0 so the client does not have to check for success.
10271 result->SetNumResults(0);
10272 Program* program = GetProgramInfoNotShader(program_id, "glGetUniform");
10273 if (!program) {
10274 return false;
10276 if (!program->IsValid()) {
10277 // Program was not linked successfully. (ie, glLinkProgram)
10278 LOCAL_SET_GL_ERROR(
10279 GL_INVALID_OPERATION, "glGetUniform", "program not linked");
10280 return false;
10282 *service_id = program->service_id();
10283 GLint array_index = -1;
10284 const Program::UniformInfo* uniform_info =
10285 program->GetUniformInfoByFakeLocation(
10286 fake_location, real_location, &array_index);
10287 if (!uniform_info) {
10288 // No such location.
10289 LOCAL_SET_GL_ERROR(
10290 GL_INVALID_OPERATION, "glGetUniform", "unknown location");
10291 return false;
10293 GLenum type = uniform_info->type;
10294 uint32 num_elements = GLES2Util::GetElementCountForUniformType(type);
10295 if (num_elements == 0) {
10296 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glGetUniform", "unknown type");
10297 return false;
10299 result = GetSharedMemoryAs<SizedResult<T>*>(
10300 shm_id, shm_offset, SizedResult<T>::ComputeSize(num_elements));
10301 if (!result) {
10302 *error = error::kOutOfBounds;
10303 return false;
10305 result->SetNumResults(num_elements);
10306 *result_size = num_elements * sizeof(T);
10307 *result_type = type;
10308 return true;
10311 error::Error GLES2DecoderImpl::HandleGetUniformiv(uint32 immediate_data_size,
10312 const void* cmd_data) {
10313 const gles2::cmds::GetUniformiv& c =
10314 *static_cast<const gles2::cmds::GetUniformiv*>(cmd_data);
10315 GLuint program = c.program;
10316 GLint fake_location = c.location;
10317 GLuint service_id;
10318 GLenum result_type;
10319 GLsizei result_size;
10320 GLint real_location = -1;
10321 Error error;
10322 cmds::GetUniformiv::Result* result;
10323 if (GetUniformSetup<GLint>(program, fake_location, c.params_shm_id,
10324 c.params_shm_offset, &error, &real_location,
10325 &service_id, &result, &result_type,
10326 &result_size)) {
10327 glGetUniformiv(
10328 service_id, real_location, result->GetData());
10330 return error;
10333 error::Error GLES2DecoderImpl::HandleGetUniformuiv(uint32 immediate_data_size,
10334 const void* cmd_data) {
10335 if (!unsafe_es3_apis_enabled())
10336 return error::kUnknownCommand;
10338 const gles2::cmds::GetUniformuiv& c =
10339 *static_cast<const gles2::cmds::GetUniformuiv*>(cmd_data);
10340 GLuint program = c.program;
10341 GLint fake_location = c.location;
10342 GLuint service_id;
10343 GLenum result_type;
10344 GLsizei result_size;
10345 GLint real_location = -1;
10346 Error error;
10347 cmds::GetUniformuiv::Result* result;
10348 if (GetUniformSetup<GLuint>(program, fake_location, c.params_shm_id,
10349 c.params_shm_offset, &error, &real_location,
10350 &service_id, &result, &result_type,
10351 &result_size)) {
10352 glGetUniformuiv(
10353 service_id, real_location, result->GetData());
10355 return error;
10358 error::Error GLES2DecoderImpl::HandleGetUniformfv(uint32 immediate_data_size,
10359 const void* cmd_data) {
10360 const gles2::cmds::GetUniformfv& c =
10361 *static_cast<const gles2::cmds::GetUniformfv*>(cmd_data);
10362 GLuint program = c.program;
10363 GLint fake_location = c.location;
10364 GLuint service_id;
10365 GLint real_location = -1;
10366 Error error;
10367 cmds::GetUniformfv::Result* result;
10368 GLenum result_type;
10369 GLsizei result_size;
10370 if (GetUniformSetup<GLfloat>(program, fake_location, c.params_shm_id,
10371 c.params_shm_offset, &error, &real_location,
10372 &service_id, &result, &result_type,
10373 &result_size)) {
10374 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
10375 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
10376 GLsizei num_values = result_size / sizeof(GLfloat);
10377 scoped_ptr<GLint[]> temp(new GLint[num_values]);
10378 glGetUniformiv(service_id, real_location, temp.get());
10379 GLfloat* dst = result->GetData();
10380 for (GLsizei ii = 0; ii < num_values; ++ii) {
10381 dst[ii] = (temp[ii] != 0);
10383 } else {
10384 glGetUniformfv(service_id, real_location, result->GetData());
10387 return error;
10390 error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
10391 uint32 immediate_data_size,
10392 const void* cmd_data) {
10393 const gles2::cmds::GetShaderPrecisionFormat& c =
10394 *static_cast<const gles2::cmds::GetShaderPrecisionFormat*>(cmd_data);
10395 GLenum shader_type = static_cast<GLenum>(c.shadertype);
10396 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
10397 typedef cmds::GetShaderPrecisionFormat::Result Result;
10398 Result* result = GetSharedMemoryAs<Result*>(
10399 c.result_shm_id, c.result_shm_offset, sizeof(*result));
10400 if (!result) {
10401 return error::kOutOfBounds;
10403 // Check that the client initialized the result.
10404 if (result->success != 0) {
10405 return error::kInvalidArguments;
10407 if (!validators_->shader_type.IsValid(shader_type)) {
10408 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10409 "glGetShaderPrecisionFormat", shader_type, "shader_type");
10410 return error::kNoError;
10412 if (!validators_->shader_precision.IsValid(precision_type)) {
10413 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10414 "glGetShaderPrecisionFormat", precision_type, "precision_type");
10415 return error::kNoError;
10418 result->success = 1; // true
10420 GLint range[2] = { 0, 0 };
10421 GLint precision = 0;
10422 GetShaderPrecisionFormatImpl(shader_type, precision_type, range, &precision);
10424 result->min_range = range[0];
10425 result->max_range = range[1];
10426 result->precision = precision;
10428 return error::kNoError;
10431 error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
10432 uint32 immediate_data_size,
10433 const void* cmd_data) {
10434 const gles2::cmds::GetAttachedShaders& c =
10435 *static_cast<const gles2::cmds::GetAttachedShaders*>(cmd_data);
10436 uint32 result_size = c.result_size;
10437 GLuint program_id = static_cast<GLuint>(c.program);
10438 Program* program = GetProgramInfoNotShader(
10439 program_id, "glGetAttachedShaders");
10440 if (!program) {
10441 return error::kNoError;
10443 typedef cmds::GetAttachedShaders::Result Result;
10444 uint32 max_count = Result::ComputeMaxResults(result_size);
10445 Result* result = GetSharedMemoryAs<Result*>(
10446 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
10447 if (!result) {
10448 return error::kOutOfBounds;
10450 // Check that the client initialized the result.
10451 if (result->size != 0) {
10452 return error::kInvalidArguments;
10454 GLsizei count = 0;
10455 glGetAttachedShaders(
10456 program->service_id(), max_count, &count, result->GetData());
10457 for (GLsizei ii = 0; ii < count; ++ii) {
10458 if (!shader_manager()->GetClientId(result->GetData()[ii],
10459 &result->GetData()[ii])) {
10460 NOTREACHED();
10461 return error::kGenericError;
10464 result->SetNumResults(count);
10465 return error::kNoError;
10468 error::Error GLES2DecoderImpl::HandleGetActiveUniform(
10469 uint32 immediate_data_size,
10470 const void* cmd_data) {
10471 const gles2::cmds::GetActiveUniform& c =
10472 *static_cast<const gles2::cmds::GetActiveUniform*>(cmd_data);
10473 GLuint program_id = c.program;
10474 GLuint index = c.index;
10475 uint32 name_bucket_id = c.name_bucket_id;
10476 typedef cmds::GetActiveUniform::Result Result;
10477 Result* result = GetSharedMemoryAs<Result*>(
10478 c.result_shm_id, c.result_shm_offset, sizeof(*result));
10479 if (!result) {
10480 return error::kOutOfBounds;
10482 // Check that the client initialized the result.
10483 if (result->success != 0) {
10484 return error::kInvalidArguments;
10486 Program* program = GetProgramInfoNotShader(
10487 program_id, "glGetActiveUniform");
10488 if (!program) {
10489 return error::kNoError;
10491 const Program::UniformInfo* uniform_info =
10492 program->GetUniformInfo(index);
10493 if (!uniform_info) {
10494 LOCAL_SET_GL_ERROR(
10495 GL_INVALID_VALUE, "glGetActiveUniform", "index out of range");
10496 return error::kNoError;
10498 result->success = 1; // true.
10499 result->size = uniform_info->size;
10500 result->type = uniform_info->type;
10501 Bucket* bucket = CreateBucket(name_bucket_id);
10502 bucket->SetFromString(uniform_info->name.c_str());
10503 return error::kNoError;
10506 error::Error GLES2DecoderImpl::HandleGetActiveUniformBlockiv(
10507 uint32 immediate_data_size, const void* cmd_data) {
10508 if (!unsafe_es3_apis_enabled())
10509 return error::kUnknownCommand;
10510 const gles2::cmds::GetActiveUniformBlockiv& c =
10511 *static_cast<const gles2::cmds::GetActiveUniformBlockiv*>(cmd_data);
10512 GLuint program_id = c.program;
10513 GLuint index = static_cast<GLuint>(c.index);
10514 GLenum pname = static_cast<GLenum>(c.pname);
10515 Program* program = GetProgramInfoNotShader(
10516 program_id, "glGetActiveUniformBlockiv");
10517 if (!program) {
10518 return error::kNoError;
10520 GLuint service_id = program->service_id();
10521 GLint link_status = GL_FALSE;
10522 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
10523 if (link_status != GL_TRUE) {
10524 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10525 "glGetActiveActiveUniformBlockiv", "program not linked");
10526 return error::kNoError;
10528 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetActiveUniformBlockiv");
10529 GLsizei num_values = 1;
10530 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES) {
10531 GLint num = 0;
10532 glGetActiveUniformBlockiv(
10533 service_id, index, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &num);
10534 GLenum error = glGetError();
10535 if (error != GL_NO_ERROR) {
10536 // Assume this will the same error if calling with pname.
10537 LOCAL_SET_GL_ERROR(error, "GetActiveUniformBlockiv", "");
10538 return error::kNoError;
10540 num_values = static_cast<GLsizei>(num);
10542 typedef cmds::GetActiveUniformBlockiv::Result Result;
10543 Result* result = GetSharedMemoryAs<Result*>(
10544 c.params_shm_id, c.params_shm_offset, Result::ComputeSize(num_values));
10545 GLint* params = result ? result->GetData() : NULL;
10546 if (params == NULL) {
10547 return error::kOutOfBounds;
10549 // Check that the client initialized the result.
10550 if (result->size != 0) {
10551 return error::kInvalidArguments;
10553 glGetActiveUniformBlockiv(service_id, index, pname, params);
10554 GLenum error = glGetError();
10555 if (error == GL_NO_ERROR) {
10556 result->SetNumResults(num_values);
10557 } else {
10558 LOCAL_SET_GL_ERROR(error, "GetActiveUniformBlockiv", "");
10560 return error::kNoError;
10563 error::Error GLES2DecoderImpl::HandleGetActiveUniformBlockName(
10564 uint32 immediate_data_size, const void* cmd_data) {
10565 if (!unsafe_es3_apis_enabled())
10566 return error::kUnknownCommand;
10567 const gles2::cmds::GetActiveUniformBlockName& c =
10568 *static_cast<const gles2::cmds::GetActiveUniformBlockName*>(cmd_data);
10569 GLuint program_id = c.program;
10570 GLuint index = c.index;
10571 uint32 name_bucket_id = c.name_bucket_id;
10572 typedef cmds::GetActiveUniformBlockName::Result Result;
10573 Result* result = GetSharedMemoryAs<Result*>(
10574 c.result_shm_id, c.result_shm_offset, sizeof(*result));
10575 if (!result) {
10576 return error::kOutOfBounds;
10578 // Check that the client initialized the result.
10579 if (*result != 0) {
10580 return error::kInvalidArguments;
10582 Program* program = GetProgramInfoNotShader(
10583 program_id, "glGetActiveUniformBlockName");
10584 if (!program) {
10585 return error::kNoError;
10587 GLuint service_id = program->service_id();
10588 GLint link_status = GL_FALSE;
10589 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
10590 if (link_status != GL_TRUE) {
10591 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10592 "glGetActiveActiveUniformBlockName", "program not linked");
10593 return error::kNoError;
10595 GLint max_length = 0;
10596 glGetProgramiv(
10597 service_id, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &max_length);
10598 // Increase one so &buffer[0] is always valid.
10599 GLsizei buf_size = static_cast<GLsizei>(max_length) + 1;
10600 std::vector<char> buffer(buf_size);
10601 GLsizei length = 0;
10602 glGetActiveUniformBlockName(
10603 service_id, index, buf_size, &length, &buffer[0]);
10604 if (length == 0) {
10605 *result = 0;
10606 return error::kNoError;
10608 *result = 1;
10609 Bucket* bucket = CreateBucket(name_bucket_id);
10610 DCHECK_GT(buf_size, length);
10611 DCHECK_EQ(0, buffer[length]);
10612 bucket->SetFromString(&buffer[0]);
10613 return error::kNoError;
10616 error::Error GLES2DecoderImpl::HandleGetActiveUniformsiv(
10617 uint32 immediate_data_size, const void* cmd_data) {
10618 if (!unsafe_es3_apis_enabled())
10619 return error::kUnknownCommand;
10620 const gles2::cmds::GetActiveUniformsiv& c =
10621 *static_cast<const gles2::cmds::GetActiveUniformsiv*>(cmd_data);
10622 GLuint program_id = c.program;
10623 GLenum pname = static_cast<GLenum>(c.pname);
10624 Bucket* bucket = GetBucket(c.indices_bucket_id);
10625 if (!bucket) {
10626 return error::kInvalidArguments;
10628 GLsizei count = static_cast<GLsizei>(bucket->size() / sizeof(GLuint));
10629 const GLuint* indices = bucket->GetDataAs<const GLuint*>(0, bucket->size());
10630 typedef cmds::GetActiveUniformsiv::Result Result;
10631 Result* result = GetSharedMemoryAs<Result*>(
10632 c.params_shm_id, c.params_shm_offset, Result::ComputeSize(count));
10633 GLint* params = result ? result->GetData() : NULL;
10634 if (params == NULL) {
10635 return error::kOutOfBounds;
10637 // Check that the client initialized the result.
10638 if (result->size != 0) {
10639 return error::kInvalidArguments;
10641 Program* program = GetProgramInfoNotShader(
10642 program_id, "glGetActiveUniformsiv");
10643 if (!program) {
10644 return error::kNoError;
10646 GLuint service_id = program->service_id();
10647 GLint link_status = GL_FALSE;
10648 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
10649 if (link_status != GL_TRUE) {
10650 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10651 "glGetActiveUniformsiv", "program not linked");
10652 return error::kNoError;
10654 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetActiveUniformsiv");
10655 glGetActiveUniformsiv(service_id, count, indices, pname, params);
10656 GLenum error = glGetError();
10657 if (error == GL_NO_ERROR) {
10658 result->SetNumResults(count);
10659 } else {
10660 LOCAL_SET_GL_ERROR(error, "GetActiveUniformsiv", "");
10662 return error::kNoError;
10665 error::Error GLES2DecoderImpl::HandleGetActiveAttrib(uint32 immediate_data_size,
10666 const void* cmd_data) {
10667 const gles2::cmds::GetActiveAttrib& c =
10668 *static_cast<const gles2::cmds::GetActiveAttrib*>(cmd_data);
10669 GLuint program_id = c.program;
10670 GLuint index = c.index;
10671 uint32 name_bucket_id = c.name_bucket_id;
10672 typedef cmds::GetActiveAttrib::Result Result;
10673 Result* result = GetSharedMemoryAs<Result*>(
10674 c.result_shm_id, c.result_shm_offset, sizeof(*result));
10675 if (!result) {
10676 return error::kOutOfBounds;
10678 // Check that the client initialized the result.
10679 if (result->success != 0) {
10680 return error::kInvalidArguments;
10682 Program* program = GetProgramInfoNotShader(
10683 program_id, "glGetActiveAttrib");
10684 if (!program) {
10685 return error::kNoError;
10687 const Program::VertexAttrib* attrib_info =
10688 program->GetAttribInfo(index);
10689 if (!attrib_info) {
10690 LOCAL_SET_GL_ERROR(
10691 GL_INVALID_VALUE, "glGetActiveAttrib", "index out of range");
10692 return error::kNoError;
10694 result->success = 1; // true.
10695 result->size = attrib_info->size;
10696 result->type = attrib_info->type;
10697 Bucket* bucket = CreateBucket(name_bucket_id);
10698 bucket->SetFromString(attrib_info->name.c_str());
10699 return error::kNoError;
10702 error::Error GLES2DecoderImpl::HandleShaderBinary(uint32 immediate_data_size,
10703 const void* cmd_data) {
10704 #if 1 // No binary shader support.
10705 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glShaderBinary", "not supported");
10706 return error::kNoError;
10707 #else
10708 GLsizei n = static_cast<GLsizei>(c.n);
10709 if (n < 0) {
10710 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "n < 0");
10711 return error::kNoError;
10713 GLsizei length = static_cast<GLsizei>(c.length);
10714 if (length < 0) {
10715 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "length < 0");
10716 return error::kNoError;
10718 uint32 data_size;
10719 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
10720 return error::kOutOfBounds;
10722 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
10723 c.shaders_shm_id, c.shaders_shm_offset, data_size);
10724 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
10725 const void* binary = GetSharedMemoryAs<const void*>(
10726 c.binary_shm_id, c.binary_shm_offset, length);
10727 if (shaders == NULL || binary == NULL) {
10728 return error::kOutOfBounds;
10730 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
10731 for (GLsizei ii = 0; ii < n; ++ii) {
10732 Shader* shader = GetShader(shaders[ii]);
10733 if (!shader) {
10734 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "unknown shader");
10735 return error::kNoError;
10737 service_ids[ii] = shader->service_id();
10739 // TODO(gman): call glShaderBinary
10740 return error::kNoError;
10741 #endif
10744 void GLES2DecoderImpl::DoSwapBuffers() {
10745 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
10747 int this_frame_number = frame_number_++;
10748 // TRACE_EVENT for gpu tests:
10749 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffersLatency",
10750 TRACE_EVENT_SCOPE_THREAD,
10751 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
10752 "width", (is_offscreen ? offscreen_size_.width() :
10753 surface_->GetSize().width()));
10754 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoSwapBuffers",
10755 "offscreen", is_offscreen,
10756 "frame", this_frame_number);
10758 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
10761 ScopedGPUTrace scoped_gpu_trace(gpu_tracer_.get(), kTraceDecoder,
10762 "gpu_toplevel", "SwapBuffer");
10764 bool is_tracing;
10765 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
10766 &is_tracing);
10767 if (is_tracing) {
10768 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
10769 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
10770 is_offscreen ? offscreen_size_ : surface_->GetSize());
10773 // If offscreen then don't actually SwapBuffers to the display. Just copy
10774 // the rendered frame to another frame buffer.
10775 if (is_offscreen) {
10776 TRACE_EVENT2("gpu", "Offscreen",
10777 "width", offscreen_size_.width(), "height", offscreen_size_.height());
10778 if (offscreen_size_ != offscreen_saved_color_texture_->size()) {
10779 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
10780 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
10781 // fix this.
10782 if (workarounds().needs_offscreen_buffer_workaround) {
10783 offscreen_saved_frame_buffer_->Create();
10784 glFinish();
10787 // Allocate the offscreen saved color texture.
10788 DCHECK(offscreen_saved_color_format_);
10789 offscreen_saved_color_texture_->AllocateStorage(
10790 offscreen_size_, offscreen_saved_color_format_, false);
10792 offscreen_saved_frame_buffer_->AttachRenderTexture(
10793 offscreen_saved_color_texture_.get());
10794 if (offscreen_size_.width() != 0 && offscreen_size_.height() != 0) {
10795 if (offscreen_saved_frame_buffer_->CheckStatus() !=
10796 GL_FRAMEBUFFER_COMPLETE) {
10797 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
10798 << "because offscreen saved FBO was incomplete.";
10799 MarkContextLost(error::kUnknown);
10800 group_->LoseContexts(error::kUnknown);
10801 return;
10804 // Clear the offscreen color texture.
10805 // TODO(piman): Is this still necessary?
10807 ScopedFrameBufferBinder binder(this,
10808 offscreen_saved_frame_buffer_->id());
10809 glClearColor(0, 0, 0, 0);
10810 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
10811 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
10812 glClear(GL_COLOR_BUFFER_BIT);
10813 RestoreClearState();
10817 UpdateParentTextureInfo();
10820 if (offscreen_size_.width() == 0 || offscreen_size_.height() == 0)
10821 return;
10822 ScopedGLErrorSuppressor suppressor(
10823 "GLES2DecoderImpl::DoSwapBuffers", GetErrorState());
10825 if (IsOffscreenBufferMultisampled()) {
10826 // For multisampled buffers, resolve the frame buffer.
10827 ScopedResolvedFrameBufferBinder binder(this, true, false);
10828 } else {
10829 ScopedFrameBufferBinder binder(this,
10830 offscreen_target_frame_buffer_->id());
10832 if (offscreen_target_buffer_preserved_) {
10833 // Copy the target frame buffer to the saved offscreen texture.
10834 offscreen_saved_color_texture_->Copy(
10835 offscreen_saved_color_texture_->size(),
10836 offscreen_saved_color_format_);
10837 } else {
10838 // Flip the textures in the parent context via the texture manager.
10839 if (!!offscreen_saved_color_texture_info_.get())
10840 offscreen_saved_color_texture_info_->texture()->
10841 SetServiceId(offscreen_target_color_texture_->id());
10843 offscreen_saved_color_texture_.swap(offscreen_target_color_texture_);
10844 offscreen_target_frame_buffer_->AttachRenderTexture(
10845 offscreen_target_color_texture_.get());
10848 // Ensure the side effects of the copy are visible to the parent
10849 // context. There is no need to do this for ANGLE because it uses a
10850 // single D3D device for all contexts.
10851 if (!feature_info_->gl_version_info().is_angle)
10852 glFlush();
10854 } else {
10855 if (!surface_->SwapBuffers()) {
10856 LOG(ERROR) << "Context lost because SwapBuffers failed.";
10857 if (!CheckResetStatus()) {
10858 MarkContextLost(error::kUnknown);
10859 group_->LoseContexts(error::kUnknown);
10864 // This may be a slow command. Exit command processing to allow for
10865 // context preemption and GPU watchdog checks.
10866 ExitCommandProcessingEarly();
10869 void GLES2DecoderImpl::DoSwapInterval(int interval) {
10870 context_->SetSwapInterval(interval);
10873 error::Error GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
10874 uint32 immediate_data_size,
10875 const void* cmd_data) {
10876 const gles2::cmds::EnableFeatureCHROMIUM& c =
10877 *static_cast<const gles2::cmds::EnableFeatureCHROMIUM*>(cmd_data);
10878 Bucket* bucket = GetBucket(c.bucket_id);
10879 if (!bucket || bucket->size() == 0) {
10880 return error::kInvalidArguments;
10882 typedef cmds::EnableFeatureCHROMIUM::Result Result;
10883 Result* result = GetSharedMemoryAs<Result*>(
10884 c.result_shm_id, c.result_shm_offset, sizeof(*result));
10885 if (!result) {
10886 return error::kOutOfBounds;
10888 // Check that the client initialized the result.
10889 if (*result != 0) {
10890 return error::kInvalidArguments;
10892 std::string feature_str;
10893 if (!bucket->GetAsString(&feature_str)) {
10894 return error::kInvalidArguments;
10897 // TODO(gman): make this some kind of table to function pointer thingy.
10898 if (feature_str.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
10899 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
10900 } else if (feature_str.compare("pepper3d_support_fixed_attribs") == 0) {
10901 buffer_manager()->set_allow_fixed_attribs(true);
10902 // TODO(gman): decide how to remove the need for this const_cast.
10903 // I could make validators_ non const but that seems bad as this is the only
10904 // place it is needed. I could make some special friend class of validators
10905 // just to allow this to set them. That seems silly. I could refactor this
10906 // code to use the extension mechanism or the initialization attributes to
10907 // turn this feature on. Given that the only real point of this is to make
10908 // the conformance tests pass and given that there is lots of real work that
10909 // needs to be done it seems like refactoring for one to one of those
10910 // methods is a very low priority.
10911 const_cast<Validators*>(validators_)->vertex_attrib_type.AddValue(GL_FIXED);
10912 } else if (feature_str.compare("webgl_enable_glsl_webgl_validation") == 0) {
10913 force_webgl_glsl_validation_ = true;
10914 InitializeShaderTranslator();
10915 } else {
10916 return error::kNoError;
10919 *result = 1; // true.
10920 return error::kNoError;
10923 error::Error GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
10924 uint32 immediate_data_size,
10925 const void* cmd_data) {
10926 const gles2::cmds::GetRequestableExtensionsCHROMIUM& c =
10927 *static_cast<const gles2::cmds::GetRequestableExtensionsCHROMIUM*>(
10928 cmd_data);
10929 Bucket* bucket = CreateBucket(c.bucket_id);
10930 scoped_refptr<FeatureInfo> info(new FeatureInfo());
10931 info->Initialize(disallowed_features_);
10932 bucket->SetFromString(info->extensions().c_str());
10933 return error::kNoError;
10936 error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
10937 uint32 immediate_data_size,
10938 const void* cmd_data) {
10939 const gles2::cmds::RequestExtensionCHROMIUM& c =
10940 *static_cast<const gles2::cmds::RequestExtensionCHROMIUM*>(cmd_data);
10941 Bucket* bucket = GetBucket(c.bucket_id);
10942 if (!bucket || bucket->size() == 0) {
10943 return error::kInvalidArguments;
10945 std::string feature_str;
10946 if (!bucket->GetAsString(&feature_str)) {
10947 return error::kInvalidArguments;
10950 bool desire_webgl_glsl_validation =
10951 feature_str.find("GL_CHROMIUM_webglsl") != std::string::npos;
10952 bool desire_standard_derivatives = false;
10953 bool desire_frag_depth = false;
10954 bool desire_draw_buffers = false;
10955 bool desire_shader_texture_lod = false;
10956 if (force_webgl_glsl_validation_) {
10957 desire_standard_derivatives =
10958 feature_str.find("GL_OES_standard_derivatives") != std::string::npos;
10959 desire_frag_depth =
10960 feature_str.find("GL_EXT_frag_depth") != std::string::npos;
10961 desire_draw_buffers =
10962 feature_str.find("GL_EXT_draw_buffers") != std::string::npos;
10963 desire_shader_texture_lod =
10964 feature_str.find("GL_EXT_shader_texture_lod") != std::string::npos;
10967 if (desire_webgl_glsl_validation != force_webgl_glsl_validation_ ||
10968 desire_standard_derivatives != derivatives_explicitly_enabled_ ||
10969 desire_frag_depth != frag_depth_explicitly_enabled_ ||
10970 desire_draw_buffers != draw_buffers_explicitly_enabled_) {
10971 force_webgl_glsl_validation_ |= desire_webgl_glsl_validation;
10972 derivatives_explicitly_enabled_ |= desire_standard_derivatives;
10973 frag_depth_explicitly_enabled_ |= desire_frag_depth;
10974 draw_buffers_explicitly_enabled_ |= desire_draw_buffers;
10975 shader_texture_lod_explicitly_enabled_ |= desire_shader_texture_lod;
10976 InitializeShaderTranslator();
10979 UpdateCapabilities();
10981 return error::kNoError;
10984 error::Error GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
10985 uint32 immediate_data_size,
10986 const void* cmd_data) {
10987 const gles2::cmds::GetProgramInfoCHROMIUM& c =
10988 *static_cast<const gles2::cmds::GetProgramInfoCHROMIUM*>(cmd_data);
10989 GLuint program_id = static_cast<GLuint>(c.program);
10990 uint32 bucket_id = c.bucket_id;
10991 Bucket* bucket = CreateBucket(bucket_id);
10992 bucket->SetSize(sizeof(ProgramInfoHeader)); // in case we fail.
10993 Program* program = NULL;
10994 program = GetProgram(program_id);
10995 if (!program || !program->IsValid()) {
10996 return error::kNoError;
10998 program->GetProgramInfo(program_manager(), bucket);
10999 return error::kNoError;
11002 error::Error GLES2DecoderImpl::HandleGetUniformBlocksCHROMIUM(
11003 uint32 immediate_data_size, const void* cmd_data) {
11004 if (!unsafe_es3_apis_enabled())
11005 return error::kUnknownCommand;
11006 const gles2::cmds::GetUniformBlocksCHROMIUM& c =
11007 *static_cast<const gles2::cmds::GetUniformBlocksCHROMIUM*>(cmd_data);
11008 GLuint program_id = static_cast<GLuint>(c.program);
11009 uint32 bucket_id = c.bucket_id;
11010 Bucket* bucket = CreateBucket(bucket_id);
11011 bucket->SetSize(sizeof(UniformBlocksHeader)); // in case we fail.
11012 Program* program = NULL;
11013 program = GetProgram(program_id);
11014 if (!program || !program->IsValid()) {
11015 return error::kNoError;
11017 program->GetUniformBlocks(bucket);
11018 return error::kNoError;
11021 error::Error GLES2DecoderImpl::HandleGetUniformsES3CHROMIUM(
11022 uint32 immediate_data_size, const void* cmd_data) {
11023 if (!unsafe_es3_apis_enabled())
11024 return error::kUnknownCommand;
11025 const gles2::cmds::GetUniformsES3CHROMIUM& c =
11026 *static_cast<const gles2::cmds::GetUniformsES3CHROMIUM*>(cmd_data);
11027 GLuint program_id = static_cast<GLuint>(c.program);
11028 uint32 bucket_id = c.bucket_id;
11029 Bucket* bucket = CreateBucket(bucket_id);
11030 bucket->SetSize(sizeof(UniformsES3Header)); // in case we fail.
11031 Program* program = NULL;
11032 program = GetProgram(program_id);
11033 if (!program || !program->IsValid()) {
11034 return error::kNoError;
11036 program->GetUniformsES3(bucket);
11037 return error::kNoError;
11040 error::Error GLES2DecoderImpl::HandleGetTransformFeedbackVarying(
11041 uint32 immediate_data_size,
11042 const void* cmd_data) {
11043 if (!unsafe_es3_apis_enabled())
11044 return error::kUnknownCommand;
11045 const gles2::cmds::GetTransformFeedbackVarying& c =
11046 *static_cast<const gles2::cmds::GetTransformFeedbackVarying*>(cmd_data);
11047 GLuint program_id = c.program;
11048 GLuint index = c.index;
11049 uint32 name_bucket_id = c.name_bucket_id;
11050 typedef cmds::GetTransformFeedbackVarying::Result Result;
11051 Result* result = GetSharedMemoryAs<Result*>(
11052 c.result_shm_id, c.result_shm_offset, sizeof(*result));
11053 if (!result) {
11054 return error::kOutOfBounds;
11056 // Check that the client initialized the result.
11057 if (result->success != 0) {
11058 return error::kInvalidArguments;
11060 Program* program = GetProgramInfoNotShader(
11061 program_id, "glGetTransformFeedbackVarying");
11062 if (!program) {
11063 return error::kNoError;
11065 GLuint service_id = program->service_id();
11066 GLint link_status = GL_FALSE;
11067 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
11068 if (link_status != GL_TRUE) {
11069 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
11070 "glGetTransformFeedbackVarying", "program not linked");
11071 return error::kNoError;
11073 GLint max_length = 0;
11074 glGetProgramiv(
11075 service_id, GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH, &max_length);
11076 max_length = std::max(1, max_length);
11077 std::vector<char> buffer(max_length);
11078 GLsizei length = 0;
11079 GLsizei size = 0;
11080 GLenum type = 0;
11081 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetTransformFeedbackVarying");
11082 glGetTransformFeedbackVarying(
11083 service_id, index, max_length, &length, &size, &type, &buffer[0]);
11084 GLenum error = glGetError();
11085 if (error != GL_NO_ERROR) {
11086 LOCAL_SET_GL_ERROR(error, "glGetTransformFeedbackVarying", "");
11087 return error::kNoError;
11089 result->success = 1; // true.
11090 result->size = static_cast<int32_t>(size);
11091 result->type = static_cast<uint32_t>(type);
11092 Bucket* bucket = CreateBucket(name_bucket_id);
11093 DCHECK(length >= 0 && length < max_length);
11094 buffer[length] = '\0'; // Just to be safe.
11095 bucket->SetFromString(&buffer[0]);
11096 return error::kNoError;
11099 error::Error GLES2DecoderImpl::HandleGetTransformFeedbackVaryingsCHROMIUM(
11100 uint32 immediate_data_size, const void* cmd_data) {
11101 if (!unsafe_es3_apis_enabled())
11102 return error::kUnknownCommand;
11103 const gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM& c =
11104 *static_cast<const gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM*>(
11105 cmd_data);
11106 GLuint program_id = static_cast<GLuint>(c.program);
11107 uint32 bucket_id = c.bucket_id;
11108 Bucket* bucket = CreateBucket(bucket_id);
11109 bucket->SetSize(sizeof(TransformFeedbackVaryingsHeader)); // in case we fail.
11110 Program* program = NULL;
11111 program = GetProgram(program_id);
11112 if (!program || !program->IsValid()) {
11113 return error::kNoError;
11115 program->GetTransformFeedbackVaryings(bucket);
11116 return error::kNoError;
11119 error::ContextLostReason GLES2DecoderImpl::GetContextLostReason() {
11120 return context_lost_reason_;
11123 error::ContextLostReason GLES2DecoderImpl::GetContextLostReasonFromResetStatus(
11124 GLenum reset_status) const {
11125 switch (reset_status) {
11126 case GL_NO_ERROR:
11127 // TODO(kbr): improve the precision of the error code in this case.
11128 // Consider delegating to context for error code if MakeCurrent fails.
11129 return error::kUnknown;
11130 case GL_GUILTY_CONTEXT_RESET_ARB:
11131 return error::kGuilty;
11132 case GL_INNOCENT_CONTEXT_RESET_ARB:
11133 return error::kInnocent;
11134 case GL_UNKNOWN_CONTEXT_RESET_ARB:
11135 return error::kUnknown;
11138 NOTREACHED();
11139 return error::kUnknown;
11142 bool GLES2DecoderImpl::WasContextLost() const {
11143 return context_was_lost_;
11146 bool GLES2DecoderImpl::WasContextLostByRobustnessExtension() const {
11147 return WasContextLost() && reset_by_robustness_extension_;
11150 void GLES2DecoderImpl::MarkContextLost(error::ContextLostReason reason) {
11151 // Only lose the context once.
11152 if (WasContextLost())
11153 return;
11155 // Don't make GL calls in here, the context might not be current.
11156 context_lost_reason_ = reason;
11157 current_decoder_error_ = error::kLostContext;
11158 context_was_lost_ = true;
11160 // Some D3D drivers cannot recover from device lost in the GPU process
11161 // sandbox. Allow a new GPU process to launch.
11162 if (workarounds().exit_on_context_lost) {
11163 LOG(ERROR) << "Exiting GPU process because some drivers cannot reset"
11164 << " a D3D device in the Chrome GPU process sandbox.";
11165 #if defined(OS_WIN)
11166 base::win::SetShouldCrashOnProcessDetach(false);
11167 #endif
11168 exit(0);
11172 bool GLES2DecoderImpl::CheckResetStatus() {
11173 DCHECK(!WasContextLost());
11174 DCHECK(context_->IsCurrent(NULL));
11176 if (IsRobustnessSupported()) {
11177 // If the reason for the call was a GL error, we can try to determine the
11178 // reset status more accurately.
11179 GLenum driver_status = glGetGraphicsResetStatusARB();
11180 if (driver_status == GL_NO_ERROR)
11181 return false;
11183 LOG(ERROR) << (surface_->IsOffscreen() ? "Offscreen" : "Onscreen")
11184 << " context lost via ARB/EXT_robustness. Reset status = "
11185 << GLES2Util::GetStringEnum(driver_status);
11187 // Don't pretend we know which client was responsible.
11188 if (workarounds().use_virtualized_gl_contexts)
11189 driver_status = GL_UNKNOWN_CONTEXT_RESET_ARB;
11191 switch (driver_status) {
11192 case GL_GUILTY_CONTEXT_RESET_ARB:
11193 MarkContextLost(error::kGuilty);
11194 break;
11195 case GL_INNOCENT_CONTEXT_RESET_ARB:
11196 MarkContextLost(error::kInnocent);
11197 break;
11198 case GL_UNKNOWN_CONTEXT_RESET_ARB:
11199 MarkContextLost(error::kUnknown);
11200 break;
11201 default:
11202 NOTREACHED();
11203 return false;
11205 reset_by_robustness_extension_ = true;
11206 return true;
11208 return false;
11211 error::Error GLES2DecoderImpl::HandleInsertSyncPointCHROMIUM(
11212 uint32 immediate_data_size,
11213 const void* cmd_data) {
11214 return error::kUnknownCommand;
11217 error::Error GLES2DecoderImpl::HandleWaitSyncPointCHROMIUM(
11218 uint32 immediate_data_size,
11219 const void* cmd_data) {
11220 const gles2::cmds::WaitSyncPointCHROMIUM& c =
11221 *static_cast<const gles2::cmds::WaitSyncPointCHROMIUM*>(cmd_data);
11222 uint32 sync_point = c.sync_point;
11223 if (wait_sync_point_callback_.is_null())
11224 return error::kNoError;
11226 return wait_sync_point_callback_.Run(sync_point) ?
11227 error::kNoError : error::kDeferCommandUntilLater;
11230 error::Error GLES2DecoderImpl::HandleDiscardBackbufferCHROMIUM(
11231 uint32 immediate_data_size,
11232 const void* cmd_data) {
11233 if (surface_->DeferDraws())
11234 return error::kDeferCommandUntilLater;
11235 if (!surface_->SetBackbufferAllocation(false))
11236 return error::kLostContext;
11237 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
11238 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
11239 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
11240 return error::kNoError;
11243 bool GLES2DecoderImpl::GenQueriesEXTHelper(
11244 GLsizei n, const GLuint* client_ids) {
11245 for (GLsizei ii = 0; ii < n; ++ii) {
11246 if (query_manager_->GetQuery(client_ids[ii])) {
11247 return false;
11250 query_manager_->GenQueries(n, client_ids);
11251 return true;
11254 void GLES2DecoderImpl::DeleteQueriesEXTHelper(
11255 GLsizei n, const GLuint* client_ids) {
11256 for (GLsizei ii = 0; ii < n; ++ii) {
11257 QueryManager::Query* query = query_manager_->GetQuery(client_ids[ii]);
11258 if (query && !query->IsDeleted()) {
11259 ContextState::QueryMap::iterator it =
11260 state_.current_queries.find(query->target());
11261 if (it != state_.current_queries.end())
11262 state_.current_queries.erase(it);
11264 query->Destroy(true);
11266 query_manager_->RemoveQuery(client_ids[ii]);
11270 bool GLES2DecoderImpl::ProcessPendingQueries(bool did_finish) {
11271 if (query_manager_.get() == NULL) {
11272 return false;
11274 if (!query_manager_->ProcessPendingQueries(did_finish)) {
11275 current_decoder_error_ = error::kOutOfBounds;
11277 return query_manager_->HavePendingQueries();
11280 // Note that if there are no pending readpixels right now,
11281 // this function will call the callback immediately.
11282 void GLES2DecoderImpl::WaitForReadPixels(base::Closure callback) {
11283 if (features().use_async_readpixels && !pending_readpixel_fences_.empty()) {
11284 pending_readpixel_fences_.back()->callbacks.push_back(callback);
11285 } else {
11286 callback.Run();
11290 void GLES2DecoderImpl::ProcessPendingReadPixels() {
11291 while (!pending_readpixel_fences_.empty() &&
11292 pending_readpixel_fences_.front()->fence->HasCompleted()) {
11293 std::vector<base::Closure> callbacks =
11294 pending_readpixel_fences_.front()->callbacks;
11295 pending_readpixel_fences_.pop();
11296 for (size_t i = 0; i < callbacks.size(); i++) {
11297 callbacks[i].Run();
11302 bool GLES2DecoderImpl::HasMoreIdleWork() {
11303 return !pending_readpixel_fences_.empty() ||
11304 async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers();
11307 void GLES2DecoderImpl::PerformIdleWork() {
11308 ProcessPendingReadPixels();
11309 if (!async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers())
11310 return;
11311 async_pixel_transfer_manager_->ProcessMorePendingTransfers();
11312 ProcessFinishedAsyncTransfers();
11315 error::Error GLES2DecoderImpl::HandleBeginQueryEXT(uint32 immediate_data_size,
11316 const void* cmd_data) {
11317 const gles2::cmds::BeginQueryEXT& c =
11318 *static_cast<const gles2::cmds::BeginQueryEXT*>(cmd_data);
11319 GLenum target = static_cast<GLenum>(c.target);
11320 GLuint client_id = static_cast<GLuint>(c.id);
11321 int32 sync_shm_id = static_cast<int32>(c.sync_data_shm_id);
11322 uint32 sync_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
11324 switch (target) {
11325 case GL_COMMANDS_ISSUED_CHROMIUM:
11326 case GL_LATENCY_QUERY_CHROMIUM:
11327 case GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM:
11328 case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM:
11329 case GL_GET_ERROR_QUERY_CHROMIUM:
11330 break;
11331 case GL_COMMANDS_COMPLETED_CHROMIUM:
11332 if (!features().chromium_sync_query) {
11333 LOCAL_SET_GL_ERROR(
11334 GL_INVALID_OPERATION, "glBeginQueryEXT",
11335 "not enabled for commands completed queries");
11336 return error::kNoError;
11338 break;
11339 default:
11340 if (!features().occlusion_query_boolean) {
11341 LOCAL_SET_GL_ERROR(
11342 GL_INVALID_OPERATION, "glBeginQueryEXT",
11343 "not enabled for occlusion queries");
11344 return error::kNoError;
11346 break;
11349 if (state_.current_queries.find(target) != state_.current_queries.end()) {
11350 LOCAL_SET_GL_ERROR(
11351 GL_INVALID_OPERATION, "glBeginQueryEXT", "query already in progress");
11352 return error::kNoError;
11355 if (client_id == 0) {
11356 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glBeginQueryEXT", "id is 0");
11357 return error::kNoError;
11360 QueryManager::Query* query = query_manager_->GetQuery(client_id);
11361 if (!query) {
11362 if (!query_manager_->IsValidQuery(client_id)) {
11363 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
11364 "glBeginQueryEXT",
11365 "id not made by glGenQueriesEXT");
11366 return error::kNoError;
11368 query = query_manager_->CreateQuery(
11369 target, client_id, sync_shm_id, sync_shm_offset);
11372 if (query->target() != target) {
11373 LOCAL_SET_GL_ERROR(
11374 GL_INVALID_OPERATION, "glBeginQueryEXT", "target does not match");
11375 return error::kNoError;
11376 } else if (query->shm_id() != sync_shm_id ||
11377 query->shm_offset() != sync_shm_offset) {
11378 DLOG(ERROR) << "Shared memory used by query not the same as before";
11379 return error::kInvalidArguments;
11382 if (!query_manager_->BeginQuery(query)) {
11383 return error::kOutOfBounds;
11386 state_.current_queries[target] = query;
11387 return error::kNoError;
11390 error::Error GLES2DecoderImpl::HandleEndQueryEXT(uint32 immediate_data_size,
11391 const void* cmd_data) {
11392 const gles2::cmds::EndQueryEXT& c =
11393 *static_cast<const gles2::cmds::EndQueryEXT*>(cmd_data);
11394 GLenum target = static_cast<GLenum>(c.target);
11395 uint32 submit_count = static_cast<GLuint>(c.submit_count);
11396 ContextState::QueryMap::iterator it = state_.current_queries.find(target);
11398 if (it == state_.current_queries.end()) {
11399 LOCAL_SET_GL_ERROR(
11400 GL_INVALID_OPERATION, "glEndQueryEXT", "No active query");
11401 return error::kNoError;
11404 QueryManager::Query* query = it->second.get();
11405 if (!query_manager_->EndQuery(query, submit_count)) {
11406 return error::kOutOfBounds;
11409 query_manager_->ProcessPendingTransferQueries();
11411 state_.current_queries.erase(it);
11412 return error::kNoError;
11415 bool GLES2DecoderImpl::GenVertexArraysOESHelper(
11416 GLsizei n, const GLuint* client_ids) {
11417 for (GLsizei ii = 0; ii < n; ++ii) {
11418 if (GetVertexAttribManager(client_ids[ii])) {
11419 return false;
11423 if (!features().native_vertex_array_object) {
11424 // Emulated VAO
11425 for (GLsizei ii = 0; ii < n; ++ii) {
11426 CreateVertexAttribManager(client_ids[ii], 0, true);
11428 } else {
11429 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
11431 glGenVertexArraysOES(n, service_ids.get());
11432 for (GLsizei ii = 0; ii < n; ++ii) {
11433 CreateVertexAttribManager(client_ids[ii], service_ids[ii], true);
11437 return true;
11440 void GLES2DecoderImpl::DeleteVertexArraysOESHelper(
11441 GLsizei n, const GLuint* client_ids) {
11442 for (GLsizei ii = 0; ii < n; ++ii) {
11443 VertexAttribManager* vao =
11444 GetVertexAttribManager(client_ids[ii]);
11445 if (vao && !vao->IsDeleted()) {
11446 if (state_.vertex_attrib_manager.get() == vao) {
11447 DoBindVertexArrayOES(0);
11449 RemoveVertexAttribManager(client_ids[ii]);
11454 void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id) {
11455 VertexAttribManager* vao = NULL;
11456 if (client_id != 0) {
11457 vao = GetVertexAttribManager(client_id);
11458 if (!vao) {
11459 // Unlike most Bind* methods, the spec explicitly states that VertexArray
11460 // only allows names that have been previously generated. As such, we do
11461 // not generate new names here.
11462 LOCAL_SET_GL_ERROR(
11463 GL_INVALID_OPERATION,
11464 "glBindVertexArrayOES", "bad vertex array id.");
11465 current_decoder_error_ = error::kNoError;
11466 return;
11468 } else {
11469 vao = state_.default_vertex_attrib_manager.get();
11472 // Only set the VAO state if it's changed
11473 if (state_.vertex_attrib_manager.get() != vao) {
11474 state_.vertex_attrib_manager = vao;
11475 if (!features().native_vertex_array_object) {
11476 EmulateVertexArrayState();
11477 } else {
11478 GLuint service_id = vao->service_id();
11479 glBindVertexArrayOES(service_id);
11484 // Used when OES_vertex_array_object isn't natively supported
11485 void GLES2DecoderImpl::EmulateVertexArrayState() {
11486 // Setup the Vertex attribute state
11487 for (uint32 vv = 0; vv < group_->max_vertex_attribs(); ++vv) {
11488 RestoreStateForAttrib(vv, true);
11491 // Setup the element buffer
11492 Buffer* element_array_buffer =
11493 state_.vertex_attrib_manager->element_array_buffer();
11494 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
11495 element_array_buffer ? element_array_buffer->service_id() : 0);
11498 bool GLES2DecoderImpl::DoIsVertexArrayOES(GLuint client_id) {
11499 const VertexAttribManager* vao =
11500 GetVertexAttribManager(client_id);
11501 return vao && vao->IsValid() && !vao->IsDeleted();
11504 #if defined(OS_MACOSX)
11505 void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id) {
11506 TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.find(
11507 texture_id);
11508 if (it != texture_to_io_surface_map_.end()) {
11509 // Found a previous IOSurface bound to this texture; release it.
11510 IOSurfaceRef surface = it->second;
11511 CFRelease(surface);
11512 texture_to_io_surface_map_.erase(it);
11515 #endif
11517 void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
11518 GLenum target, GLsizei width, GLsizei height,
11519 GLuint io_surface_id, GLuint plane) {
11520 #if defined(OS_MACOSX)
11521 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) {
11522 LOCAL_SET_GL_ERROR(
11523 GL_INVALID_OPERATION,
11524 "glTexImageIOSurface2DCHROMIUM", "only supported on desktop GL.");
11525 return;
11528 if (target != GL_TEXTURE_RECTANGLE_ARB) {
11529 // This might be supported in the future, and if we could require
11530 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
11531 // could delete a lot of code. For now, perform strict validation so we
11532 // know what's going on.
11533 LOCAL_SET_GL_ERROR(
11534 GL_INVALID_OPERATION,
11535 "glTexImageIOSurface2DCHROMIUM",
11536 "requires TEXTURE_RECTANGLE_ARB target");
11537 return;
11540 // Default target might be conceptually valid, but disallow it to avoid
11541 // accidents.
11542 TextureRef* texture_ref =
11543 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
11544 if (!texture_ref) {
11545 LOCAL_SET_GL_ERROR(
11546 GL_INVALID_OPERATION,
11547 "glTexImageIOSurface2DCHROMIUM", "no rectangle texture bound");
11548 return;
11551 // Look up the new IOSurface. Note that because of asynchrony
11552 // between processes this might fail; during live resizing the
11553 // plugin process might allocate and release an IOSurface before
11554 // this process gets a chance to look it up. Hold on to any old
11555 // IOSurface in this case.
11556 IOSurfaceRef surface = IOSurfaceLookup(io_surface_id);
11557 if (!surface) {
11558 LOCAL_SET_GL_ERROR(
11559 GL_INVALID_OPERATION,
11560 "glTexImageIOSurface2DCHROMIUM", "no IOSurface with the given ID");
11561 return;
11564 // Release any IOSurface previously bound to this texture.
11565 ReleaseIOSurfaceForTexture(texture_ref->service_id());
11567 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
11568 texture_to_io_surface_map_.insert(
11569 std::make_pair(texture_ref->service_id(), surface));
11571 CGLContextObj context =
11572 static_cast<CGLContextObj>(context_->GetHandle());
11574 CGLError err = CGLTexImageIOSurface2D(
11575 context,
11576 target,
11577 GL_RGBA,
11578 width,
11579 height,
11580 GL_BGRA,
11581 GL_UNSIGNED_INT_8_8_8_8_REV,
11582 surface,
11583 plane);
11585 if (err != kCGLNoError) {
11586 LOCAL_SET_GL_ERROR(
11587 GL_INVALID_OPERATION,
11588 "glTexImageIOSurface2DCHROMIUM", "error in CGLTexImageIOSurface2D");
11589 return;
11592 texture_manager()->SetLevelInfo(
11593 texture_ref, target, 0, GL_RGBA, width, height, 1, 0,
11594 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, true);
11596 #else
11597 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
11598 "glTexImageIOSurface2DCHROMIUM", "not supported.");
11599 #endif
11602 static GLenum ExtractFormatFromStorageFormat(GLenum internalformat) {
11603 switch (internalformat) {
11604 case GL_RGB565:
11605 return GL_RGB;
11606 case GL_RGBA4:
11607 return GL_RGBA;
11608 case GL_RGB5_A1:
11609 return GL_RGBA;
11610 case GL_RGB8_OES:
11611 return GL_RGB;
11612 case GL_RGBA8_OES:
11613 return GL_RGBA;
11614 case GL_LUMINANCE8_ALPHA8_EXT:
11615 return GL_LUMINANCE_ALPHA;
11616 case GL_LUMINANCE8_EXT:
11617 return GL_LUMINANCE;
11618 case GL_ALPHA8_EXT:
11619 return GL_ALPHA;
11620 case GL_RGBA32F_EXT:
11621 return GL_RGBA;
11622 case GL_RGB32F_EXT:
11623 return GL_RGB;
11624 case GL_ALPHA32F_EXT:
11625 return GL_ALPHA;
11626 case GL_LUMINANCE32F_EXT:
11627 return GL_LUMINANCE;
11628 case GL_LUMINANCE_ALPHA32F_EXT:
11629 return GL_LUMINANCE_ALPHA;
11630 case GL_RGBA16F_EXT:
11631 return GL_RGBA;
11632 case GL_RGB16F_EXT:
11633 return GL_RGB;
11634 case GL_ALPHA16F_EXT:
11635 return GL_ALPHA;
11636 case GL_LUMINANCE16F_EXT:
11637 return GL_LUMINANCE;
11638 case GL_LUMINANCE_ALPHA16F_EXT:
11639 return GL_LUMINANCE_ALPHA;
11640 case GL_BGRA8_EXT:
11641 return GL_BGRA_EXT;
11642 case GL_SRGB8_ALPHA8_EXT:
11643 return GL_SRGB_ALPHA_EXT;
11644 default:
11645 return GL_NONE;
11649 bool GLES2DecoderImpl::ValidateCopyTextureCHROMIUM(
11650 const char* function_name,
11651 GLenum target,
11652 TextureRef* source_texture_ref,
11653 TextureRef* dest_texture_ref,
11654 GLenum dest_internal_format) {
11655 if (!source_texture_ref || !dest_texture_ref) {
11656 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "unknown texture id");
11657 return false;
11660 if (GL_TEXTURE_2D != target) {
11661 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name,
11662 "invalid texture target");
11663 return false;
11666 Texture* source_texture = source_texture_ref->texture();
11667 Texture* dest_texture = dest_texture_ref->texture();
11668 if (source_texture == dest_texture) {
11669 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
11670 "source and destination textures are the same");
11671 return false;
11674 if (dest_texture->target() != GL_TEXTURE_2D ||
11675 (source_texture->target() != GL_TEXTURE_2D &&
11676 source_texture->target() != GL_TEXTURE_RECTANGLE_ARB &&
11677 source_texture->target() != GL_TEXTURE_EXTERNAL_OES)) {
11678 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name,
11679 "invalid texture target binding");
11680 return false;
11683 GLenum source_type = 0;
11684 GLenum source_internal_format = 0;
11685 source_texture->GetLevelType(source_texture->target(), 0, &source_type,
11686 &source_internal_format);
11688 // The destination format should be GL_RGB, or GL_RGBA. GL_ALPHA,
11689 // GL_LUMINANCE, and GL_LUMINANCE_ALPHA are not supported because they are not
11690 // renderable on some platforms.
11691 bool valid_dest_format = dest_internal_format == GL_RGB ||
11692 dest_internal_format == GL_RGBA ||
11693 dest_internal_format == GL_BGRA_EXT;
11694 bool valid_source_format = source_internal_format == GL_ALPHA ||
11695 source_internal_format == GL_RGB ||
11696 source_internal_format == GL_RGBA ||
11697 source_internal_format == GL_LUMINANCE ||
11698 source_internal_format == GL_LUMINANCE_ALPHA ||
11699 source_internal_format == GL_BGRA_EXT;
11700 if (!valid_source_format || !valid_dest_format) {
11701 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
11702 "invalid internal format");
11703 return false;
11705 return true;
11708 void GLES2DecoderImpl::DoCopyTextureCHROMIUM(GLenum target,
11709 GLuint source_id,
11710 GLuint dest_id,
11711 GLenum internal_format,
11712 GLenum dest_type) {
11713 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopyTextureCHROMIUM");
11715 TextureRef* source_texture_ref = GetTexture(source_id);
11716 TextureRef* dest_texture_ref = GetTexture(dest_id);
11717 Texture* source_texture = source_texture_ref->texture();
11718 Texture* dest_texture = dest_texture_ref->texture();
11719 int source_width = 0;
11720 int source_height = 0;
11721 gfx::GLImage* image =
11722 source_texture->GetLevelImage(source_texture->target(), 0);
11723 if (image) {
11724 gfx::Size size = image->GetSize();
11725 source_width = size.width();
11726 source_height = size.height();
11727 if (source_width <= 0 || source_height <= 0) {
11728 LOCAL_SET_GL_ERROR(
11729 GL_INVALID_VALUE,
11730 "glCopyTextureChromium", "invalid image size");
11731 return;
11733 } else {
11734 if (!source_texture->GetLevelSize(source_texture->target(), 0,
11735 &source_width, &source_height, nullptr)) {
11736 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
11737 "glCopyTextureChromium",
11738 "source texture has no level 0");
11739 return;
11742 // Check that this type of texture is allowed.
11743 if (!texture_manager()->ValidForTarget(source_texture->target(), 0,
11744 source_width, source_height, 1)) {
11745 LOCAL_SET_GL_ERROR(
11746 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "Bad dimensions");
11747 return;
11751 GLenum source_type = 0;
11752 GLenum source_internal_format = 0;
11753 source_texture->GetLevelType(
11754 source_texture->target(), 0, &source_type, &source_internal_format);
11756 if (dest_texture->IsImmutable()) {
11757 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCopyTextureCHROMIUM",
11758 "texture is immutable");
11759 return;
11762 if (!ValidateCopyTextureCHROMIUM("glCopyTextureCHROMIUM", target,
11763 source_texture_ref, dest_texture_ref,
11764 internal_format)) {
11765 return;
11768 // Clear the source texture if necessary.
11769 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref,
11770 source_texture->target(), 0)) {
11771 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTextureCHROMIUM",
11772 "dimensions too big");
11773 return;
11776 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
11777 // needed because it takes 10s of milliseconds to initialize.
11778 if (!copy_texture_CHROMIUM_.get()) {
11779 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
11780 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
11781 copy_texture_CHROMIUM_->Initialize(this);
11782 RestoreCurrentFramebufferBindings();
11783 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR)
11784 return;
11787 GLenum dest_type_previous = dest_type;
11788 GLenum dest_internal_format = internal_format;
11789 int dest_width = 0;
11790 int dest_height = 0;
11791 bool dest_level_defined = dest_texture->GetLevelSize(
11792 GL_TEXTURE_2D, 0, &dest_width, &dest_height, nullptr);
11794 if (dest_level_defined) {
11795 dest_texture->GetLevelType(GL_TEXTURE_2D, 0, &dest_type_previous,
11796 &dest_internal_format);
11799 // Resize the destination texture to the dimensions of the source texture.
11800 if (!dest_level_defined || dest_width != source_width ||
11801 dest_height != source_height ||
11802 dest_internal_format != internal_format ||
11803 dest_type_previous != dest_type) {
11804 // Ensure that the glTexImage2D succeeds.
11805 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
11806 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
11807 glTexImage2D(GL_TEXTURE_2D, 0, internal_format, source_width, source_height,
11808 0, internal_format, dest_type, NULL);
11809 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM");
11810 if (error != GL_NO_ERROR) {
11811 RestoreCurrentTextureBindings(&state_, GL_TEXTURE_2D);
11812 return;
11815 texture_manager()->SetLevelInfo(
11816 dest_texture_ref, GL_TEXTURE_2D, 0, internal_format, source_width,
11817 source_height, 1, 0, internal_format, dest_type, true);
11818 } else {
11819 texture_manager()->SetLevelCleared(dest_texture_ref, GL_TEXTURE_2D, 0,
11820 true);
11823 ScopedModifyPixels modify(dest_texture_ref);
11825 // Try using GLImage::CopyTexImage when possible.
11826 bool unpack_premultiply_alpha_change =
11827 unpack_premultiply_alpha_ ^ unpack_unpremultiply_alpha_;
11828 if (image && !unpack_flip_y_ && !unpack_premultiply_alpha_change) {
11829 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
11830 if (image->CopyTexImage(GL_TEXTURE_2D))
11831 return;
11834 DoWillUseTexImageIfNeeded(source_texture, source_texture->target());
11836 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
11837 // before presenting.
11838 if (source_texture->target() == GL_TEXTURE_EXTERNAL_OES) {
11839 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
11840 // instead of using kIdentityMatrix crbug.com/226218.
11841 copy_texture_CHROMIUM_->DoCopyTextureWithTransform(
11842 this, source_texture->target(), source_texture->service_id(),
11843 dest_texture->service_id(), source_width, source_height, unpack_flip_y_,
11844 unpack_premultiply_alpha_, unpack_unpremultiply_alpha_,
11845 kIdentityMatrix);
11846 } else {
11847 copy_texture_CHROMIUM_->DoCopyTexture(
11848 this, source_texture->target(), source_texture->service_id(),
11849 source_internal_format, dest_texture->service_id(), internal_format,
11850 source_width, source_height, unpack_flip_y_, unpack_premultiply_alpha_,
11851 unpack_unpremultiply_alpha_);
11854 DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
11857 void GLES2DecoderImpl::DoCopySubTextureCHROMIUM(GLenum target,
11858 GLuint source_id,
11859 GLuint dest_id,
11860 GLint xoffset,
11861 GLint yoffset) {
11862 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopySubTextureCHROMIUM");
11864 TextureRef* source_texture_ref = GetTexture(source_id);
11865 TextureRef* dest_texture_ref = GetTexture(dest_id);
11866 Texture* source_texture = source_texture_ref->texture();
11867 Texture* dest_texture = dest_texture_ref->texture();
11868 int source_width = 0;
11869 int source_height = 0;
11870 gfx::GLImage* image =
11871 source_texture->GetLevelImage(source_texture->target(), 0);
11872 if (image) {
11873 gfx::Size size = image->GetSize();
11874 source_width = size.width();
11875 source_height = size.height();
11876 if (source_width <= 0 || source_height <= 0) {
11877 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
11878 "invalid image size");
11879 return;
11881 } else {
11882 if (!source_texture->GetLevelSize(source_texture->target(), 0,
11883 &source_width, &source_height, nullptr)) {
11884 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
11885 "source texture has no level 0");
11886 return;
11889 // Check that this type of texture is allowed.
11890 if (!texture_manager()->ValidForTarget(source_texture->target(), 0,
11891 source_width, source_height, 1)) {
11892 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
11893 "source texture bad dimensions");
11894 return;
11898 GLenum source_type = 0;
11899 GLenum source_internal_format = 0;
11900 source_texture->GetLevelType(source_texture->target(), 0, &source_type,
11901 &source_internal_format);
11902 GLenum dest_type = 0;
11903 GLenum dest_internal_format = 0;
11904 bool dest_level_defined = dest_texture->GetLevelType(
11905 dest_texture->target(), 0, &dest_type, &dest_internal_format);
11906 if (!dest_level_defined) {
11907 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCopySubTextureCHROMIUM",
11908 "destination texture is not defined");
11909 return;
11911 if (!dest_texture->ValidForTexture(dest_texture->target(), 0, xoffset,
11912 yoffset, 0, source_width, source_height,
11913 1, dest_type)) {
11914 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
11915 "destination texture bad dimensions.");
11916 return;
11919 if (!ValidateCopyTextureCHROMIUM("glCopySubTextureCHROMIUM", target,
11920 source_texture_ref, dest_texture_ref,
11921 dest_internal_format)) {
11922 return;
11925 // Clear the source texture if necessary.
11926 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref,
11927 source_texture->target(), 0)) {
11928 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopySubTextureCHROMIUM",
11929 "source texture dimensions too big");
11930 return;
11933 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
11934 // needed because it takes 10s of milliseconds to initialize.
11935 if (!copy_texture_CHROMIUM_.get()) {
11936 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopySubTextureCHROMIUM");
11937 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
11938 copy_texture_CHROMIUM_->Initialize(this);
11939 RestoreCurrentFramebufferBindings();
11940 if (LOCAL_PEEK_GL_ERROR("glCopySubTextureCHROMIUM") != GL_NO_ERROR)
11941 return;
11944 int dest_width = 0;
11945 int dest_height = 0;
11946 bool ok = dest_texture->GetLevelSize(
11947 GL_TEXTURE_2D, 0, &dest_width, &dest_height, nullptr);
11948 DCHECK(ok);
11949 if (xoffset != 0 || yoffset != 0 || source_width != dest_width ||
11950 source_height != dest_height) {
11951 if (!texture_manager()->ClearTextureLevel(this, dest_texture_ref, target,
11952 0)) {
11953 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopySubTextureCHROMIUM",
11954 "destination texture dimensions too big");
11955 return;
11957 } else {
11958 texture_manager()->SetLevelCleared(dest_texture_ref, GL_TEXTURE_2D, 0,
11959 true);
11962 ScopedModifyPixels modify(dest_texture_ref);
11964 // Try using GLImage::CopyTexSubImage when possible.
11965 bool unpack_premultiply_alpha_change =
11966 unpack_premultiply_alpha_ ^ unpack_unpremultiply_alpha_;
11967 if (image && !unpack_flip_y_ && !unpack_premultiply_alpha_change &&
11968 !xoffset && !yoffset) {
11969 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
11970 if (image->CopyTexImage(GL_TEXTURE_2D))
11971 return;
11974 DoWillUseTexImageIfNeeded(source_texture, source_texture->target());
11976 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
11977 // before presenting.
11978 if (source_texture->target() == GL_TEXTURE_EXTERNAL_OES) {
11979 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
11980 // instead of using kIdentityMatrix crbug.com/226218.
11981 copy_texture_CHROMIUM_->DoCopySubTextureWithTransform(
11982 this, source_texture->target(), source_texture->service_id(),
11983 dest_texture->service_id(), xoffset, yoffset, dest_width, dest_height,
11984 source_width, source_height, unpack_flip_y_, unpack_premultiply_alpha_,
11985 unpack_unpremultiply_alpha_, kIdentityMatrix);
11986 } else {
11987 copy_texture_CHROMIUM_->DoCopySubTexture(
11988 this, source_texture->target(), source_texture->service_id(),
11989 source_internal_format, dest_texture->service_id(),
11990 dest_internal_format, xoffset, yoffset, dest_width, dest_height,
11991 source_width, source_height, unpack_flip_y_, unpack_premultiply_alpha_,
11992 unpack_unpremultiply_alpha_);
11995 DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
11998 static GLenum ExtractTypeFromStorageFormat(GLenum internalformat) {
11999 switch (internalformat) {
12000 case GL_RGB565:
12001 return GL_UNSIGNED_SHORT_5_6_5;
12002 case GL_RGBA4:
12003 return GL_UNSIGNED_SHORT_4_4_4_4;
12004 case GL_RGB5_A1:
12005 return GL_UNSIGNED_SHORT_5_5_5_1;
12006 case GL_RGB8_OES:
12007 return GL_UNSIGNED_BYTE;
12008 case GL_RGBA8_OES:
12009 return GL_UNSIGNED_BYTE;
12010 case GL_LUMINANCE8_ALPHA8_EXT:
12011 return GL_UNSIGNED_BYTE;
12012 case GL_LUMINANCE8_EXT:
12013 return GL_UNSIGNED_BYTE;
12014 case GL_ALPHA8_EXT:
12015 return GL_UNSIGNED_BYTE;
12016 case GL_RGBA32F_EXT:
12017 return GL_FLOAT;
12018 case GL_RGB32F_EXT:
12019 return GL_FLOAT;
12020 case GL_ALPHA32F_EXT:
12021 return GL_FLOAT;
12022 case GL_LUMINANCE32F_EXT:
12023 return GL_FLOAT;
12024 case GL_LUMINANCE_ALPHA32F_EXT:
12025 return GL_FLOAT;
12026 case GL_RGBA16F_EXT:
12027 return GL_HALF_FLOAT_OES;
12028 case GL_RGB16F_EXT:
12029 return GL_HALF_FLOAT_OES;
12030 case GL_ALPHA16F_EXT:
12031 return GL_HALF_FLOAT_OES;
12032 case GL_LUMINANCE16F_EXT:
12033 return GL_HALF_FLOAT_OES;
12034 case GL_LUMINANCE_ALPHA16F_EXT:
12035 return GL_HALF_FLOAT_OES;
12036 case GL_BGRA8_EXT:
12037 return GL_UNSIGNED_BYTE;
12038 default:
12039 return GL_NONE;
12043 void GLES2DecoderImpl::DoTexStorage2DEXT(
12044 GLenum target,
12045 GLint levels,
12046 GLenum internal_format,
12047 GLsizei width,
12048 GLsizei height) {
12049 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT",
12050 "width", width, "height", height);
12051 if (!texture_manager()->ValidForTarget(target, 0, width, height, 1) ||
12052 TextureManager::ComputeMipMapCount(target, width, height, 1) < levels) {
12053 LOCAL_SET_GL_ERROR(
12054 GL_INVALID_VALUE, "glTexStorage2DEXT", "dimensions out of range");
12055 return;
12057 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
12058 &state_, target);
12059 if (!texture_ref) {
12060 LOCAL_SET_GL_ERROR(
12061 GL_INVALID_OPERATION,
12062 "glTexStorage2DEXT", "unknown texture for target");
12063 return;
12065 Texture* texture = texture_ref->texture();
12066 if (texture->IsAttachedToFramebuffer()) {
12067 framebuffer_state_.clear_state_dirty = true;
12069 if (texture->IsImmutable()) {
12070 LOCAL_SET_GL_ERROR(
12071 GL_INVALID_OPERATION,
12072 "glTexStorage2DEXT", "texture is immutable");
12073 return;
12076 GLenum format = ExtractFormatFromStorageFormat(internal_format);
12077 GLenum type = ExtractTypeFromStorageFormat(internal_format);
12080 GLsizei level_width = width;
12081 GLsizei level_height = height;
12082 uint32 estimated_size = 0;
12083 for (int ii = 0; ii < levels; ++ii) {
12084 uint32 level_size = 0;
12085 if (!GLES2Util::ComputeImageDataSizes(
12086 level_width, level_height, 1, format, type, state_.unpack_alignment,
12087 &estimated_size, NULL, NULL) ||
12088 !SafeAddUint32(estimated_size, level_size, &estimated_size)) {
12089 LOCAL_SET_GL_ERROR(
12090 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "dimensions too large");
12091 return;
12093 level_width = std::max(1, level_width >> 1);
12094 level_height = std::max(1, level_height >> 1);
12096 if (!EnsureGPUMemoryAvailable(estimated_size)) {
12097 LOCAL_SET_GL_ERROR(
12098 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "out of memory");
12099 return;
12103 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexStorage2DEXT");
12104 glTexStorage2DEXT(target, levels, internal_format, width, height);
12105 GLenum error = LOCAL_PEEK_GL_ERROR("glTexStorage2DEXT");
12106 if (error == GL_NO_ERROR) {
12107 GLsizei level_width = width;
12108 GLsizei level_height = height;
12109 for (int ii = 0; ii < levels; ++ii) {
12110 texture_manager()->SetLevelInfo(
12111 texture_ref, target, ii, format,
12112 level_width, level_height, 1, 0, format, type, false);
12113 level_width = std::max(1, level_width >> 1);
12114 level_height = std::max(1, level_height >> 1);
12116 texture->SetImmutable(true);
12120 error::Error GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
12121 uint32 immediate_data_size,
12122 const void* cmd_data) {
12123 return error::kUnknownCommand;
12126 void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target,
12127 const GLbyte* data) {
12128 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureCHROMIUM",
12129 "context", logger_.GetLogPrefix(),
12130 "mailbox[0]", static_cast<unsigned char>(data[0]));
12132 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
12133 &state_, target);
12134 ProduceTextureRef("glProduceTextureCHROMIUM", texture_ref, target, data);
12137 void GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM(GLuint client_id,
12138 GLenum target, const GLbyte* data) {
12139 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM",
12140 "context", logger_.GetLogPrefix(),
12141 "mailbox[0]", static_cast<unsigned char>(data[0]));
12143 ProduceTextureRef("glProduceTextureDirectCHROMIUM", GetTexture(client_id),
12144 target, data);
12147 void GLES2DecoderImpl::ProduceTextureRef(std::string func_name,
12148 TextureRef* texture_ref, GLenum target, const GLbyte* data) {
12149 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
12150 DLOG_IF(ERROR, !mailbox.Verify()) << func_name << " was passed a "
12151 "mailbox that was not generated by "
12152 "GenMailboxCHROMIUM.";
12154 if (!texture_ref) {
12155 LOCAL_SET_GL_ERROR(
12156 GL_INVALID_OPERATION, func_name.c_str(), "unknown texture for target");
12157 return;
12160 Texture* produced = texture_manager()->Produce(texture_ref);
12161 if (!produced) {
12162 LOCAL_SET_GL_ERROR(
12163 GL_INVALID_OPERATION, func_name.c_str(), "invalid texture");
12164 return;
12167 if (produced->target() != target) {
12168 LOCAL_SET_GL_ERROR(
12169 GL_INVALID_OPERATION, func_name.c_str(), "invalid target");
12170 return;
12173 group_->mailbox_manager()->ProduceTexture(mailbox, produced);
12176 void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target,
12177 const GLbyte* data) {
12178 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoConsumeTextureCHROMIUM",
12179 "context", logger_.GetLogPrefix(),
12180 "mailbox[0]", static_cast<unsigned char>(data[0]));
12181 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
12182 DLOG_IF(ERROR, !mailbox.Verify()) << "ConsumeTextureCHROMIUM was passed a "
12183 "mailbox that was not generated by "
12184 "GenMailboxCHROMIUM.";
12186 scoped_refptr<TextureRef> texture_ref =
12187 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
12188 if (!texture_ref.get()) {
12189 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
12190 "glConsumeTextureCHROMIUM",
12191 "unknown texture for target");
12192 return;
12194 GLuint client_id = texture_ref->client_id();
12195 if (!client_id) {
12196 LOCAL_SET_GL_ERROR(
12197 GL_INVALID_OPERATION,
12198 "glConsumeTextureCHROMIUM", "unknown texture for target");
12199 return;
12201 Texture* texture = group_->mailbox_manager()->ConsumeTexture(mailbox);
12202 if (!texture) {
12203 LOCAL_SET_GL_ERROR(
12204 GL_INVALID_OPERATION,
12205 "glConsumeTextureCHROMIUM", "invalid mailbox name");
12206 return;
12208 if (texture->target() != target) {
12209 LOCAL_SET_GL_ERROR(
12210 GL_INVALID_OPERATION,
12211 "glConsumeTextureCHROMIUM", "invalid target");
12212 return;
12215 DeleteTexturesHelper(1, &client_id);
12216 texture_ref = texture_manager()->Consume(client_id, texture);
12217 glBindTexture(target, texture_ref->service_id());
12219 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
12220 unit.bind_target = target;
12221 switch (target) {
12222 case GL_TEXTURE_2D:
12223 unit.bound_texture_2d = texture_ref;
12224 break;
12225 case GL_TEXTURE_CUBE_MAP:
12226 unit.bound_texture_cube_map = texture_ref;
12227 break;
12228 case GL_TEXTURE_EXTERNAL_OES:
12229 unit.bound_texture_external_oes = texture_ref;
12230 break;
12231 case GL_TEXTURE_RECTANGLE_ARB:
12232 unit.bound_texture_rectangle_arb = texture_ref;
12233 break;
12234 default:
12235 NOTREACHED(); // Validation should prevent us getting here.
12236 break;
12240 void GLES2DecoderImpl::EnsureTextureForClientId(
12241 GLenum target,
12242 GLuint client_id) {
12243 TextureRef* texture_ref = GetTexture(client_id);
12244 if (!texture_ref) {
12245 GLuint service_id;
12246 glGenTextures(1, &service_id);
12247 DCHECK_NE(0u, service_id);
12248 texture_ref = CreateTexture(client_id, service_id);
12249 texture_manager()->SetTarget(texture_ref, target);
12250 glBindTexture(target, service_id);
12251 RestoreCurrentTextureBindings(&state_, target);
12255 // If CreateAndConsumeTexture fails we still need to ensure that the client_id
12256 // provided is associated with a service_id/TextureRef for consistency, even if
12257 // the resulting texture is incomplete.
12258 error::Error GLES2DecoderImpl::HandleCreateAndConsumeTextureCHROMIUMImmediate(
12259 uint32_t immediate_data_size,
12260 const void* cmd_data) {
12261 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate& c =
12262 *static_cast<
12263 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate*>(
12264 cmd_data);
12265 GLenum target = static_cast<GLenum>(c.target);
12266 uint32_t data_size;
12267 if (!ComputeDataSize(1, sizeof(GLbyte), 64, &data_size)) {
12268 return error::kOutOfBounds;
12270 if (data_size > immediate_data_size) {
12271 return error::kOutOfBounds;
12273 const GLbyte* mailbox =
12274 GetImmediateDataAs<const GLbyte*>(c, data_size, immediate_data_size);
12275 if (!validators_->texture_bind_target.IsValid(target)) {
12276 LOCAL_SET_GL_ERROR_INVALID_ENUM(
12277 "glCreateAndConsumeTextureCHROMIUM", target, "target");
12278 return error::kNoError;
12280 if (mailbox == NULL) {
12281 return error::kOutOfBounds;
12283 uint32_t client_id = c.client_id;
12284 DoCreateAndConsumeTextureCHROMIUM(target, mailbox, client_id);
12285 return error::kNoError;
12288 void GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM(GLenum target,
12289 const GLbyte* data, GLuint client_id) {
12290 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM",
12291 "context", logger_.GetLogPrefix(),
12292 "mailbox[0]", static_cast<unsigned char>(data[0]));
12293 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
12294 DLOG_IF(ERROR, !mailbox.Verify()) << "CreateAndConsumeTextureCHROMIUM was "
12295 "passed a mailbox that was not "
12296 "generated by GenMailboxCHROMIUM.";
12298 TextureRef* texture_ref = GetTexture(client_id);
12299 if (texture_ref) {
12300 // No need to call EnsureTextureForClientId here, the client_id already has
12301 // an associated texture.
12302 LOCAL_SET_GL_ERROR(
12303 GL_INVALID_OPERATION,
12304 "glCreateAndConsumeTextureCHROMIUM", "client id already in use");
12305 return;
12307 Texture* texture = group_->mailbox_manager()->ConsumeTexture(mailbox);
12308 if (!texture) {
12309 EnsureTextureForClientId(target, client_id);
12310 LOCAL_SET_GL_ERROR(
12311 GL_INVALID_OPERATION,
12312 "glCreateAndConsumeTextureCHROMIUM", "invalid mailbox name");
12313 return;
12316 if (texture->target() != target) {
12317 EnsureTextureForClientId(target, client_id);
12318 LOCAL_SET_GL_ERROR(
12319 GL_INVALID_OPERATION,
12320 "glCreateAndConsumeTextureCHROMIUM", "invalid target");
12321 return;
12324 texture_ref = texture_manager()->Consume(client_id, texture);
12327 bool GLES2DecoderImpl::DoIsValuebufferCHROMIUM(GLuint client_id) {
12328 const Valuebuffer* valuebuffer = GetValuebuffer(client_id);
12329 return valuebuffer && valuebuffer->IsValid();
12332 void GLES2DecoderImpl::DoBindValueBufferCHROMIUM(GLenum target,
12333 GLuint client_id) {
12334 Valuebuffer* valuebuffer = NULL;
12335 if (client_id != 0) {
12336 valuebuffer = GetValuebuffer(client_id);
12337 if (!valuebuffer) {
12338 if (!group_->bind_generates_resource()) {
12339 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glBindValuebufferCHROMIUM",
12340 "id not generated by glBindValuebufferCHROMIUM");
12341 return;
12344 // It's a new id so make a valuebuffer for it.
12345 CreateValuebuffer(client_id);
12346 valuebuffer = GetValuebuffer(client_id);
12348 valuebuffer->MarkAsValid();
12350 state_.bound_valuebuffer = valuebuffer;
12353 void GLES2DecoderImpl::DoSubscribeValueCHROMIUM(GLenum target,
12354 GLenum subscription) {
12355 if (!CheckCurrentValuebuffer("glSubscribeValueCHROMIUM")) {
12356 return;
12358 state_.bound_valuebuffer.get()->AddSubscription(subscription);
12361 void GLES2DecoderImpl::DoPopulateSubscribedValuesCHROMIUM(GLenum target) {
12362 if (!CheckCurrentValuebuffer("glPopulateSubscribedValuesCHROMIUM")) {
12363 return;
12365 valuebuffer_manager()->UpdateValuebufferState(state_.bound_valuebuffer.get());
12368 void GLES2DecoderImpl::DoUniformValueBufferCHROMIUM(GLint location,
12369 GLenum target,
12370 GLenum subscription) {
12371 if (!CheckCurrentValuebufferForSubscription(
12372 subscription, "glPopulateSubscribedValuesCHROMIUM")) {
12373 return;
12375 if (!CheckSubscriptionTarget(location, subscription,
12376 "glPopulateSubscribedValuesCHROMIUM")) {
12377 return;
12379 const ValueState* state =
12380 state_.bound_valuebuffer.get()->GetState(subscription);
12381 if (state) {
12382 switch (subscription) {
12383 case GL_MOUSE_POSITION_CHROMIUM:
12384 DoUniform2iv(location, 1, state->int_value);
12385 break;
12386 default:
12387 NOTREACHED() << "Unhandled uniform subscription target "
12388 << subscription;
12389 break;
12394 void GLES2DecoderImpl::DoInsertEventMarkerEXT(
12395 GLsizei length, const GLchar* marker) {
12396 if (!marker) {
12397 marker = "";
12399 debug_marker_manager_.SetMarker(
12400 length ? std::string(marker, length) : std::string(marker));
12403 void GLES2DecoderImpl::DoPushGroupMarkerEXT(
12404 GLsizei length, const GLchar* marker) {
12405 if (!marker) {
12406 marker = "";
12408 std::string name = length ? std::string(marker, length) : std::string(marker);
12409 debug_marker_manager_.PushGroup(name);
12410 gpu_tracer_->Begin(TRACE_DISABLED_BY_DEFAULT("gpu_group_marker"), name,
12411 kTraceGroupMarker);
12414 void GLES2DecoderImpl::DoPopGroupMarkerEXT(void) {
12415 debug_marker_manager_.PopGroup();
12416 gpu_tracer_->End(kTraceGroupMarker);
12419 void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(
12420 GLenum target, GLint image_id) {
12421 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM");
12423 if (target == GL_TEXTURE_CUBE_MAP) {
12424 LOCAL_SET_GL_ERROR(
12425 GL_INVALID_ENUM,
12426 "glBindTexImage2DCHROMIUM", "invalid target");
12427 return;
12430 // Default target might be conceptually valid, but disallow it to avoid
12431 // accidents.
12432 TextureRef* texture_ref =
12433 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
12434 if (!texture_ref) {
12435 LOCAL_SET_GL_ERROR(
12436 GL_INVALID_OPERATION,
12437 "glBindTexImage2DCHROMIUM", "no texture bound");
12438 return;
12441 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
12442 if (!gl_image) {
12443 LOCAL_SET_GL_ERROR(
12444 GL_INVALID_OPERATION,
12445 "glBindTexImage2DCHROMIUM", "no image found with the given ID");
12446 return;
12450 ScopedGLErrorSuppressor suppressor(
12451 "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", GetErrorState());
12452 if (!gl_image->BindTexImage(target)) {
12453 LOCAL_SET_GL_ERROR(
12454 GL_INVALID_OPERATION,
12455 "glBindTexImage2DCHROMIUM", "fail to bind image with the given ID");
12456 return;
12460 gfx::Size size = gl_image->GetSize();
12461 texture_manager()->SetLevelInfo(
12462 texture_ref, target, 0, GL_RGBA, size.width(), size.height(), 1, 0,
12463 GL_RGBA, GL_UNSIGNED_BYTE, true);
12464 texture_manager()->SetLevelImage(texture_ref, target, 0, gl_image);
12467 void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(
12468 GLenum target, GLint image_id) {
12469 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM");
12471 // Default target might be conceptually valid, but disallow it to avoid
12472 // accidents.
12473 TextureRef* texture_ref =
12474 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
12475 if (!texture_ref) {
12476 LOCAL_SET_GL_ERROR(
12477 GL_INVALID_OPERATION,
12478 "glReleaseTexImage2DCHROMIUM", "no texture bound");
12479 return;
12482 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
12483 if (!gl_image) {
12484 LOCAL_SET_GL_ERROR(
12485 GL_INVALID_OPERATION,
12486 "glReleaseTexImage2DCHROMIUM", "no image found with the given ID");
12487 return;
12490 // Do nothing when image is not currently bound.
12491 if (texture_ref->texture()->GetLevelImage(target, 0) != gl_image)
12492 return;
12495 ScopedGLErrorSuppressor suppressor(
12496 "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", GetErrorState());
12497 gl_image->ReleaseTexImage(target);
12500 texture_manager()->SetLevelInfo(
12501 texture_ref, target, 0, GL_RGBA, 0, 0, 1, 0,
12502 GL_RGBA, GL_UNSIGNED_BYTE, false);
12505 error::Error GLES2DecoderImpl::HandleTraceBeginCHROMIUM(
12506 uint32 immediate_data_size,
12507 const void* cmd_data) {
12508 const gles2::cmds::TraceBeginCHROMIUM& c =
12509 *static_cast<const gles2::cmds::TraceBeginCHROMIUM*>(cmd_data);
12510 Bucket* category_bucket = GetBucket(c.category_bucket_id);
12511 Bucket* name_bucket = GetBucket(c.name_bucket_id);
12512 if (!category_bucket || category_bucket->size() == 0 ||
12513 !name_bucket || name_bucket->size() == 0) {
12514 return error::kInvalidArguments;
12517 std::string category_name;
12518 std::string trace_name;
12519 if (!category_bucket->GetAsString(&category_name) ||
12520 !name_bucket->GetAsString(&trace_name)) {
12521 return error::kInvalidArguments;
12524 if (!gpu_tracer_->Begin(category_name, trace_name, kTraceCHROMIUM)) {
12525 LOCAL_SET_GL_ERROR(
12526 GL_INVALID_OPERATION,
12527 "glTraceBeginCHROMIUM", "unable to create begin trace");
12528 return error::kNoError;
12530 return error::kNoError;
12533 void GLES2DecoderImpl::DoTraceEndCHROMIUM() {
12534 if (!gpu_tracer_->End(kTraceCHROMIUM)) {
12535 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
12536 "glTraceEndCHROMIUM", "no trace begin found");
12537 return;
12541 void GLES2DecoderImpl::DoDrawBuffersEXT(
12542 GLsizei count, const GLenum* bufs) {
12543 if (count > static_cast<GLsizei>(group_->max_draw_buffers())) {
12544 LOCAL_SET_GL_ERROR(
12545 GL_INVALID_VALUE,
12546 "glDrawBuffersEXT", "greater than GL_MAX_DRAW_BUFFERS_EXT");
12547 return;
12550 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
12551 if (framebuffer) {
12552 for (GLsizei i = 0; i < count; ++i) {
12553 if (bufs[i] != static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i) &&
12554 bufs[i] != GL_NONE) {
12555 LOCAL_SET_GL_ERROR(
12556 GL_INVALID_OPERATION,
12557 "glDrawBuffersEXT",
12558 "bufs[i] not GL_NONE or GL_COLOR_ATTACHMENTi_EXT");
12559 return;
12562 glDrawBuffersARB(count, bufs);
12563 framebuffer->SetDrawBuffers(count, bufs);
12564 } else { // backbuffer
12565 if (count > 1 ||
12566 (bufs[0] != GL_BACK && bufs[0] != GL_NONE)) {
12567 LOCAL_SET_GL_ERROR(
12568 GL_INVALID_OPERATION,
12569 "glDrawBuffersEXT",
12570 "more than one buffer or bufs not GL_NONE or GL_BACK");
12571 return;
12573 GLenum mapped_buf = bufs[0];
12574 if (GetBackbufferServiceId() != 0 && // emulated backbuffer
12575 bufs[0] == GL_BACK) {
12576 mapped_buf = GL_COLOR_ATTACHMENT0;
12578 glDrawBuffersARB(count, &mapped_buf);
12579 group_->set_draw_buffer(bufs[0]);
12583 void GLES2DecoderImpl::DoLoseContextCHROMIUM(GLenum current, GLenum other) {
12584 MarkContextLost(GetContextLostReasonFromResetStatus(current));
12585 group_->LoseContexts(GetContextLostReasonFromResetStatus(other));
12586 reset_by_robustness_extension_ = true;
12589 void GLES2DecoderImpl::DoMatrixLoadfCHROMIUM(GLenum matrix_mode,
12590 const GLfloat* matrix) {
12591 DCHECK(matrix_mode == GL_PATH_PROJECTION_CHROMIUM ||
12592 matrix_mode == GL_PATH_MODELVIEW_CHROMIUM);
12593 if (!features().chromium_path_rendering) {
12594 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
12595 "glMatrixLoadfCHROMIUM",
12596 "function not available");
12597 return;
12600 GLfloat* target_matrix = matrix_mode == GL_PATH_PROJECTION_CHROMIUM
12601 ? state_.projection_matrix
12602 : state_.modelview_matrix;
12603 memcpy(target_matrix, matrix, sizeof(GLfloat) * 16);
12604 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
12605 // since the values of the _NV and _CHROMIUM tokens match.
12606 glMatrixLoadfEXT(matrix_mode, matrix);
12609 void GLES2DecoderImpl::DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode) {
12610 DCHECK(matrix_mode == GL_PATH_PROJECTION_CHROMIUM ||
12611 matrix_mode == GL_PATH_MODELVIEW_CHROMIUM);
12613 if (!features().chromium_path_rendering) {
12614 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
12615 "glMatrixLoadIdentityCHROMIUM",
12616 "function not available");
12617 return;
12620 GLfloat* target_matrix = matrix_mode == GL_PATH_PROJECTION_CHROMIUM
12621 ? state_.projection_matrix
12622 : state_.modelview_matrix;
12623 memcpy(target_matrix, kIdentityMatrix, sizeof(kIdentityMatrix));
12624 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
12625 // since the values of the _NV and _CHROMIUM tokens match.
12626 glMatrixLoadIdentityEXT(matrix_mode);
12629 bool GLES2DecoderImpl::ValidateAsyncTransfer(
12630 const char* function_name,
12631 TextureRef* texture_ref,
12632 GLenum target,
12633 GLint level,
12634 const void * data) {
12635 // We only support async uploads to 2D textures for now.
12636 if (GL_TEXTURE_2D != target) {
12637 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
12638 return false;
12640 // We only support uploads to level zero for now.
12641 if (level != 0) {
12642 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "level != 0");
12643 return false;
12645 // A transfer buffer must be bound, even for asyncTexImage2D.
12646 if (data == NULL) {
12647 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, "buffer == 0");
12648 return false;
12650 // We only support one async transfer in progress.
12651 if (!texture_ref ||
12652 async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
12653 LOCAL_SET_GL_ERROR(
12654 GL_INVALID_OPERATION,
12655 function_name, "transfer already in progress");
12656 return false;
12658 return true;
12661 base::Closure GLES2DecoderImpl::AsyncUploadTokenCompletionClosure(
12662 uint32 async_upload_token,
12663 uint32 sync_data_shm_id,
12664 uint32 sync_data_shm_offset) {
12665 scoped_refptr<gpu::Buffer> buffer = GetSharedMemoryBuffer(sync_data_shm_id);
12666 if (!buffer.get() ||
12667 !buffer->GetDataAddress(sync_data_shm_offset, sizeof(AsyncUploadSync)))
12668 return base::Closure();
12670 AsyncMemoryParams mem_params(buffer,
12671 sync_data_shm_offset,
12672 sizeof(AsyncUploadSync));
12674 scoped_refptr<AsyncUploadTokenCompletionObserver> observer(
12675 new AsyncUploadTokenCompletionObserver(async_upload_token));
12677 return base::Bind(
12678 &AsyncPixelTransferManager::AsyncNotifyCompletion,
12679 base::Unretained(GetAsyncPixelTransferManager()),
12680 mem_params,
12681 observer);
12684 error::Error GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM(
12685 uint32 immediate_data_size,
12686 const void* cmd_data) {
12687 const gles2::cmds::AsyncTexImage2DCHROMIUM& c =
12688 *static_cast<const gles2::cmds::AsyncTexImage2DCHROMIUM*>(cmd_data);
12689 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM");
12690 GLenum target = static_cast<GLenum>(c.target);
12691 GLint level = static_cast<GLint>(c.level);
12692 GLenum internal_format = static_cast<GLenum>(c.internalformat);
12693 GLsizei width = static_cast<GLsizei>(c.width);
12694 GLsizei height = static_cast<GLsizei>(c.height);
12695 GLint border = static_cast<GLint>(c.border);
12696 GLenum format = static_cast<GLenum>(c.format);
12697 GLenum type = static_cast<GLenum>(c.type);
12698 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
12699 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
12700 uint32 pixels_size;
12701 uint32 async_upload_token = static_cast<uint32>(c.async_upload_token);
12702 uint32 sync_data_shm_id = static_cast<uint32>(c.sync_data_shm_id);
12703 uint32 sync_data_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
12705 base::ScopedClosureRunner scoped_completion_callback;
12706 if (async_upload_token) {
12707 base::Closure completion_closure =
12708 AsyncUploadTokenCompletionClosure(async_upload_token,
12709 sync_data_shm_id,
12710 sync_data_shm_offset);
12711 if (completion_closure.is_null())
12712 return error::kInvalidArguments;
12714 scoped_completion_callback.Reset(completion_closure);
12717 // TODO(epenner): Move this and copies of this memory validation
12718 // into ValidateTexImage2D step.
12719 if (!GLES2Util::ComputeImageDataSizes(
12720 width, height, 1, format, type, state_.unpack_alignment, &pixels_size,
12721 NULL, NULL)) {
12722 return error::kOutOfBounds;
12724 const void* pixels = NULL;
12725 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
12726 pixels = GetSharedMemoryAs<const void*>(
12727 pixels_shm_id, pixels_shm_offset, pixels_size);
12728 if (!pixels) {
12729 return error::kOutOfBounds;
12733 TextureManager::DoTextImage2DArguments args = {
12734 target, level, internal_format, width, height, border, format, type,
12735 pixels, pixels_size};
12736 TextureRef* texture_ref;
12737 // All the normal glTexSubImage2D validation.
12738 if (!texture_manager()->ValidateTexImage2D(
12739 &state_, "glAsyncTexImage2DCHROMIUM", args, &texture_ref)) {
12740 return error::kNoError;
12743 // Extra async validation.
12744 Texture* texture = texture_ref->texture();
12745 if (!ValidateAsyncTransfer(
12746 "glAsyncTexImage2DCHROMIUM", texture_ref, target, level, pixels))
12747 return error::kNoError;
12749 // Don't allow async redefinition of a textures.
12750 if (texture->IsDefined()) {
12751 LOCAL_SET_GL_ERROR(
12752 GL_INVALID_OPERATION,
12753 "glAsyncTexImage2DCHROMIUM", "already defined");
12754 return error::kNoError;
12757 if (!EnsureGPUMemoryAvailable(pixels_size)) {
12758 LOCAL_SET_GL_ERROR(
12759 GL_OUT_OF_MEMORY, "glAsyncTexImage2DCHROMIUM", "out of memory");
12760 return error::kNoError;
12763 // Setup the parameters.
12764 AsyncTexImage2DParams tex_params = {
12765 target, level, static_cast<GLenum>(internal_format),
12766 width, height, border, format, type};
12767 AsyncMemoryParams mem_params(
12768 GetSharedMemoryBuffer(c.pixels_shm_id), c.pixels_shm_offset, pixels_size);
12770 // Set up the async state if needed, and make the texture
12771 // immutable so the async state stays valid. The level info
12772 // is set up lazily when the transfer completes.
12773 AsyncPixelTransferDelegate* delegate =
12774 async_pixel_transfer_manager_->CreatePixelTransferDelegate(texture_ref,
12775 tex_params);
12776 texture->SetImmutable(true);
12778 delegate->AsyncTexImage2D(
12779 tex_params,
12780 mem_params,
12781 base::Bind(&TextureManager::SetLevelInfoFromParams,
12782 // The callback is only invoked if the transfer delegate still
12783 // exists, which implies through manager->texture_ref->state
12784 // ownership that both of these pointers are valid.
12785 base::Unretained(texture_manager()),
12786 base::Unretained(texture_ref),
12787 tex_params));
12788 return error::kNoError;
12791 error::Error GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM(
12792 uint32 immediate_data_size,
12793 const void* cmd_data) {
12794 const gles2::cmds::AsyncTexSubImage2DCHROMIUM& c =
12795 *static_cast<const gles2::cmds::AsyncTexSubImage2DCHROMIUM*>(cmd_data);
12796 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM");
12797 GLenum target = static_cast<GLenum>(c.target);
12798 GLint level = static_cast<GLint>(c.level);
12799 GLint xoffset = static_cast<GLint>(c.xoffset);
12800 GLint yoffset = static_cast<GLint>(c.yoffset);
12801 GLsizei width = static_cast<GLsizei>(c.width);
12802 GLsizei height = static_cast<GLsizei>(c.height);
12803 GLenum format = static_cast<GLenum>(c.format);
12804 GLenum type = static_cast<GLenum>(c.type);
12805 uint32 async_upload_token = static_cast<uint32>(c.async_upload_token);
12806 uint32 sync_data_shm_id = static_cast<uint32>(c.sync_data_shm_id);
12807 uint32 sync_data_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
12809 base::ScopedClosureRunner scoped_completion_callback;
12810 if (async_upload_token) {
12811 base::Closure completion_closure =
12812 AsyncUploadTokenCompletionClosure(async_upload_token,
12813 sync_data_shm_id,
12814 sync_data_shm_offset);
12815 if (completion_closure.is_null())
12816 return error::kInvalidArguments;
12818 scoped_completion_callback.Reset(completion_closure);
12821 // TODO(epenner): Move this and copies of this memory validation
12822 // into ValidateTexSubImage2D step.
12823 uint32 data_size;
12824 if (!GLES2Util::ComputeImageDataSizes(
12825 width, height, 1, format, type, state_.unpack_alignment, &data_size,
12826 NULL, NULL)) {
12827 return error::kOutOfBounds;
12829 const void* pixels = GetSharedMemoryAs<const void*>(
12830 c.data_shm_id, c.data_shm_offset, data_size);
12832 // All the normal glTexSubImage2D validation.
12833 error::Error error = error::kNoError;
12834 if (!ValidateTexSubImage2D(&error, "glAsyncTexSubImage2DCHROMIUM",
12835 target, level, xoffset, yoffset, width, height, format, type, pixels)) {
12836 return error;
12839 // Extra async validation.
12840 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
12841 &state_, target);
12842 Texture* texture = texture_ref->texture();
12843 if (!ValidateAsyncTransfer(
12844 "glAsyncTexSubImage2DCHROMIUM", texture_ref, target, level, pixels))
12845 return error::kNoError;
12847 // Guarantee async textures are always 'cleared' as follows:
12848 // - AsyncTexImage2D can not redefine an existing texture
12849 // - AsyncTexImage2D must initialize the entire image via non-null buffer.
12850 // - AsyncTexSubImage2D clears synchronously if not already cleared.
12851 // - Textures become immutable after an async call.
12852 // This way we know in all cases that an async texture is always clear.
12853 if (!texture->SafeToRenderFrom()) {
12854 if (!texture_manager()->ClearTextureLevel(this, texture_ref,
12855 target, level)) {
12856 LOCAL_SET_GL_ERROR(
12857 GL_OUT_OF_MEMORY,
12858 "glAsyncTexSubImage2DCHROMIUM", "dimensions too big");
12859 return error::kNoError;
12863 // Setup the parameters.
12864 AsyncTexSubImage2DParams tex_params = {target, level, xoffset, yoffset,
12865 width, height, format, type};
12866 AsyncMemoryParams mem_params(
12867 GetSharedMemoryBuffer(c.data_shm_id), c.data_shm_offset, data_size);
12868 AsyncPixelTransferDelegate* delegate =
12869 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
12870 if (!delegate) {
12871 // TODO(epenner): We may want to enforce exclusive use
12872 // of async APIs in which case this should become an error,
12873 // (the texture should have been async defined).
12874 AsyncTexImage2DParams define_params = {target, level,
12875 0, 0, 0, 0, 0, 0};
12876 texture->GetLevelSize(
12877 target, level, &define_params.width, &define_params.height, nullptr);
12878 texture->GetLevelType(
12879 target, level, &define_params.type, &define_params.internal_format);
12880 // Set up the async state if needed, and make the texture
12881 // immutable so the async state stays valid.
12882 delegate = async_pixel_transfer_manager_->CreatePixelTransferDelegate(
12883 texture_ref, define_params);
12884 texture->SetImmutable(true);
12887 delegate->AsyncTexSubImage2D(tex_params, mem_params);
12888 return error::kNoError;
12891 error::Error GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM(
12892 uint32 immediate_data_size,
12893 const void* cmd_data) {
12894 const gles2::cmds::WaitAsyncTexImage2DCHROMIUM& c =
12895 *static_cast<const gles2::cmds::WaitAsyncTexImage2DCHROMIUM*>(cmd_data);
12896 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
12897 GLenum target = static_cast<GLenum>(c.target);
12899 if (GL_TEXTURE_2D != target) {
12900 LOCAL_SET_GL_ERROR(
12901 GL_INVALID_ENUM, "glWaitAsyncTexImage2DCHROMIUM", "target");
12902 return error::kNoError;
12904 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
12905 &state_, target);
12906 if (!texture_ref) {
12907 LOCAL_SET_GL_ERROR(
12908 GL_INVALID_OPERATION,
12909 "glWaitAsyncTexImage2DCHROMIUM", "unknown texture");
12910 return error::kNoError;
12912 AsyncPixelTransferDelegate* delegate =
12913 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
12914 if (!delegate) {
12915 LOCAL_SET_GL_ERROR(
12916 GL_INVALID_OPERATION,
12917 "glWaitAsyncTexImage2DCHROMIUM", "No async transfer started");
12918 return error::kNoError;
12920 delegate->WaitForTransferCompletion();
12921 ProcessFinishedAsyncTransfers();
12922 return error::kNoError;
12925 error::Error GLES2DecoderImpl::HandleWaitAllAsyncTexImage2DCHROMIUM(
12926 uint32 immediate_data_size,
12927 const void* data) {
12928 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
12930 GetAsyncPixelTransferManager()->WaitAllAsyncTexImage2D();
12931 ProcessFinishedAsyncTransfers();
12932 return error::kNoError;
12935 error::Error GLES2DecoderImpl::HandleUniformBlockBinding(
12936 uint32_t immediate_data_size, const void* cmd_data) {
12937 if (!unsafe_es3_apis_enabled())
12938 return error::kUnknownCommand;
12939 const gles2::cmds::UniformBlockBinding& c =
12940 *static_cast<const gles2::cmds::UniformBlockBinding*>(cmd_data);
12941 GLuint client_id = c.program;
12942 GLuint index = static_cast<GLuint>(c.index);
12943 GLuint binding = static_cast<GLuint>(c.binding);
12944 Program* program = GetProgramInfoNotShader(
12945 client_id, "glUniformBlockBinding");
12946 if (!program) {
12947 return error::kNoError;
12949 GLuint service_id = program->service_id();
12950 glUniformBlockBinding(service_id, index, binding);
12951 return error::kNoError;
12954 error::Error GLES2DecoderImpl::HandleClientWaitSync(
12955 uint32_t immediate_data_size, const void* cmd_data) {
12956 if (!unsafe_es3_apis_enabled())
12957 return error::kUnknownCommand;
12958 const gles2::cmds::ClientWaitSync& c =
12959 *static_cast<const gles2::cmds::ClientWaitSync*>(cmd_data);
12960 GLuint sync = static_cast<GLuint>(c.sync);
12961 GLbitfield flags = static_cast<GLbitfield>(c.flags);
12962 GLuint64 timeout = GLES2Util::MapTwoUint32ToUint64(c.timeout_0, c.timeout_1);
12963 typedef cmds::ClientWaitSync::Result Result;
12964 Result* result_dst = GetSharedMemoryAs<Result*>(
12965 c.result_shm_id, c.result_shm_offset, sizeof(*result_dst));
12966 if (!result_dst) {
12967 return error::kOutOfBounds;
12969 if (*result_dst != GL_WAIT_FAILED) {
12970 return error::kInvalidArguments;
12972 GLsync service_sync = 0;
12973 if (!group_->GetSyncServiceId(sync, &service_sync)) {
12974 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "ClientWaitSync", "invalid sync");
12975 return error::kNoError;
12977 *result_dst = glClientWaitSync(service_sync, flags, timeout);
12978 return error::kNoError;
12981 error::Error GLES2DecoderImpl::HandleWaitSync(
12982 uint32_t immediate_data_size, const void* cmd_data) {
12983 if (!unsafe_es3_apis_enabled())
12984 return error::kUnknownCommand;
12985 const gles2::cmds::WaitSync& c =
12986 *static_cast<const gles2::cmds::WaitSync*>(cmd_data);
12987 GLuint sync = static_cast<GLuint>(c.sync);
12988 GLbitfield flags = static_cast<GLbitfield>(c.flags);
12989 GLuint64 timeout = GLES2Util::MapTwoUint32ToUint64(c.timeout_0, c.timeout_1);
12990 GLsync service_sync = 0;
12991 if (!group_->GetSyncServiceId(sync, &service_sync)) {
12992 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "WaitSync", "invalid sync");
12993 return error::kNoError;
12995 glWaitSync(service_sync, flags, timeout);
12996 return error::kNoError;
12999 error::Error GLES2DecoderImpl::HandleMapBufferRange(
13000 uint32_t immediate_data_size, const void* cmd_data) {
13001 if (!unsafe_es3_apis_enabled()) {
13002 return error::kUnknownCommand;
13004 const gles2::cmds::MapBufferRange& c =
13005 *static_cast<const gles2::cmds::MapBufferRange*>(cmd_data);
13006 GLenum target = static_cast<GLenum>(c.target);
13007 GLbitfield access = static_cast<GLbitfield>(c.access);
13008 GLintptr offset = static_cast<GLintptr>(c.offset);
13009 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
13011 typedef cmds::MapBufferRange::Result Result;
13012 Result* result = GetSharedMemoryAs<Result*>(
13013 c.result_shm_id, c.result_shm_offset, sizeof(*result));
13014 if (!result) {
13015 return error::kOutOfBounds;
13017 if (*result != 0) {
13018 *result = 0;
13019 return error::kInvalidArguments;
13021 int8_t* mem =
13022 GetSharedMemoryAs<int8_t*>(c.data_shm_id, c.data_shm_offset, size);
13023 if (!mem) {
13024 return error::kOutOfBounds;
13027 GLbitfield mask = GL_MAP_INVALIDATE_BUFFER_BIT;
13028 if ((access & mask) == mask) {
13029 // TODO(zmo): To be on the safe side, always map
13030 // GL_MAP_INVALIDATE_BUFFER_BIT to GL_MAP_INVALIDATE_RANGE_BIT.
13031 access = (access & ~GL_MAP_INVALIDATE_BUFFER_BIT);
13032 access = (access | GL_MAP_INVALIDATE_RANGE_BIT);
13034 // TODO(zmo): Always filter out GL_MAP_UNSYNCHRONIZED_BIT to get rid of
13035 // undefined behaviors.
13036 mask = GL_MAP_READ_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
13037 if ((access & mask) == mask) {
13038 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "MapBufferRange",
13039 "incompatible access bits");
13040 return error::kNoError;
13042 access = (access & ~GL_MAP_UNSYNCHRONIZED_BIT);
13043 if ((access & GL_MAP_WRITE_BIT) == GL_MAP_WRITE_BIT &&
13044 (access & GL_MAP_INVALIDATE_RANGE_BIT) == 0) {
13045 access = (access | GL_MAP_READ_BIT);
13047 void* ptr = glMapBufferRange(target, offset, size, access);
13048 if (ptr == nullptr) {
13049 return error::kNoError;
13051 Buffer* buffer = buffer_manager()->GetBufferInfoForTarget(&state_, target);
13052 DCHECK(buffer);
13053 buffer->SetMappedRange(offset, size, access, ptr,
13054 GetSharedMemoryBuffer(c.data_shm_id));
13055 if ((access & GL_MAP_INVALIDATE_RANGE_BIT) == 0) {
13056 memcpy(mem, ptr, size);
13058 *result = 1;
13059 return error::kNoError;
13062 error::Error GLES2DecoderImpl::HandleUnmapBuffer(
13063 uint32_t immediate_data_size, const void* cmd_data) {
13064 if (!unsafe_es3_apis_enabled()) {
13065 return error::kUnknownCommand;
13067 const gles2::cmds::UnmapBuffer& c =
13068 *static_cast<const gles2::cmds::UnmapBuffer*>(cmd_data);
13069 GLenum target = static_cast<GLenum>(c.target);
13071 Buffer* buffer = buffer_manager()->GetBufferInfoForTarget(&state_, target);
13072 if (!buffer) {
13073 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "UnmapBuffer", "no buffer bound");
13074 return error::kNoError;
13076 const Buffer::MappedRange* mapped_range = buffer->GetMappedRange();
13077 if (!mapped_range) {
13078 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "UnmapBuffer",
13079 "buffer is unmapped");
13080 return error::kNoError;
13082 if ((mapped_range->access & GL_MAP_WRITE_BIT) == 0 ||
13083 (mapped_range->access & GL_MAP_FLUSH_EXPLICIT_BIT) ==
13084 GL_MAP_FLUSH_EXPLICIT_BIT) {
13085 // If we don't need to write back, or explict flush is required, no copying
13086 // back is needed.
13087 } else {
13088 void* mem = mapped_range->GetShmPointer();
13089 if (!mem) {
13090 return error::kOutOfBounds;
13092 DCHECK(mapped_range->pointer);
13093 memcpy(mapped_range->pointer, mem, mapped_range->size);
13095 buffer->RemoveMappedRange();
13096 GLboolean rt = glUnmapBuffer(target);
13097 if (rt == GL_FALSE) {
13098 // At this point, we have already done the necessary validation, so
13099 // GL_FALSE indicates data corruption.
13100 // TODO(zmo): We could redo the map / copy data / unmap to recover, but
13101 // the second unmap could still return GL_FALSE. For now, we simply lose
13102 // the contexts in the share group.
13103 LOG(ERROR) << "glUnmapBuffer unexpectedly returned GL_FALSE";
13104 // Need to lose current context before broadcasting!
13105 MarkContextLost(error::kGuilty);
13106 group_->LoseContexts(error::kInnocent);
13107 return error::kLostContext;
13109 return error::kNoError;
13112 void GLES2DecoderImpl::OnTextureRefDetachedFromFramebuffer(
13113 TextureRef* texture_ref) {
13114 Texture* texture = texture_ref->texture();
13115 DoDidUseTexImageIfNeeded(texture, texture->target());
13118 // Note that GL_LOST_CONTEXT is specific to GLES.
13119 // For desktop GL we have to query the reset status proactively.
13120 void GLES2DecoderImpl::OnContextLostError() {
13121 if (!WasContextLost()) {
13122 // Need to lose current context before broadcasting!
13123 CheckResetStatus();
13124 group_->LoseContexts(error::kUnknown);
13125 reset_by_robustness_extension_ = true;
13129 void GLES2DecoderImpl::OnOutOfMemoryError() {
13130 if (lose_context_when_out_of_memory_ && !WasContextLost()) {
13131 error::ContextLostReason other = error::kOutOfMemory;
13132 if (CheckResetStatus()) {
13133 other = error::kUnknown;
13134 } else {
13135 // Need to lose current context before broadcasting!
13136 MarkContextLost(error::kOutOfMemory);
13138 group_->LoseContexts(other);
13142 // Include the auto-generated part of this file. We split this because it means
13143 // we can easily edit the non-auto generated parts right here in this file
13144 // instead of having to edit some template or the code generator.
13145 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
13147 } // namespace gles2
13148 } // namespace gpu