Don't add an aura tooltip to bubble close buttons on Windows.
[chromium-blink-merge.git] / gpu / command_buffer / service / gles2_cmd_decoder.cc
blob6ed2f8948c338d4211f4f1e1067c2d734b0c9a08
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
7 #include <stdio.h>
9 #include <algorithm>
10 #include <list>
11 #include <map>
12 #include <queue>
13 #include <stack>
14 #include <string>
15 #include <vector>
17 #include "base/at_exit.h"
18 #include "base/bind.h"
19 #include "base/callback_helpers.h"
20 #include "base/command_line.h"
21 #include "base/float_util.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 // TODO(gman): Cache these pointers?
764 BufferManager* buffer_manager() {
765 return group_->buffer_manager();
768 RenderbufferManager* renderbuffer_manager() {
769 return group_->renderbuffer_manager();
772 FramebufferManager* framebuffer_manager() {
773 return group_->framebuffer_manager();
776 ValuebufferManager* valuebuffer_manager() {
777 return group_->valuebuffer_manager();
780 ProgramManager* program_manager() {
781 return group_->program_manager();
784 ShaderManager* shader_manager() {
785 return group_->shader_manager();
788 ShaderTranslatorCache* shader_translator_cache() {
789 return group_->shader_translator_cache();
792 const TextureManager* texture_manager() const {
793 return group_->texture_manager();
796 TextureManager* texture_manager() {
797 return group_->texture_manager();
800 MailboxManager* mailbox_manager() {
801 return group_->mailbox_manager();
804 ImageManager* image_manager() { return image_manager_.get(); }
806 VertexArrayManager* vertex_array_manager() {
807 return vertex_array_manager_.get();
810 MemoryTracker* memory_tracker() {
811 return group_->memory_tracker();
814 bool EnsureGPUMemoryAvailable(size_t estimated_size) {
815 MemoryTracker* tracker = memory_tracker();
816 if (tracker) {
817 return tracker->EnsureGPUMemoryAvailable(estimated_size);
819 return true;
822 bool IsOffscreenBufferMultisampled() const {
823 return offscreen_target_samples_ > 1;
826 // Creates a Texture for the given texture.
827 TextureRef* CreateTexture(
828 GLuint client_id, GLuint service_id) {
829 return texture_manager()->CreateTexture(client_id, service_id);
832 // Gets the texture info for the given texture. Returns NULL if none exists.
833 TextureRef* GetTexture(GLuint client_id) const {
834 return texture_manager()->GetTexture(client_id);
837 // Deletes the texture info for the given texture.
838 void RemoveTexture(GLuint client_id) {
839 texture_manager()->RemoveTexture(client_id);
842 // Get the size (in pixels) of the currently bound frame buffer (either FBO
843 // or regular back buffer).
844 gfx::Size GetBoundReadFrameBufferSize();
846 // Get the format of the currently bound frame buffer (either FBO or regular
847 // back buffer)
848 GLenum GetBoundReadFrameBufferTextureType();
849 GLenum GetBoundReadFrameBufferInternalFormat();
850 GLenum GetBoundDrawFrameBufferInternalFormat();
852 // Wrapper for CompressedTexImage2D commands.
853 error::Error DoCompressedTexImage2D(
854 GLenum target,
855 GLint level,
856 GLenum internal_format,
857 GLsizei width,
858 GLsizei height,
859 GLint border,
860 GLsizei image_size,
861 const void* data);
863 // Wrapper for CompressedTexSubImage2D.
864 void DoCompressedTexSubImage2D(
865 GLenum target,
866 GLint level,
867 GLint xoffset,
868 GLint yoffset,
869 GLsizei width,
870 GLsizei height,
871 GLenum format,
872 GLsizei imageSize,
873 const void * data);
875 // Wrapper for CopyTexImage2D.
876 void DoCopyTexImage2D(
877 GLenum target,
878 GLint level,
879 GLenum internal_format,
880 GLint x,
881 GLint y,
882 GLsizei width,
883 GLsizei height,
884 GLint border);
886 // Wrapper for SwapBuffers.
887 void DoSwapBuffers();
889 // Wrapper for SwapInterval.
890 void DoSwapInterval(int interval);
892 // Wrapper for CopyTexSubImage2D.
893 void DoCopyTexSubImage2D(
894 GLenum target,
895 GLint level,
896 GLint xoffset,
897 GLint yoffset,
898 GLint x,
899 GLint y,
900 GLsizei width,
901 GLsizei height);
903 // Validation for TexSubImage2D.
904 bool ValidateTexSubImage2D(
905 error::Error* error,
906 const char* function_name,
907 GLenum target,
908 GLint level,
909 GLint xoffset,
910 GLint yoffset,
911 GLsizei width,
912 GLsizei height,
913 GLenum format,
914 GLenum type,
915 const void * data);
917 // Wrapper for TexSubImage2D.
918 error::Error DoTexSubImage2D(
919 GLenum target,
920 GLint level,
921 GLint xoffset,
922 GLint yoffset,
923 GLsizei width,
924 GLsizei height,
925 GLenum format,
926 GLenum type,
927 const void * data);
929 // Extra validation for async tex(Sub)Image2D.
930 bool ValidateAsyncTransfer(
931 const char* function_name,
932 TextureRef* texture_ref,
933 GLenum target,
934 GLint level,
935 const void * data);
937 // Wrapper for TexImageIOSurface2DCHROMIUM.
938 void DoTexImageIOSurface2DCHROMIUM(
939 GLenum target,
940 GLsizei width,
941 GLsizei height,
942 GLuint io_surface_id,
943 GLuint plane);
945 void DoCopyTextureCHROMIUM(GLenum target,
946 GLuint source_id,
947 GLuint dest_id,
948 GLenum internal_format,
949 GLenum dest_type);
951 void DoCopySubTextureCHROMIUM(GLenum target,
952 GLuint source_id,
953 GLuint dest_id,
954 GLint xoffset,
955 GLint yoffset);
957 // Wrapper for TexStorage2DEXT.
958 void DoTexStorage2DEXT(
959 GLenum target,
960 GLint levels,
961 GLenum internal_format,
962 GLsizei width,
963 GLsizei height);
965 void DoProduceTextureCHROMIUM(GLenum target, const GLbyte* key);
966 void DoProduceTextureDirectCHROMIUM(GLuint texture, GLenum target,
967 const GLbyte* key);
968 void ProduceTextureRef(std::string func_name, TextureRef* texture_ref,
969 GLenum target, const GLbyte* data);
971 void EnsureTextureForClientId(GLenum target, GLuint client_id);
972 void DoConsumeTextureCHROMIUM(GLenum target, const GLbyte* key);
973 void DoCreateAndConsumeTextureCHROMIUM(GLenum target, const GLbyte* key,
974 GLuint client_id);
976 bool DoIsValuebufferCHROMIUM(GLuint client_id);
977 void DoBindValueBufferCHROMIUM(GLenum target, GLuint valuebuffer);
978 void DoSubscribeValueCHROMIUM(GLenum target, GLenum subscription);
979 void DoPopulateSubscribedValuesCHROMIUM(GLenum target);
980 void DoUniformValueBufferCHROMIUM(GLint location,
981 GLenum target,
982 GLenum subscription);
984 void DoBindTexImage2DCHROMIUM(
985 GLenum target,
986 GLint image_id);
987 void DoReleaseTexImage2DCHROMIUM(
988 GLenum target,
989 GLint image_id);
991 void DoTraceEndCHROMIUM(void);
993 void DoDrawBuffersEXT(GLsizei count, const GLenum* bufs);
995 void DoLoseContextCHROMIUM(GLenum current, GLenum other);
997 void DoMatrixLoadfCHROMIUM(GLenum matrix_mode, const GLfloat* matrix);
998 void DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode);
1000 // Creates a Program for the given program.
1001 Program* CreateProgram(
1002 GLuint client_id, GLuint service_id) {
1003 return program_manager()->CreateProgram(client_id, service_id);
1006 // Gets the program info for the given program. Returns NULL if none exists.
1007 Program* GetProgram(GLuint client_id) {
1008 return program_manager()->GetProgram(client_id);
1011 #if defined(NDEBUG)
1012 void LogClientServiceMapping(
1013 const char* /* function_name */,
1014 GLuint /* client_id */,
1015 GLuint /* service_id */) {
1017 template<typename T>
1018 void LogClientServiceForInfo(
1019 T* /* info */, GLuint /* client_id */, const char* /* function_name */) {
1021 #else
1022 void LogClientServiceMapping(
1023 const char* function_name, GLuint client_id, GLuint service_id) {
1024 if (service_logging_) {
1025 VLOG(1) << "[" << logger_.GetLogPrefix() << "] " << function_name
1026 << ": client_id = " << client_id
1027 << ", service_id = " << service_id;
1030 template<typename T>
1031 void LogClientServiceForInfo(
1032 T* info, GLuint client_id, const char* function_name) {
1033 if (info) {
1034 LogClientServiceMapping(function_name, client_id, info->service_id());
1037 #endif
1039 // Gets the program info for the given program. If it's not a program
1040 // generates a GL error. Returns NULL if not program.
1041 Program* GetProgramInfoNotShader(
1042 GLuint client_id, const char* function_name) {
1043 Program* program = GetProgram(client_id);
1044 if (!program) {
1045 if (GetShader(client_id)) {
1046 LOCAL_SET_GL_ERROR(
1047 GL_INVALID_OPERATION, function_name, "shader passed for program");
1048 } else {
1049 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "unknown program");
1052 LogClientServiceForInfo(program, client_id, function_name);
1053 return program;
1057 // Creates a Shader for the given shader.
1058 Shader* CreateShader(
1059 GLuint client_id,
1060 GLuint service_id,
1061 GLenum shader_type) {
1062 return shader_manager()->CreateShader(
1063 client_id, service_id, shader_type);
1066 // Gets the shader info for the given shader. Returns NULL if none exists.
1067 Shader* GetShader(GLuint client_id) {
1068 return shader_manager()->GetShader(client_id);
1071 // Gets the shader info for the given shader. If it's not a shader generates a
1072 // GL error. Returns NULL if not shader.
1073 Shader* GetShaderInfoNotProgram(
1074 GLuint client_id, const char* function_name) {
1075 Shader* shader = GetShader(client_id);
1076 if (!shader) {
1077 if (GetProgram(client_id)) {
1078 LOCAL_SET_GL_ERROR(
1079 GL_INVALID_OPERATION, function_name, "program passed for shader");
1080 } else {
1081 LOCAL_SET_GL_ERROR(
1082 GL_INVALID_VALUE, function_name, "unknown shader");
1085 LogClientServiceForInfo(shader, client_id, function_name);
1086 return shader;
1089 // Creates a buffer info for the given buffer.
1090 void CreateBuffer(GLuint client_id, GLuint service_id) {
1091 return buffer_manager()->CreateBuffer(client_id, service_id);
1094 // Gets the buffer info for the given buffer.
1095 Buffer* GetBuffer(GLuint client_id) {
1096 Buffer* buffer = buffer_manager()->GetBuffer(client_id);
1097 return buffer;
1100 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
1101 // on glDeleteBuffers so we can make sure the user does not try to render
1102 // with deleted buffers.
1103 void RemoveBuffer(GLuint client_id);
1105 // Creates a framebuffer info for the given framebuffer.
1106 void CreateFramebuffer(GLuint client_id, GLuint service_id) {
1107 return framebuffer_manager()->CreateFramebuffer(client_id, service_id);
1110 // Gets the framebuffer info for the given framebuffer.
1111 Framebuffer* GetFramebuffer(GLuint client_id) {
1112 return framebuffer_manager()->GetFramebuffer(client_id);
1115 // Removes the framebuffer info for the given framebuffer.
1116 void RemoveFramebuffer(GLuint client_id) {
1117 framebuffer_manager()->RemoveFramebuffer(client_id);
1120 // Creates a renderbuffer info for the given renderbuffer.
1121 void CreateRenderbuffer(GLuint client_id, GLuint service_id) {
1122 return renderbuffer_manager()->CreateRenderbuffer(
1123 client_id, service_id);
1126 // Gets the renderbuffer info for the given renderbuffer.
1127 Renderbuffer* GetRenderbuffer(GLuint client_id) {
1128 return renderbuffer_manager()->GetRenderbuffer(client_id);
1131 // Removes the renderbuffer info for the given renderbuffer.
1132 void RemoveRenderbuffer(GLuint client_id) {
1133 renderbuffer_manager()->RemoveRenderbuffer(client_id);
1136 // Creates a valuebuffer info for the given valuebuffer.
1137 void CreateValuebuffer(GLuint client_id) {
1138 return valuebuffer_manager()->CreateValuebuffer(client_id);
1141 // Gets the valuebuffer info for a given valuebuffer.
1142 Valuebuffer* GetValuebuffer(GLuint client_id) {
1143 return valuebuffer_manager()->GetValuebuffer(client_id);
1146 // Removes the valuebuffer info for the given valuebuffer.
1147 void RemoveValuebuffer(GLuint client_id) {
1148 valuebuffer_manager()->RemoveValuebuffer(client_id);
1151 // Gets the vertex attrib manager for the given vertex array.
1152 VertexAttribManager* GetVertexAttribManager(GLuint client_id) {
1153 VertexAttribManager* info =
1154 vertex_array_manager()->GetVertexAttribManager(client_id);
1155 return info;
1158 // Removes the vertex attrib manager for the given vertex array.
1159 void RemoveVertexAttribManager(GLuint client_id) {
1160 vertex_array_manager()->RemoveVertexAttribManager(client_id);
1163 // Creates a vertex attrib manager for the given vertex array.
1164 scoped_refptr<VertexAttribManager> CreateVertexAttribManager(
1165 GLuint client_id,
1166 GLuint service_id,
1167 bool client_visible) {
1168 return vertex_array_manager()->CreateVertexAttribManager(
1169 client_id, service_id, group_->max_vertex_attribs(), client_visible);
1172 void DoBindAttribLocation(GLuint client_id, GLuint index, const char* name);
1173 void DoBindUniformLocationCHROMIUM(
1174 GLuint client_id, GLint location, const char* name);
1176 error::Error GetAttribLocationHelper(
1177 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1178 const std::string& name_str);
1180 error::Error GetUniformLocationHelper(
1181 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1182 const std::string& name_str);
1184 error::Error GetFragDataLocationHelper(
1185 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1186 const std::string& name_str);
1188 // Wrapper for glShaderSource.
1189 void DoShaderSource(
1190 GLuint client_id, GLsizei count, const char** data, const GLint* length);
1192 // Wrapper for glTransformFeedbackVaryings.
1193 void DoTransformFeedbackVaryings(
1194 GLuint client_program_id, GLsizei count, const char* const* varyings,
1195 GLenum buffer_mode);
1197 // Clear any textures used by the current program.
1198 bool ClearUnclearedTextures();
1200 // Clears any uncleared attachments attached to the given frame buffer.
1201 // Returns false if there was a generated GL error.
1202 void ClearUnclearedAttachments(GLenum target, Framebuffer* framebuffer);
1204 // overridden from GLES2Decoder
1205 bool ClearLevel(Texture* texture,
1206 unsigned target,
1207 int level,
1208 unsigned internal_format,
1209 unsigned format,
1210 unsigned type,
1211 int width,
1212 int height,
1213 bool is_texture_immutable) override;
1215 // Restore all GL state that affects clearing.
1216 void RestoreClearState();
1218 // Remembers the state of some capabilities.
1219 // Returns: true if glEnable/glDisable should actually be called.
1220 bool SetCapabilityState(GLenum cap, bool enabled);
1222 // Check that the currently bound framebuffers are valid.
1223 // Generates GL error if not.
1224 bool CheckBoundFramebuffersValid(const char* func_name);
1226 // Check that the currently bound read framebuffer has a color image
1227 // attached. Generates GL error if not.
1228 bool CheckBoundReadFramebufferColorAttachment(const char* func_name);
1230 // Check that the currently bound read framebuffer's color image
1231 // isn't the target texture of the glCopyTex{Sub}Image2D.
1232 bool FormsTextureCopyingFeedbackLoop(TextureRef* texture, GLint level);
1234 // Check if a framebuffer meets our requirements.
1235 bool CheckFramebufferValid(
1236 Framebuffer* framebuffer,
1237 GLenum target,
1238 const char* func_name);
1240 // Check if the current valuebuffer exists and is valid. If not generates
1241 // the appropriate GL error. Returns true if the current valuebuffer is in
1242 // a usable state.
1243 bool CheckCurrentValuebuffer(const char* function_name);
1245 // Check if the current valuebuffer exists and is valiud and that the
1246 // value buffer is actually subscribed to the given subscription
1247 bool CheckCurrentValuebufferForSubscription(GLenum subscription,
1248 const char* function_name);
1250 // Check if the location can be used for the given subscription target. If not
1251 // generates the appropriate GL error. Returns true if the location is usable
1252 bool CheckSubscriptionTarget(GLint location,
1253 GLenum subscription,
1254 const char* function_name);
1256 // Checks if the current program exists and is valid. If not generates the
1257 // appropriate GL error. Returns true if the current program is in a usable
1258 // state.
1259 bool CheckCurrentProgram(const char* function_name);
1261 // Checks if the current program exists and is valid and that location is not
1262 // -1. If the current program is not valid generates the appropriate GL
1263 // error. Returns true if the current program is in a usable state and
1264 // location is not -1.
1265 bool CheckCurrentProgramForUniform(GLint location, const char* function_name);
1267 // Checks if the current program samples a texture that is also the color
1268 // image of the current bound framebuffer, i.e., the source and destination
1269 // of the draw operation are the same.
1270 bool CheckDrawingFeedbackLoops();
1272 // Checks if |api_type| is valid for the given uniform
1273 // If the api type is not valid generates the appropriate GL
1274 // error. Returns true if |api_type| is valid for the uniform
1275 bool CheckUniformForApiType(const Program::UniformInfo* info,
1276 const char* function_name,
1277 Program::UniformApiType api_type);
1279 // Gets the type of a uniform for a location in the current program. Sets GL
1280 // errors if the current program is not valid. Returns true if the current
1281 // program is valid and the location exists. Adjusts count so it
1282 // does not overflow the uniform.
1283 bool PrepForSetUniformByLocation(GLint fake_location,
1284 const char* function_name,
1285 Program::UniformApiType api_type,
1286 GLint* real_location,
1287 GLenum* type,
1288 GLsizei* count);
1290 // Gets the service id for any simulated backbuffer fbo.
1291 GLuint GetBackbufferServiceId() const;
1293 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
1294 bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
1296 // Helper for glGetVertexAttrib
1297 void GetVertexAttribHelper(
1298 const VertexAttrib* attrib, GLenum pname, GLint* param);
1300 // Wrapper for glActiveTexture
1301 void DoActiveTexture(GLenum texture_unit);
1303 // Wrapper for glAttachShader
1304 void DoAttachShader(GLuint client_program_id, GLint client_shader_id);
1306 // Wrapper for glBindBuffer since we need to track the current targets.
1307 void DoBindBuffer(GLenum target, GLuint buffer);
1309 // Wrapper for glBindFramebuffer since we need to track the current targets.
1310 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
1312 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1313 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
1315 // Wrapper for glBindTexture since we need to track the current targets.
1316 void DoBindTexture(GLenum target, GLuint texture);
1318 // Wrapper for glBindVertexArrayOES
1319 void DoBindVertexArrayOES(GLuint array);
1320 void EmulateVertexArrayState();
1322 // Wrapper for glBlitFramebufferCHROMIUM.
1323 void DoBlitFramebufferCHROMIUM(
1324 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
1325 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
1326 GLbitfield mask, GLenum filter);
1328 // Wrapper for glBufferSubData.
1329 void DoBufferSubData(
1330 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
1332 // Wrapper for glCheckFramebufferStatus
1333 GLenum DoCheckFramebufferStatus(GLenum target);
1335 // Wrapper for glClear
1336 error::Error DoClear(GLbitfield mask);
1338 // Wrappers for various state.
1339 void DoDepthRangef(GLclampf znear, GLclampf zfar);
1340 void DoSampleCoverage(GLclampf value, GLboolean invert);
1342 // Wrapper for glCompileShader.
1343 void DoCompileShader(GLuint shader);
1345 // Wrapper for glDetachShader
1346 void DoDetachShader(GLuint client_program_id, GLint client_shader_id);
1348 // Wrapper for glDisable
1349 void DoDisable(GLenum cap);
1351 // Wrapper for glDisableVertexAttribArray.
1352 void DoDisableVertexAttribArray(GLuint index);
1354 // Wrapper for glDiscardFramebufferEXT, since we need to track undefined
1355 // attachments.
1356 void DoDiscardFramebufferEXT(GLenum target,
1357 GLsizei numAttachments,
1358 const GLenum* attachments);
1360 // Wrapper for glEnable
1361 void DoEnable(GLenum cap);
1363 // Wrapper for glEnableVertexAttribArray.
1364 void DoEnableVertexAttribArray(GLuint index);
1366 // Wrapper for glFinish.
1367 void DoFinish();
1369 // Wrapper for glFlush.
1370 void DoFlush();
1372 // Wrapper for glFramebufferRenderbufffer.
1373 void DoFramebufferRenderbuffer(
1374 GLenum target, GLenum attachment, GLenum renderbuffertarget,
1375 GLuint renderbuffer);
1377 // Wrapper for glFramebufferTexture2D.
1378 void DoFramebufferTexture2D(
1379 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
1380 GLint level);
1382 // Wrapper for glFramebufferTexture2DMultisampleEXT.
1383 void DoFramebufferTexture2DMultisample(
1384 GLenum target, GLenum attachment, GLenum textarget,
1385 GLuint texture, GLint level, GLsizei samples);
1387 // Common implementation for both DoFramebufferTexture2D wrappers.
1388 void DoFramebufferTexture2DCommon(const char* name,
1389 GLenum target, GLenum attachment, GLenum textarget,
1390 GLuint texture, GLint level, GLsizei samples);
1392 // Wrapper for glFramebufferTextureLayer.
1393 void DoFramebufferTextureLayer(
1394 GLenum target, GLenum attachment, GLuint texture, GLint level,
1395 GLint layer);
1397 // Wrapper for glGenerateMipmap
1398 void DoGenerateMipmap(GLenum target);
1400 // Helper for DoGetBooleanv, Floatv, and Intergerv to adjust pname
1401 // to account for different pname values defined in different extension
1402 // variants.
1403 GLenum AdjustGetPname(GLenum pname);
1405 // Wrapper for DoGetBooleanv.
1406 void DoGetBooleanv(GLenum pname, GLboolean* params);
1408 // Wrapper for DoGetFloatv.
1409 void DoGetFloatv(GLenum pname, GLfloat* params);
1411 // Wrapper for glGetFramebufferAttachmentParameteriv.
1412 void DoGetFramebufferAttachmentParameteriv(
1413 GLenum target, GLenum attachment, GLenum pname, GLint* params);
1415 // Wrapper for glGetIntegerv.
1416 void DoGetIntegerv(GLenum pname, GLint* params);
1418 // Gets the max value in a range in a buffer.
1419 GLuint DoGetMaxValueInBufferCHROMIUM(
1420 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset);
1422 // Wrapper for glGetBufferParameteriv.
1423 void DoGetBufferParameteriv(
1424 GLenum target, GLenum pname, GLint* params);
1426 // Wrapper for glGetProgramiv.
1427 void DoGetProgramiv(
1428 GLuint program_id, GLenum pname, GLint* params);
1430 // Wrapper for glRenderbufferParameteriv.
1431 void DoGetRenderbufferParameteriv(
1432 GLenum target, GLenum pname, GLint* params);
1434 // Wrapper for glGetShaderiv
1435 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
1437 // Wrappers for glGetTexParameter.
1438 void DoGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params);
1439 void DoGetTexParameteriv(GLenum target, GLenum pname, GLint* params);
1440 void InitTextureMaxAnisotropyIfNeeded(GLenum target, GLenum pname);
1442 // Wrappers for glGetVertexAttrib.
1443 void DoGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params);
1444 void DoGetVertexAttribiv(GLuint index, GLenum pname, GLint *params);
1446 // Wrappers for glIsXXX functions.
1447 bool DoIsEnabled(GLenum cap);
1448 bool DoIsBuffer(GLuint client_id);
1449 bool DoIsFramebuffer(GLuint client_id);
1450 bool DoIsProgram(GLuint client_id);
1451 bool DoIsRenderbuffer(GLuint client_id);
1452 bool DoIsShader(GLuint client_id);
1453 bool DoIsTexture(GLuint client_id);
1454 bool DoIsVertexArrayOES(GLuint client_id);
1456 // Wrapper for glLinkProgram
1457 void DoLinkProgram(GLuint program);
1459 // Wrapper for glRenderbufferStorage.
1460 void DoRenderbufferStorage(
1461 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
1463 // Handler for glRenderbufferStorageMultisampleCHROMIUM.
1464 void DoRenderbufferStorageMultisampleCHROMIUM(
1465 GLenum target, GLsizei samples, GLenum internalformat,
1466 GLsizei width, GLsizei height);
1468 // Handler for glRenderbufferStorageMultisampleEXT
1469 // (multisampled_render_to_texture).
1470 void DoRenderbufferStorageMultisampleEXT(
1471 GLenum target, GLsizei samples, GLenum internalformat,
1472 GLsizei width, GLsizei height);
1474 // Common validation for multisample extensions.
1475 bool ValidateRenderbufferStorageMultisample(GLsizei samples,
1476 GLenum internalformat,
1477 GLsizei width,
1478 GLsizei height);
1480 // Verifies that the currently bound multisample renderbuffer is valid
1481 // Very slow! Only done on platforms with driver bugs that return invalid
1482 // buffers under memory pressure
1483 bool VerifyMultisampleRenderbufferIntegrity(
1484 GLuint renderbuffer, GLenum format);
1486 // Wrapper for glReleaseShaderCompiler.
1487 void DoReleaseShaderCompiler() { }
1489 // Wrappers for glSamplerParameter*v functions.
1490 void DoSamplerParameterfv(
1491 GLuint sampler, GLenum pname, const GLfloat* params);
1492 void DoSamplerParameteriv(GLuint sampler, GLenum pname, const GLint* params);
1494 // Wrappers for glTexParameter functions.
1495 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
1496 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
1497 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
1498 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
1500 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1501 // spec only these 2 functions can be used to set sampler uniforms.
1502 void DoUniform1i(GLint fake_location, GLint v0);
1503 void DoUniform1iv(GLint fake_location, GLsizei count, const GLint* value);
1504 void DoUniform2iv(GLint fake_location, GLsizei count, const GLint* value);
1505 void DoUniform3iv(GLint fake_location, GLsizei count, const GLint* value);
1506 void DoUniform4iv(GLint fake_location, GLsizei count, const GLint* value);
1508 // Wrappers for glUniformfv because some drivers don't correctly accept
1509 // bool uniforms.
1510 void DoUniform1fv(GLint fake_location, GLsizei count, const GLfloat* value);
1511 void DoUniform2fv(GLint fake_location, GLsizei count, const GLfloat* value);
1512 void DoUniform3fv(GLint fake_location, GLsizei count, const GLfloat* value);
1513 void DoUniform4fv(GLint fake_location, GLsizei count, const GLfloat* value);
1515 void DoUniformMatrix2fv(
1516 GLint fake_location, GLsizei count, GLboolean transpose,
1517 const GLfloat* value);
1518 void DoUniformMatrix3fv(
1519 GLint fake_location, GLsizei count, GLboolean transpose,
1520 const GLfloat* value);
1521 void DoUniformMatrix4fv(
1522 GLint fake_location, GLsizei count, GLboolean transpose,
1523 const GLfloat* value);
1525 bool SetVertexAttribValue(
1526 const char* function_name, GLuint index, const GLfloat* value);
1528 // Wrappers for glVertexAttrib??
1529 void DoVertexAttrib1f(GLuint index, GLfloat v0);
1530 void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
1531 void DoVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
1532 void DoVertexAttrib4f(
1533 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
1534 void DoVertexAttrib1fv(GLuint index, const GLfloat *v);
1535 void DoVertexAttrib2fv(GLuint index, const GLfloat *v);
1536 void DoVertexAttrib3fv(GLuint index, const GLfloat *v);
1537 void DoVertexAttrib4fv(GLuint index, const GLfloat *v);
1539 // Wrapper for glViewport
1540 void DoViewport(GLint x, GLint y, GLsizei width, GLsizei height);
1542 // Wrapper for glUseProgram
1543 void DoUseProgram(GLuint program);
1545 // Wrapper for glValidateProgram.
1546 void DoValidateProgram(GLuint program_client_id);
1548 void DoInsertEventMarkerEXT(GLsizei length, const GLchar* marker);
1549 void DoPushGroupMarkerEXT(GLsizei length, const GLchar* group);
1550 void DoPopGroupMarkerEXT(void);
1552 // Gets the number of values that will be returned by glGetXXX. Returns
1553 // false if pname is unknown.
1554 bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
1556 // Checks if the current program and vertex attributes are valid for drawing.
1557 bool IsDrawValid(
1558 const char* function_name, GLuint max_vertex_accessed, bool instanced,
1559 GLsizei primcount);
1561 // Returns true if successful, simulated will be true if attrib0 was
1562 // simulated.
1563 bool SimulateAttrib0(
1564 const char* function_name, GLuint max_vertex_accessed, bool* simulated);
1565 void RestoreStateForAttrib(GLuint attrib, bool restore_array_binding);
1567 // If an image is bound to texture, this will call Will/DidUseTexImage
1568 // if needed.
1569 void DoWillUseTexImageIfNeeded(Texture* texture, GLenum textarget);
1570 void DoDidUseTexImageIfNeeded(Texture* texture, GLenum textarget);
1572 // Returns false if textures were replaced.
1573 bool PrepareTexturesForRender();
1574 void RestoreStateForTextures();
1576 // Returns true if GL_FIXED attribs were simulated.
1577 bool SimulateFixedAttribs(
1578 const char* function_name,
1579 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount);
1580 void RestoreStateForSimulatedFixedAttribs();
1582 // Handle DrawArrays and DrawElements for both instanced and non-instanced
1583 // cases (primcount is always 1 for non-instanced).
1584 error::Error DoDrawArrays(
1585 const char* function_name,
1586 bool instanced, GLenum mode, GLint first, GLsizei count,
1587 GLsizei primcount);
1588 error::Error DoDrawElements(
1589 const char* function_name,
1590 bool instanced, GLenum mode, GLsizei count, GLenum type,
1591 int32 offset, GLsizei primcount);
1593 GLenum GetBindTargetForSamplerType(GLenum type) {
1594 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
1595 type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB);
1596 switch (type) {
1597 case GL_SAMPLER_2D:
1598 return GL_TEXTURE_2D;
1599 case GL_SAMPLER_CUBE:
1600 return GL_TEXTURE_CUBE_MAP;
1601 case GL_SAMPLER_EXTERNAL_OES:
1602 return GL_TEXTURE_EXTERNAL_OES;
1603 case GL_SAMPLER_2D_RECT_ARB:
1604 return GL_TEXTURE_RECTANGLE_ARB;
1607 NOTREACHED();
1608 return 0;
1611 // Gets the framebuffer info for a particular target.
1612 Framebuffer* GetFramebufferInfoForTarget(GLenum target) {
1613 Framebuffer* framebuffer = NULL;
1614 switch (target) {
1615 case GL_FRAMEBUFFER:
1616 case GL_DRAW_FRAMEBUFFER_EXT:
1617 framebuffer = framebuffer_state_.bound_draw_framebuffer.get();
1618 break;
1619 case GL_READ_FRAMEBUFFER_EXT:
1620 framebuffer = framebuffer_state_.bound_read_framebuffer.get();
1621 break;
1622 default:
1623 NOTREACHED();
1624 break;
1626 return framebuffer;
1629 Renderbuffer* GetRenderbufferInfoForTarget(
1630 GLenum target) {
1631 Renderbuffer* renderbuffer = NULL;
1632 switch (target) {
1633 case GL_RENDERBUFFER:
1634 renderbuffer = state_.bound_renderbuffer.get();
1635 break;
1636 default:
1637 NOTREACHED();
1638 break;
1640 return renderbuffer;
1643 // Validates the program and location for a glGetUniform call and returns
1644 // a SizeResult setup to receive the result. Returns true if glGetUniform
1645 // should be called.
1646 bool GetUniformSetup(GLuint program,
1647 GLint fake_location,
1648 uint32 shm_id,
1649 uint32 shm_offset,
1650 error::Error* error,
1651 GLint* real_location,
1652 GLuint* service_id,
1653 void** result,
1654 GLenum* result_type,
1655 GLsizei* result_size);
1657 void MaybeExitOnContextLost();
1658 bool WasContextLost() override;
1659 bool WasContextLostByRobustnessExtension() override;
1660 void LoseContext(uint32 reset_status) override;
1662 #if defined(OS_MACOSX)
1663 void ReleaseIOSurfaceForTexture(GLuint texture_id);
1664 #endif
1666 bool ValidateCompressedTexDimensions(
1667 const char* function_name,
1668 GLint level, GLsizei width, GLsizei height, GLenum format);
1669 bool ValidateCompressedTexFuncData(
1670 const char* function_name,
1671 GLsizei width, GLsizei height, GLenum format, size_t size);
1672 bool ValidateCompressedTexSubDimensions(
1673 const char* function_name,
1674 GLenum target, GLint level, GLint xoffset, GLint yoffset,
1675 GLsizei width, GLsizei height, GLenum format,
1676 Texture* texture);
1677 bool ValidateCopyTextureCHROMIUM(const char* function_name,
1678 GLenum target,
1679 TextureRef* source_texture_ref,
1680 TextureRef* dest_texture_ref,
1681 GLenum dest_internal_format);
1683 void RenderWarning(const char* filename, int line, const std::string& msg);
1684 void PerformanceWarning(
1685 const char* filename, int line, const std::string& msg);
1687 const FeatureInfo::FeatureFlags& features() const {
1688 return feature_info_->feature_flags();
1691 const FeatureInfo::Workarounds& workarounds() const {
1692 return feature_info_->workarounds();
1695 bool ShouldDeferDraws() {
1696 return !offscreen_target_frame_buffer_.get() &&
1697 framebuffer_state_.bound_draw_framebuffer.get() == NULL &&
1698 surface_->DeferDraws();
1701 bool ShouldDeferReads() {
1702 return !offscreen_target_frame_buffer_.get() &&
1703 framebuffer_state_.bound_read_framebuffer.get() == NULL &&
1704 surface_->DeferDraws();
1707 bool IsRobustnessSupported() {
1708 return has_robustness_extension_ &&
1709 context_->WasAllocatedUsingRobustnessExtension();
1712 error::Error WillAccessBoundFramebufferForDraw() {
1713 if (ShouldDeferDraws())
1714 return error::kDeferCommandUntilLater;
1715 if (!offscreen_target_frame_buffer_.get() &&
1716 !framebuffer_state_.bound_draw_framebuffer.get() &&
1717 !surface_->SetBackbufferAllocation(true))
1718 return error::kLostContext;
1719 return error::kNoError;
1722 error::Error WillAccessBoundFramebufferForRead() {
1723 if (ShouldDeferReads())
1724 return error::kDeferCommandUntilLater;
1725 if (!offscreen_target_frame_buffer_.get() &&
1726 !framebuffer_state_.bound_read_framebuffer.get() &&
1727 !surface_->SetBackbufferAllocation(true))
1728 return error::kLostContext;
1729 return error::kNoError;
1732 // Set remaining commands to process to 0 to force DoCommands to return
1733 // and allow context preemption and GPU watchdog checks in GpuScheduler().
1734 void ExitCommandProcessingEarly() { commands_to_process_ = 0; }
1736 void ProcessPendingReadPixels();
1737 void FinishReadPixels(const cmds::ReadPixels& c, GLuint buffer);
1739 // Generate a member function prototype for each command in an automated and
1740 // typesafe way.
1741 #define GLES2_CMD_OP(name) \
1742 Error Handle##name(uint32 immediate_data_size, const void* data);
1744 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1746 #undef GLES2_CMD_OP
1748 // The GL context this decoder renders to on behalf of the client.
1749 scoped_refptr<gfx::GLSurface> surface_;
1750 scoped_refptr<gfx::GLContext> context_;
1752 // The ContextGroup for this decoder uses to track resources.
1753 scoped_refptr<ContextGroup> group_;
1755 DebugMarkerManager debug_marker_manager_;
1756 Logger logger_;
1758 // All the state for this context.
1759 ContextState state_;
1761 // Current width and height of the offscreen frame buffer.
1762 gfx::Size offscreen_size_;
1764 // Util to help with GL.
1765 GLES2Util util_;
1767 // unpack flip y as last set by glPixelStorei
1768 bool unpack_flip_y_;
1770 // unpack (un)premultiply alpha as last set by glPixelStorei
1771 bool unpack_premultiply_alpha_;
1772 bool unpack_unpremultiply_alpha_;
1774 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1775 GLuint attrib_0_buffer_id_;
1777 // The value currently in attrib_0.
1778 Vec4 attrib_0_value_;
1780 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1781 bool attrib_0_buffer_matches_value_;
1783 // The size of attrib 0.
1784 GLsizei attrib_0_size_;
1786 // The buffer used to simulate GL_FIXED attribs.
1787 GLuint fixed_attrib_buffer_id_;
1789 // The size of fiixed attrib buffer.
1790 GLsizei fixed_attrib_buffer_size_;
1792 // The offscreen frame buffer that the client renders to. With EGL, the
1793 // depth and stencil buffers are separate. With regular GL there is a single
1794 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1795 // offscreen_target_stencil_render_buffer_ is unused.
1796 scoped_ptr<BackFramebuffer> offscreen_target_frame_buffer_;
1797 scoped_ptr<BackTexture> offscreen_target_color_texture_;
1798 scoped_ptr<BackRenderbuffer> offscreen_target_color_render_buffer_;
1799 scoped_ptr<BackRenderbuffer> offscreen_target_depth_render_buffer_;
1800 scoped_ptr<BackRenderbuffer> offscreen_target_stencil_render_buffer_;
1801 GLenum offscreen_target_color_format_;
1802 GLenum offscreen_target_depth_format_;
1803 GLenum offscreen_target_stencil_format_;
1804 GLsizei offscreen_target_samples_;
1805 GLboolean offscreen_target_buffer_preserved_;
1807 // The copy that is saved when SwapBuffers is called.
1808 scoped_ptr<BackFramebuffer> offscreen_saved_frame_buffer_;
1809 scoped_ptr<BackTexture> offscreen_saved_color_texture_;
1810 scoped_refptr<TextureRef>
1811 offscreen_saved_color_texture_info_;
1813 // The copy that is used as the destination for multi-sample resolves.
1814 scoped_ptr<BackFramebuffer> offscreen_resolved_frame_buffer_;
1815 scoped_ptr<BackTexture> offscreen_resolved_color_texture_;
1816 GLenum offscreen_saved_color_format_;
1818 scoped_ptr<QueryManager> query_manager_;
1820 scoped_ptr<VertexArrayManager> vertex_array_manager_;
1822 scoped_ptr<ImageManager> image_manager_;
1824 base::Callback<void(gfx::Size, float)> resize_callback_;
1826 WaitSyncPointCallback wait_sync_point_callback_;
1828 ShaderCacheCallback shader_cache_callback_;
1830 scoped_ptr<AsyncPixelTransferManager> async_pixel_transfer_manager_;
1832 // The format of the back buffer_
1833 GLenum back_buffer_color_format_;
1834 bool back_buffer_has_depth_;
1835 bool back_buffer_has_stencil_;
1837 bool surfaceless_;
1839 // Backbuffer attachments that are currently undefined.
1840 uint32 backbuffer_needs_clear_bits_;
1842 // The current decoder error communicates the decoder error through command
1843 // processing functions that do not return the error value. Should be set only
1844 // if not returning an error.
1845 error::Error current_decoder_error_;
1847 bool use_shader_translator_;
1848 scoped_refptr<ShaderTranslatorInterface> vertex_translator_;
1849 scoped_refptr<ShaderTranslatorInterface> fragment_translator_;
1851 DisallowedFeatures disallowed_features_;
1853 // Cached from ContextGroup
1854 const Validators* validators_;
1855 scoped_refptr<FeatureInfo> feature_info_;
1857 int frame_number_;
1859 // Number of commands remaining to be processed in DoCommands().
1860 int commands_to_process_;
1862 bool has_robustness_extension_;
1863 GLenum reset_status_;
1864 bool reset_by_robustness_extension_;
1865 bool supports_post_sub_buffer_;
1867 // These flags are used to override the state of the shared feature_info_
1868 // member. Because the same FeatureInfo instance may be shared among many
1869 // contexts, the assumptions on the availablity of extensions in WebGL
1870 // contexts may be broken. These flags override the shared state to preserve
1871 // WebGL semantics.
1872 bool force_webgl_glsl_validation_;
1873 bool derivatives_explicitly_enabled_;
1874 bool frag_depth_explicitly_enabled_;
1875 bool draw_buffers_explicitly_enabled_;
1876 bool shader_texture_lod_explicitly_enabled_;
1878 bool compile_shader_always_succeeds_;
1880 // An optional behaviour to lose the context and group when OOM.
1881 bool lose_context_when_out_of_memory_;
1883 // Log extra info.
1884 bool service_logging_;
1886 #if defined(OS_MACOSX)
1887 typedef std::map<GLuint, IOSurfaceRef> TextureToIOSurfaceMap;
1888 TextureToIOSurfaceMap texture_to_io_surface_map_;
1889 #endif
1891 scoped_ptr<CopyTextureCHROMIUMResourceManager> copy_texture_CHROMIUM_;
1892 scoped_ptr<ClearFramebufferResourceManager> clear_framebuffer_blit_;
1894 // Cached values of the currently assigned viewport dimensions.
1895 GLsizei viewport_max_width_;
1896 GLsizei viewport_max_height_;
1898 // Command buffer stats.
1899 base::TimeDelta total_processing_commands_time_;
1901 // States related to each manager.
1902 DecoderTextureState texture_state_;
1903 DecoderFramebufferState framebuffer_state_;
1905 scoped_ptr<GPUTracer> gpu_tracer_;
1906 scoped_ptr<GPUStateTracer> gpu_state_tracer_;
1907 const unsigned char* cb_command_trace_category_;
1908 const unsigned char* gpu_decoder_category_;
1909 int gpu_trace_level_;
1910 bool gpu_trace_commands_;
1911 bool gpu_debug_commands_;
1913 std::queue<linked_ptr<FenceCallback> > pending_readpixel_fences_;
1915 // Used to validate multisample renderbuffers if needed
1916 GLuint validation_texture_;
1917 GLuint validation_fbo_multisample_;
1918 GLuint validation_fbo_;
1920 typedef gpu::gles2::GLES2Decoder::Error (GLES2DecoderImpl::*CmdHandler)(
1921 uint32 immediate_data_size,
1922 const void* data);
1924 // A struct to hold info about each command.
1925 struct CommandInfo {
1926 CmdHandler cmd_handler;
1927 uint8 arg_flags; // How to handle the arguments for this command
1928 uint8 cmd_flags; // How to handle this command
1929 uint16 arg_count; // How many arguments are expected for this command.
1932 // A table of CommandInfo for all the commands.
1933 static const CommandInfo command_info[kNumCommands - kStartPoint];
1935 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
1938 const GLES2DecoderImpl::CommandInfo GLES2DecoderImpl::command_info[] = {
1939 #define GLES2_CMD_OP(name) \
1941 &GLES2DecoderImpl::Handle##name, cmds::name::kArgFlags, \
1942 cmds::name::cmd_flags, \
1943 sizeof(cmds::name) / sizeof(CommandBufferEntry) - 1, \
1945 , /* NOLINT */
1946 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1947 #undef GLES2_CMD_OP
1950 ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(
1951 const char* function_name, ErrorState* error_state)
1952 : function_name_(function_name),
1953 error_state_(error_state) {
1954 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state_, function_name_);
1957 ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
1958 ERRORSTATE_CLEAR_REAL_GL_ERRORS(error_state_, function_name_);
1961 static void RestoreCurrentTextureBindings(ContextState* state, GLenum target) {
1962 TextureUnit& info = state->texture_units[0];
1963 GLuint last_id;
1964 scoped_refptr<TextureRef> texture_ref;
1965 switch (target) {
1966 case GL_TEXTURE_2D:
1967 texture_ref = info.bound_texture_2d;
1968 break;
1969 case GL_TEXTURE_CUBE_MAP:
1970 texture_ref = info.bound_texture_cube_map;
1971 break;
1972 case GL_TEXTURE_EXTERNAL_OES:
1973 texture_ref = info.bound_texture_external_oes;
1974 break;
1975 case GL_TEXTURE_RECTANGLE_ARB:
1976 texture_ref = info.bound_texture_rectangle_arb;
1977 break;
1978 default:
1979 NOTREACHED();
1980 break;
1982 if (texture_ref.get()) {
1983 last_id = texture_ref->service_id();
1984 } else {
1985 last_id = 0;
1988 glBindTexture(target, last_id);
1989 glActiveTexture(GL_TEXTURE0 + state->active_texture_unit);
1992 ScopedTextureBinder::ScopedTextureBinder(ContextState* state,
1993 GLuint id,
1994 GLenum target)
1995 : state_(state),
1996 target_(target) {
1997 ScopedGLErrorSuppressor suppressor(
1998 "ScopedTextureBinder::ctor", state_->GetErrorState());
2000 // TODO(apatrick): Check if there are any other states that need to be reset
2001 // before binding a new texture.
2002 glActiveTexture(GL_TEXTURE0);
2003 glBindTexture(target, id);
2006 ScopedTextureBinder::~ScopedTextureBinder() {
2007 ScopedGLErrorSuppressor suppressor(
2008 "ScopedTextureBinder::dtor", state_->GetErrorState());
2009 RestoreCurrentTextureBindings(state_, target_);
2012 ScopedRenderBufferBinder::ScopedRenderBufferBinder(ContextState* state,
2013 GLuint id)
2014 : state_(state) {
2015 ScopedGLErrorSuppressor suppressor(
2016 "ScopedRenderBufferBinder::ctor", state_->GetErrorState());
2017 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
2020 ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
2021 ScopedGLErrorSuppressor suppressor(
2022 "ScopedRenderBufferBinder::dtor", state_->GetErrorState());
2023 state_->RestoreRenderbufferBindings();
2026 ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
2027 GLuint id)
2028 : decoder_(decoder) {
2029 ScopedGLErrorSuppressor suppressor(
2030 "ScopedFrameBufferBinder::ctor", decoder_->GetErrorState());
2031 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
2032 decoder->OnFboChanged();
2035 ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
2036 ScopedGLErrorSuppressor suppressor(
2037 "ScopedFrameBufferBinder::dtor", decoder_->GetErrorState());
2038 decoder_->RestoreCurrentFramebufferBindings();
2041 ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
2042 GLES2DecoderImpl* decoder, bool enforce_internal_framebuffer, bool internal)
2043 : decoder_(decoder) {
2044 resolve_and_bind_ = (
2045 decoder_->offscreen_target_frame_buffer_.get() &&
2046 decoder_->IsOffscreenBufferMultisampled() &&
2047 (!decoder_->framebuffer_state_.bound_read_framebuffer.get() ||
2048 enforce_internal_framebuffer));
2049 if (!resolve_and_bind_)
2050 return;
2052 ScopedGLErrorSuppressor suppressor(
2053 "ScopedResolvedFrameBufferBinder::ctor", decoder_->GetErrorState());
2054 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT,
2055 decoder_->offscreen_target_frame_buffer_->id());
2056 GLuint targetid;
2057 if (internal) {
2058 if (!decoder_->offscreen_resolved_frame_buffer_.get()) {
2059 decoder_->offscreen_resolved_frame_buffer_.reset(
2060 new BackFramebuffer(decoder_));
2061 decoder_->offscreen_resolved_frame_buffer_->Create();
2062 decoder_->offscreen_resolved_color_texture_.reset(
2063 new BackTexture(decoder->memory_tracker(), &decoder->state_));
2064 decoder_->offscreen_resolved_color_texture_->Create();
2066 DCHECK(decoder_->offscreen_saved_color_format_);
2067 decoder_->offscreen_resolved_color_texture_->AllocateStorage(
2068 decoder_->offscreen_size_, decoder_->offscreen_saved_color_format_,
2069 false);
2070 decoder_->offscreen_resolved_frame_buffer_->AttachRenderTexture(
2071 decoder_->offscreen_resolved_color_texture_.get());
2072 if (decoder_->offscreen_resolved_frame_buffer_->CheckStatus() !=
2073 GL_FRAMEBUFFER_COMPLETE) {
2074 LOG(ERROR) << "ScopedResolvedFrameBufferBinder failed "
2075 << "because offscreen resolved FBO was incomplete.";
2076 return;
2079 targetid = decoder_->offscreen_resolved_frame_buffer_->id();
2080 } else {
2081 targetid = decoder_->offscreen_saved_frame_buffer_->id();
2083 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, targetid);
2084 const int width = decoder_->offscreen_size_.width();
2085 const int height = decoder_->offscreen_size_.height();
2086 decoder->state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
2087 decoder->BlitFramebufferHelper(0,
2089 width,
2090 height,
2093 width,
2094 height,
2095 GL_COLOR_BUFFER_BIT,
2096 GL_NEAREST);
2097 glBindFramebufferEXT(GL_FRAMEBUFFER, targetid);
2100 ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
2101 if (!resolve_and_bind_)
2102 return;
2104 ScopedGLErrorSuppressor suppressor(
2105 "ScopedResolvedFrameBufferBinder::dtor", decoder_->GetErrorState());
2106 decoder_->RestoreCurrentFramebufferBindings();
2107 if (decoder_->state_.enable_flags.scissor_test) {
2108 decoder_->state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
2112 BackTexture::BackTexture(
2113 MemoryTracker* memory_tracker,
2114 ContextState* state)
2115 : memory_tracker_(memory_tracker, MemoryTracker::kUnmanaged),
2116 state_(state),
2117 bytes_allocated_(0),
2118 id_(0) {
2121 BackTexture::~BackTexture() {
2122 // This does not destroy the render texture because that would require that
2123 // the associated GL context was current. Just check that it was explicitly
2124 // destroyed.
2125 DCHECK_EQ(id_, 0u);
2128 void BackTexture::Create() {
2129 ScopedGLErrorSuppressor suppressor("BackTexture::Create",
2130 state_->GetErrorState());
2131 Destroy();
2132 glGenTextures(1, &id_);
2133 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2134 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2135 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2136 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2137 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2139 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
2140 // never called on an offscreen context, no data will ever be uploaded to the
2141 // saved offscreen color texture (it is deferred until to when SwapBuffers
2142 // is called). My idea is that some nvidia drivers might have a bug where
2143 // deleting a texture that has never been populated might cause a
2144 // crash.
2145 glTexImage2D(
2146 GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
2148 bytes_allocated_ = 16u * 16u * 4u;
2149 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2152 bool BackTexture::AllocateStorage(
2153 const gfx::Size& size, GLenum format, bool zero) {
2154 DCHECK_NE(id_, 0u);
2155 ScopedGLErrorSuppressor suppressor("BackTexture::AllocateStorage",
2156 state_->GetErrorState());
2157 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2158 uint32 image_size = 0;
2159 GLES2Util::ComputeImageDataSizes(
2160 size.width(), size.height(), 1, format, GL_UNSIGNED_BYTE, 8, &image_size,
2161 NULL, NULL);
2163 if (!memory_tracker_.EnsureGPUMemoryAvailable(image_size)) {
2164 return false;
2167 scoped_ptr<char[]> zero_data;
2168 if (zero) {
2169 zero_data.reset(new char[image_size]);
2170 memset(zero_data.get(), 0, image_size);
2173 glTexImage2D(GL_TEXTURE_2D,
2174 0, // mip level
2175 format,
2176 size.width(),
2177 size.height(),
2178 0, // border
2179 format,
2180 GL_UNSIGNED_BYTE,
2181 zero_data.get());
2183 size_ = size;
2185 bool success = glGetError() == GL_NO_ERROR;
2186 if (success) {
2187 memory_tracker_.TrackMemFree(bytes_allocated_);
2188 bytes_allocated_ = image_size;
2189 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2191 return success;
2194 void BackTexture::Copy(const gfx::Size& size, GLenum format) {
2195 DCHECK_NE(id_, 0u);
2196 ScopedGLErrorSuppressor suppressor("BackTexture::Copy",
2197 state_->GetErrorState());
2198 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2199 glCopyTexImage2D(GL_TEXTURE_2D,
2200 0, // level
2201 format,
2202 0, 0,
2203 size.width(),
2204 size.height(),
2205 0); // border
2208 void BackTexture::Destroy() {
2209 if (id_ != 0) {
2210 ScopedGLErrorSuppressor suppressor("BackTexture::Destroy",
2211 state_->GetErrorState());
2212 glDeleteTextures(1, &id_);
2213 id_ = 0;
2215 memory_tracker_.TrackMemFree(bytes_allocated_);
2216 bytes_allocated_ = 0;
2219 void BackTexture::Invalidate() {
2220 id_ = 0;
2223 BackRenderbuffer::BackRenderbuffer(
2224 RenderbufferManager* renderbuffer_manager,
2225 MemoryTracker* memory_tracker,
2226 ContextState* state)
2227 : renderbuffer_manager_(renderbuffer_manager),
2228 memory_tracker_(memory_tracker, MemoryTracker::kUnmanaged),
2229 state_(state),
2230 bytes_allocated_(0),
2231 id_(0) {
2234 BackRenderbuffer::~BackRenderbuffer() {
2235 // This does not destroy the render buffer because that would require that
2236 // the associated GL context was current. Just check that it was explicitly
2237 // destroyed.
2238 DCHECK_EQ(id_, 0u);
2241 void BackRenderbuffer::Create() {
2242 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Create",
2243 state_->GetErrorState());
2244 Destroy();
2245 glGenRenderbuffersEXT(1, &id_);
2248 bool BackRenderbuffer::AllocateStorage(const FeatureInfo* feature_info,
2249 const gfx::Size& size,
2250 GLenum format,
2251 GLsizei samples) {
2252 ScopedGLErrorSuppressor suppressor(
2253 "BackRenderbuffer::AllocateStorage", state_->GetErrorState());
2254 ScopedRenderBufferBinder binder(state_, id_);
2256 uint32 estimated_size = 0;
2257 if (!renderbuffer_manager_->ComputeEstimatedRenderbufferSize(
2258 size.width(), size.height(), samples, format, &estimated_size)) {
2259 return false;
2262 if (!memory_tracker_.EnsureGPUMemoryAvailable(estimated_size)) {
2263 return false;
2266 if (samples <= 1) {
2267 glRenderbufferStorageEXT(GL_RENDERBUFFER,
2268 format,
2269 size.width(),
2270 size.height());
2271 } else {
2272 GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(feature_info,
2273 GL_RENDERBUFFER,
2274 samples,
2275 format,
2276 size.width(),
2277 size.height());
2279 bool success = glGetError() == GL_NO_ERROR;
2280 if (success) {
2281 // Mark the previously allocated bytes as free.
2282 memory_tracker_.TrackMemFree(bytes_allocated_);
2283 bytes_allocated_ = estimated_size;
2284 // Track the newly allocated bytes.
2285 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2287 return success;
2290 void BackRenderbuffer::Destroy() {
2291 if (id_ != 0) {
2292 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Destroy",
2293 state_->GetErrorState());
2294 glDeleteRenderbuffersEXT(1, &id_);
2295 id_ = 0;
2297 memory_tracker_.TrackMemFree(bytes_allocated_);
2298 bytes_allocated_ = 0;
2301 void BackRenderbuffer::Invalidate() {
2302 id_ = 0;
2305 BackFramebuffer::BackFramebuffer(GLES2DecoderImpl* decoder)
2306 : decoder_(decoder),
2307 id_(0) {
2310 BackFramebuffer::~BackFramebuffer() {
2311 // This does not destroy the frame buffer because that would require that
2312 // the associated GL context was current. Just check that it was explicitly
2313 // destroyed.
2314 DCHECK_EQ(id_, 0u);
2317 void BackFramebuffer::Create() {
2318 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Create",
2319 decoder_->GetErrorState());
2320 Destroy();
2321 glGenFramebuffersEXT(1, &id_);
2324 void BackFramebuffer::AttachRenderTexture(BackTexture* texture) {
2325 DCHECK_NE(id_, 0u);
2326 ScopedGLErrorSuppressor suppressor(
2327 "BackFramebuffer::AttachRenderTexture", decoder_->GetErrorState());
2328 ScopedFrameBufferBinder binder(decoder_, id_);
2329 GLuint attach_id = texture ? texture->id() : 0;
2330 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
2331 GL_COLOR_ATTACHMENT0,
2332 GL_TEXTURE_2D,
2333 attach_id,
2337 void BackFramebuffer::AttachRenderBuffer(GLenum target,
2338 BackRenderbuffer* render_buffer) {
2339 DCHECK_NE(id_, 0u);
2340 ScopedGLErrorSuppressor suppressor(
2341 "BackFramebuffer::AttachRenderBuffer", decoder_->GetErrorState());
2342 ScopedFrameBufferBinder binder(decoder_, id_);
2343 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
2344 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
2345 target,
2346 GL_RENDERBUFFER,
2347 attach_id);
2350 void BackFramebuffer::Destroy() {
2351 if (id_ != 0) {
2352 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Destroy",
2353 decoder_->GetErrorState());
2354 glDeleteFramebuffersEXT(1, &id_);
2355 id_ = 0;
2359 void BackFramebuffer::Invalidate() {
2360 id_ = 0;
2363 GLenum BackFramebuffer::CheckStatus() {
2364 DCHECK_NE(id_, 0u);
2365 ScopedGLErrorSuppressor suppressor("BackFramebuffer::CheckStatus",
2366 decoder_->GetErrorState());
2367 ScopedFrameBufferBinder binder(decoder_, id_);
2368 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
2371 GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
2372 return new GLES2DecoderImpl(group);
2375 GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
2376 : GLES2Decoder(),
2377 group_(group),
2378 logger_(&debug_marker_manager_),
2379 state_(group_->feature_info(), this, &logger_),
2380 unpack_flip_y_(false),
2381 unpack_premultiply_alpha_(false),
2382 unpack_unpremultiply_alpha_(false),
2383 attrib_0_buffer_id_(0),
2384 attrib_0_buffer_matches_value_(true),
2385 attrib_0_size_(0),
2386 fixed_attrib_buffer_id_(0),
2387 fixed_attrib_buffer_size_(0),
2388 offscreen_target_color_format_(0),
2389 offscreen_target_depth_format_(0),
2390 offscreen_target_stencil_format_(0),
2391 offscreen_target_samples_(0),
2392 offscreen_target_buffer_preserved_(true),
2393 offscreen_saved_color_format_(0),
2394 back_buffer_color_format_(0),
2395 back_buffer_has_depth_(false),
2396 back_buffer_has_stencil_(false),
2397 surfaceless_(false),
2398 backbuffer_needs_clear_bits_(0),
2399 current_decoder_error_(error::kNoError),
2400 use_shader_translator_(true),
2401 validators_(group_->feature_info()->validators()),
2402 feature_info_(group_->feature_info()),
2403 frame_number_(0),
2404 has_robustness_extension_(false),
2405 reset_status_(GL_NO_ERROR),
2406 reset_by_robustness_extension_(false),
2407 supports_post_sub_buffer_(false),
2408 force_webgl_glsl_validation_(false),
2409 derivatives_explicitly_enabled_(false),
2410 frag_depth_explicitly_enabled_(false),
2411 draw_buffers_explicitly_enabled_(false),
2412 shader_texture_lod_explicitly_enabled_(false),
2413 compile_shader_always_succeeds_(false),
2414 lose_context_when_out_of_memory_(false),
2415 service_logging_(base::CommandLine::ForCurrentProcess()->HasSwitch(
2416 switches::kEnableGPUServiceLoggingGPU)),
2417 viewport_max_width_(0),
2418 viewport_max_height_(0),
2419 texture_state_(group_->feature_info()
2420 ->workarounds()
2421 .texsubimage2d_faster_than_teximage2d),
2422 cb_command_trace_category_(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
2423 TRACE_DISABLED_BY_DEFAULT("cb_command"))),
2424 gpu_decoder_category_(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
2425 TRACE_DISABLED_BY_DEFAULT("gpu_decoder"))),
2426 gpu_trace_level_(2),
2427 gpu_trace_commands_(false),
2428 gpu_debug_commands_(false),
2429 validation_texture_(0),
2430 validation_fbo_multisample_(0),
2431 validation_fbo_(0) {
2432 DCHECK(group);
2434 attrib_0_value_.v[0] = 0.0f;
2435 attrib_0_value_.v[1] = 0.0f;
2436 attrib_0_value_.v[2] = 0.0f;
2437 attrib_0_value_.v[3] = 1.0f;
2439 // The shader translator is used for WebGL even when running on EGL
2440 // because additional restrictions are needed (like only enabling
2441 // GL_OES_standard_derivatives on demand). It is used for the unit
2442 // tests because GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes
2443 // the empty string to CompileShader and this is not a valid shader.
2444 if (gfx::GetGLImplementation() == gfx::kGLImplementationMockGL ||
2445 base::CommandLine::ForCurrentProcess()->HasSwitch(
2446 switches::kDisableGLSLTranslator)) {
2447 use_shader_translator_ = false;
2451 GLES2DecoderImpl::~GLES2DecoderImpl() {
2454 bool GLES2DecoderImpl::Initialize(
2455 const scoped_refptr<gfx::GLSurface>& surface,
2456 const scoped_refptr<gfx::GLContext>& context,
2457 bool offscreen,
2458 const gfx::Size& offscreen_size,
2459 const DisallowedFeatures& disallowed_features,
2460 const std::vector<int32>& attribs) {
2461 TRACE_EVENT0("gpu", "GLES2DecoderImpl::Initialize");
2462 DCHECK(context->IsCurrent(surface.get()));
2463 DCHECK(!context_.get());
2465 ContextCreationAttribHelper attrib_parser;
2466 if (!attrib_parser.Parse(attribs))
2467 return false;
2469 surfaceless_ = surface->IsSurfaceless() && !offscreen;
2471 set_initialized();
2472 gpu_state_tracer_ = GPUStateTracer::Create(&state_);
2474 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2475 switches::kEnableGPUDebugging)) {
2476 set_debug(true);
2479 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2480 switches::kEnableGPUCommandLogging)) {
2481 set_log_commands(true);
2484 compile_shader_always_succeeds_ =
2485 base::CommandLine::ForCurrentProcess()->HasSwitch(
2486 switches::kCompileShaderAlwaysSucceeds);
2488 // Take ownership of the context and surface. The surface can be replaced with
2489 // SetSurface.
2490 context_ = context;
2491 surface_ = surface;
2493 // Create GPU Tracer for timing values.
2494 gpu_tracer_.reset(new GPUTracer(this));
2496 // Save the loseContextWhenOutOfMemory context creation attribute.
2497 lose_context_when_out_of_memory_ =
2498 attrib_parser.lose_context_when_out_of_memory;
2500 // If the failIfMajorPerformanceCaveat context creation attribute was true
2501 // and we are using a software renderer, fail.
2502 if (attrib_parser.fail_if_major_perf_caveat &&
2503 feature_info_->feature_flags().is_swiftshader) {
2504 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
2505 Destroy(true);
2506 return false;
2509 if (!group_->Initialize(this, disallowed_features)) {
2510 LOG(ERROR) << "GpuScheduler::InitializeCommon failed because group "
2511 << "failed to initialize.";
2512 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
2513 Destroy(true);
2514 return false;
2516 CHECK_GL_ERROR();
2518 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2519 switches::kEnableUnsafeES3APIs) &&
2520 attrib_parser.es3_context_required &&
2521 feature_info_->IsES3Capable()) {
2522 feature_info_->EnableES3Validators();
2523 set_unsafe_es3_apis_enabled(true);
2526 disallowed_features_ = disallowed_features;
2528 state_.attrib_values.resize(group_->max_vertex_attribs());
2529 vertex_array_manager_.reset(new VertexArrayManager());
2531 GLuint default_vertex_attrib_service_id = 0;
2532 if (features().native_vertex_array_object) {
2533 glGenVertexArraysOES(1, &default_vertex_attrib_service_id);
2534 glBindVertexArrayOES(default_vertex_attrib_service_id);
2537 state_.default_vertex_attrib_manager =
2538 CreateVertexAttribManager(0, default_vertex_attrib_service_id, false);
2540 state_.default_vertex_attrib_manager->Initialize(
2541 group_->max_vertex_attribs(),
2542 feature_info_->workarounds().init_vertex_attributes);
2544 // vertex_attrib_manager is set to default_vertex_attrib_manager by this call
2545 DoBindVertexArrayOES(0);
2547 query_manager_.reset(new QueryManager(this, feature_info_.get()));
2549 image_manager_.reset(new ImageManager);
2551 util_.set_num_compressed_texture_formats(
2552 validators_->compressed_texture_format.GetValues().size());
2554 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2555 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
2556 // OpenGL ES 2.0 does not have this issue.
2557 glEnableVertexAttribArray(0);
2559 glGenBuffersARB(1, &attrib_0_buffer_id_);
2560 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
2561 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
2562 glBindBuffer(GL_ARRAY_BUFFER, 0);
2563 glGenBuffersARB(1, &fixed_attrib_buffer_id_);
2565 state_.texture_units.resize(group_->max_texture_units());
2566 for (uint32 tt = 0; tt < state_.texture_units.size(); ++tt) {
2567 glActiveTexture(GL_TEXTURE0 + tt);
2568 // We want the last bind to be 2D.
2569 TextureRef* ref;
2570 if (features().oes_egl_image_external) {
2571 ref = texture_manager()->GetDefaultTextureInfo(
2572 GL_TEXTURE_EXTERNAL_OES);
2573 state_.texture_units[tt].bound_texture_external_oes = ref;
2574 glBindTexture(GL_TEXTURE_EXTERNAL_OES, ref ? ref->service_id() : 0);
2576 if (features().arb_texture_rectangle) {
2577 ref = texture_manager()->GetDefaultTextureInfo(
2578 GL_TEXTURE_RECTANGLE_ARB);
2579 state_.texture_units[tt].bound_texture_rectangle_arb = ref;
2580 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, ref ? ref->service_id() : 0);
2582 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
2583 state_.texture_units[tt].bound_texture_cube_map = ref;
2584 glBindTexture(GL_TEXTURE_CUBE_MAP, ref ? ref->service_id() : 0);
2585 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
2586 state_.texture_units[tt].bound_texture_2d = ref;
2587 glBindTexture(GL_TEXTURE_2D, ref ? ref->service_id() : 0);
2589 glActiveTexture(GL_TEXTURE0);
2590 CHECK_GL_ERROR();
2592 if (offscreen) {
2593 if (attrib_parser.samples > 0 && attrib_parser.sample_buffers > 0 &&
2594 features().chromium_framebuffer_multisample) {
2595 // Per ext_framebuffer_multisample spec, need max bound on sample count.
2596 // max_sample_count must be initialized to a sane value. If
2597 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2598 GLint max_sample_count = 1;
2599 glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count);
2600 offscreen_target_samples_ = std::min(attrib_parser.samples,
2601 max_sample_count);
2602 } else {
2603 offscreen_target_samples_ = 1;
2605 offscreen_target_buffer_preserved_ = attrib_parser.buffer_preserved;
2607 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
2608 const bool rgb8_supported =
2609 context_->HasExtension("GL_OES_rgb8_rgba8");
2610 // The only available default render buffer formats in GLES2 have very
2611 // little precision. Don't enable multisampling unless 8-bit render
2612 // buffer formats are available--instead fall back to 8-bit textures.
2613 if (rgb8_supported && offscreen_target_samples_ > 1) {
2614 offscreen_target_color_format_ = attrib_parser.alpha_size > 0 ?
2615 GL_RGBA8 : GL_RGB8;
2616 } else {
2617 offscreen_target_samples_ = 1;
2618 offscreen_target_color_format_ = attrib_parser.alpha_size > 0 ?
2619 GL_RGBA : GL_RGB;
2622 // ANGLE only supports packed depth/stencil formats, so use it if it is
2623 // available.
2624 const bool depth24_stencil8_supported =
2625 feature_info_->feature_flags().packed_depth24_stencil8;
2626 VLOG(1) << "GL_OES_packed_depth_stencil "
2627 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
2628 if ((attrib_parser.depth_size > 0 || attrib_parser.stencil_size > 0) &&
2629 depth24_stencil8_supported) {
2630 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2631 offscreen_target_stencil_format_ = 0;
2632 } else {
2633 // It may be the case that this depth/stencil combination is not
2634 // supported, but this will be checked later by CheckFramebufferStatus.
2635 offscreen_target_depth_format_ = attrib_parser.depth_size > 0 ?
2636 GL_DEPTH_COMPONENT16 : 0;
2637 offscreen_target_stencil_format_ = attrib_parser.stencil_size > 0 ?
2638 GL_STENCIL_INDEX8 : 0;
2640 } else {
2641 offscreen_target_color_format_ = attrib_parser.alpha_size > 0 ?
2642 GL_RGBA : GL_RGB;
2644 // If depth is requested at all, use the packed depth stencil format if
2645 // it's available, as some desktop GL drivers don't support any non-packed
2646 // formats for depth attachments.
2647 const bool depth24_stencil8_supported =
2648 feature_info_->feature_flags().packed_depth24_stencil8;
2649 VLOG(1) << "GL_EXT_packed_depth_stencil "
2650 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
2652 if ((attrib_parser.depth_size > 0 || attrib_parser.stencil_size > 0) &&
2653 depth24_stencil8_supported) {
2654 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2655 offscreen_target_stencil_format_ = 0;
2656 } else {
2657 offscreen_target_depth_format_ = attrib_parser.depth_size > 0 ?
2658 GL_DEPTH_COMPONENT : 0;
2659 offscreen_target_stencil_format_ = attrib_parser.stencil_size > 0 ?
2660 GL_STENCIL_INDEX : 0;
2664 offscreen_saved_color_format_ = attrib_parser.alpha_size > 0 ?
2665 GL_RGBA : GL_RGB;
2667 // Create the target frame buffer. This is the one that the client renders
2668 // directly to.
2669 offscreen_target_frame_buffer_.reset(new BackFramebuffer(this));
2670 offscreen_target_frame_buffer_->Create();
2671 // Due to GLES2 format limitations, either the color texture (for
2672 // non-multisampling) or the color render buffer (for multisampling) will be
2673 // attached to the offscreen frame buffer. The render buffer has more
2674 // limited formats available to it, but the texture can't do multisampling.
2675 if (IsOffscreenBufferMultisampled()) {
2676 offscreen_target_color_render_buffer_.reset(new BackRenderbuffer(
2677 renderbuffer_manager(), memory_tracker(), &state_));
2678 offscreen_target_color_render_buffer_->Create();
2679 } else {
2680 offscreen_target_color_texture_.reset(new BackTexture(
2681 memory_tracker(), &state_));
2682 offscreen_target_color_texture_->Create();
2684 offscreen_target_depth_render_buffer_.reset(new BackRenderbuffer(
2685 renderbuffer_manager(), memory_tracker(), &state_));
2686 offscreen_target_depth_render_buffer_->Create();
2687 offscreen_target_stencil_render_buffer_.reset(new BackRenderbuffer(
2688 renderbuffer_manager(), memory_tracker(), &state_));
2689 offscreen_target_stencil_render_buffer_->Create();
2691 // Create the saved offscreen texture. The target frame buffer is copied
2692 // here when SwapBuffers is called.
2693 offscreen_saved_frame_buffer_.reset(new BackFramebuffer(this));
2694 offscreen_saved_frame_buffer_->Create();
2696 offscreen_saved_color_texture_.reset(new BackTexture(
2697 memory_tracker(), &state_));
2698 offscreen_saved_color_texture_->Create();
2700 // Allocate the render buffers at their initial size and check the status
2701 // of the frame buffers is okay.
2702 if (!ResizeOffscreenFrameBuffer(offscreen_size)) {
2703 LOG(ERROR) << "Could not allocate offscreen buffer storage.";
2704 Destroy(true);
2705 return false;
2708 state_.viewport_width = offscreen_size.width();
2709 state_.viewport_height = offscreen_size.height();
2711 // Allocate the offscreen saved color texture.
2712 DCHECK(offscreen_saved_color_format_);
2713 offscreen_saved_color_texture_->AllocateStorage(
2714 gfx::Size(1, 1), offscreen_saved_color_format_, true);
2716 offscreen_saved_frame_buffer_->AttachRenderTexture(
2717 offscreen_saved_color_texture_.get());
2718 if (offscreen_saved_frame_buffer_->CheckStatus() !=
2719 GL_FRAMEBUFFER_COMPLETE) {
2720 LOG(ERROR) << "Offscreen saved FBO was incomplete.";
2721 Destroy(true);
2722 return false;
2725 // Bind to the new default frame buffer (the offscreen target frame buffer).
2726 // This should now be associated with ID zero.
2727 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2728 } else {
2729 glBindFramebufferEXT(GL_FRAMEBUFFER, GetBackbufferServiceId());
2730 // These are NOT if the back buffer has these proprorties. They are
2731 // if we want the command buffer to enforce them regardless of what
2732 // the real backbuffer is assuming the real back buffer gives us more than
2733 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2734 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2735 // can't do anything about that.
2737 if (!surfaceless_) {
2738 GLint alpha_bits = 0;
2739 GLint depth_bits = 0;
2740 GLint stencil_bits = 0;
2742 bool default_fb = (GetBackbufferServiceId() == 0);
2744 if (feature_info_->gl_version_info().is_desktop_core_profile) {
2745 glGetFramebufferAttachmentParameterivEXT(
2746 GL_FRAMEBUFFER,
2747 default_fb ? GL_BACK_LEFT : GL_COLOR_ATTACHMENT0,
2748 GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE, &alpha_bits);
2749 glGetFramebufferAttachmentParameterivEXT(
2750 GL_FRAMEBUFFER,
2751 default_fb ? GL_DEPTH : GL_DEPTH_ATTACHMENT,
2752 GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE, &depth_bits);
2753 glGetFramebufferAttachmentParameterivEXT(
2754 GL_FRAMEBUFFER,
2755 default_fb ? GL_STENCIL : GL_STENCIL_ATTACHMENT,
2756 GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE, &stencil_bits);
2757 } else {
2758 glGetIntegerv(GL_ALPHA_BITS, &alpha_bits);
2759 glGetIntegerv(GL_DEPTH_BITS, &depth_bits);
2760 glGetIntegerv(GL_STENCIL_BITS, &stencil_bits);
2763 // This checks if the user requested RGBA and we have RGBA then RGBA. If
2764 // the user requested RGB then RGB. If the user did not specify a
2765 // preference than use whatever we were given. Same for DEPTH and STENCIL.
2766 back_buffer_color_format_ =
2767 (attrib_parser.alpha_size != 0 && alpha_bits > 0) ? GL_RGBA : GL_RGB;
2768 back_buffer_has_depth_ = attrib_parser.depth_size != 0 && depth_bits > 0;
2769 back_buffer_has_stencil_ =
2770 attrib_parser.stencil_size != 0 && stencil_bits > 0;
2773 state_.viewport_width = surface->GetSize().width();
2774 state_.viewport_height = surface->GetSize().height();
2777 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2778 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2779 // isn't well documented; it was discovered in the Khronos OpenGL ES
2780 // mailing list archives. It also implicitly enables the desktop GL
2781 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2782 // variable in fragment shaders.
2783 if (!feature_info_->gl_version_info().BehavesLikeGLES()) {
2784 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
2785 glEnable(GL_POINT_SPRITE);
2788 has_robustness_extension_ =
2789 context->HasExtension("GL_ARB_robustness") ||
2790 context->HasExtension("GL_KHR_robustness") ||
2791 context->HasExtension("GL_EXT_robustness");
2793 if (!InitializeShaderTranslator()) {
2794 return false;
2797 GLint viewport_params[4] = { 0 };
2798 glGetIntegerv(GL_MAX_VIEWPORT_DIMS, viewport_params);
2799 viewport_max_width_ = viewport_params[0];
2800 viewport_max_height_ = viewport_params[1];
2802 state_.scissor_width = state_.viewport_width;
2803 state_.scissor_height = state_.viewport_height;
2805 // Set all the default state because some GL drivers get it wrong.
2806 state_.InitCapabilities(NULL);
2807 state_.InitState(NULL);
2808 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
2810 DoBindBuffer(GL_ARRAY_BUFFER, 0);
2811 DoBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
2812 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2813 DoBindRenderbuffer(GL_RENDERBUFFER, 0);
2814 DoBindValueBufferCHROMIUM(GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM, 0);
2816 bool call_gl_clear = !surfaceless_;
2817 #if defined(OS_ANDROID)
2818 // Temporary workaround for Android WebView because this clear ignores the
2819 // clip and corrupts that external UI of the App. Not calling glClear is ok
2820 // because the system already clears the buffer before each draw. Proper
2821 // fix might be setting the scissor clip properly before initialize. See
2822 // crbug.com/259023 for details.
2823 call_gl_clear = surface_->GetHandle();
2824 #endif
2825 if (call_gl_clear) {
2826 // Clear the backbuffer.
2827 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2830 supports_post_sub_buffer_ = surface->SupportsPostSubBuffer();
2831 if (feature_info_->workarounds()
2832 .disable_post_sub_buffers_for_onscreen_surfaces &&
2833 !surface->IsOffscreen())
2834 supports_post_sub_buffer_ = false;
2836 if (feature_info_->workarounds().reverse_point_sprite_coord_origin) {
2837 glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT);
2840 if (feature_info_->workarounds().unbind_fbo_on_context_switch) {
2841 context_->SetUnbindFboOnMakeCurrent();
2844 // Only compositor contexts are known to use only the subset of GL
2845 // that can be safely migrated between the iGPU and the dGPU. Mark
2846 // those contexts as safe to forcibly transition between the GPUs.
2847 // http://crbug.com/180876, http://crbug.com/227228
2848 if (!offscreen)
2849 context_->SetSafeToForceGpuSwitch();
2851 async_pixel_transfer_manager_.reset(
2852 AsyncPixelTransferManager::Create(context.get()));
2853 async_pixel_transfer_manager_->Initialize(texture_manager());
2855 if (workarounds().gl_clear_broken) {
2856 DCHECK(!clear_framebuffer_blit_.get());
2857 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glClearWorkaroundInit");
2858 clear_framebuffer_blit_.reset(new ClearFramebufferResourceManager(this));
2859 if (LOCAL_PEEK_GL_ERROR("glClearWorkaroundInit") != GL_NO_ERROR)
2860 return false;
2863 framebuffer_manager()->AddObserver(this);
2865 return true;
2868 Capabilities GLES2DecoderImpl::GetCapabilities() {
2869 DCHECK(initialized());
2871 Capabilities caps;
2872 caps.VisitPrecisions([](GLenum shader, GLenum type,
2873 Capabilities::ShaderPrecision* shader_precision) {
2874 GLint range[2] = {0, 0};
2875 GLint precision = 0;
2876 GetShaderPrecisionFormatImpl(shader, type, range, &precision);
2877 shader_precision->min_range = range[0];
2878 shader_precision->max_range = range[1];
2879 shader_precision->precision = precision;
2881 DoGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS,
2882 &caps.max_combined_texture_image_units);
2883 DoGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &caps.max_cube_map_texture_size);
2884 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS,
2885 &caps.max_fragment_uniform_vectors);
2886 DoGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &caps.max_renderbuffer_size);
2887 DoGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &caps.max_texture_image_units);
2888 DoGetIntegerv(GL_MAX_TEXTURE_SIZE, &caps.max_texture_size);
2889 DoGetIntegerv(GL_MAX_VARYING_VECTORS, &caps.max_varying_vectors);
2890 DoGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &caps.max_vertex_attribs);
2891 DoGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS,
2892 &caps.max_vertex_texture_image_units);
2893 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS,
2894 &caps.max_vertex_uniform_vectors);
2895 DoGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS,
2896 &caps.num_compressed_texture_formats);
2897 DoGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS, &caps.num_shader_binary_formats);
2898 DoGetIntegerv(GL_BIND_GENERATES_RESOURCE_CHROMIUM,
2899 &caps.bind_generates_resource_chromium);
2900 if (unsafe_es3_apis_enabled()) {
2901 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS,
2902 &caps.max_transform_feedback_separate_attribs);
2903 DoGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS,
2904 &caps.max_uniform_buffer_bindings);
2905 DoGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT,
2906 &caps.uniform_buffer_offset_alignment);
2909 caps.egl_image_external =
2910 feature_info_->feature_flags().oes_egl_image_external;
2911 caps.texture_format_atc =
2912 feature_info_->feature_flags().ext_texture_format_atc;
2913 caps.texture_format_bgra8888 =
2914 feature_info_->feature_flags().ext_texture_format_bgra8888;
2915 caps.texture_format_dxt1 =
2916 feature_info_->feature_flags().ext_texture_format_dxt1;
2917 caps.texture_format_dxt5 =
2918 feature_info_->feature_flags().ext_texture_format_dxt5;
2919 caps.texture_format_etc1 =
2920 feature_info_->feature_flags().oes_compressed_etc1_rgb8_texture;
2921 caps.texture_format_etc1_npot =
2922 caps.texture_format_etc1 && !workarounds().etc1_power_of_two_only;
2923 caps.texture_rectangle = feature_info_->feature_flags().arb_texture_rectangle;
2924 caps.texture_usage = feature_info_->feature_flags().angle_texture_usage;
2925 caps.texture_storage = feature_info_->feature_flags().ext_texture_storage;
2926 caps.discard_framebuffer =
2927 feature_info_->feature_flags().ext_discard_framebuffer;
2928 caps.sync_query = feature_info_->feature_flags().chromium_sync_query;
2930 #if defined(OS_MACOSX)
2931 // This is unconditionally true on mac, no need to test for it at runtime.
2932 caps.iosurface = true;
2933 #endif
2935 caps.post_sub_buffer = supports_post_sub_buffer_;
2936 caps.image = true;
2938 caps.blend_equation_advanced =
2939 feature_info_->feature_flags().blend_equation_advanced;
2940 caps.blend_equation_advanced_coherent =
2941 feature_info_->feature_flags().blend_equation_advanced_coherent;
2942 caps.texture_rg = feature_info_->feature_flags().ext_texture_rg;
2943 return caps;
2946 void GLES2DecoderImpl::UpdateCapabilities() {
2947 util_.set_num_compressed_texture_formats(
2948 validators_->compressed_texture_format.GetValues().size());
2949 util_.set_num_shader_binary_formats(
2950 validators_->shader_binary_format.GetValues().size());
2953 bool GLES2DecoderImpl::InitializeShaderTranslator() {
2954 TRACE_EVENT0("gpu", "GLES2DecoderImpl::InitializeShaderTranslator");
2956 if (!use_shader_translator_) {
2957 return true;
2959 ShBuiltInResources resources;
2960 ShInitBuiltInResources(&resources);
2961 resources.MaxVertexAttribs = group_->max_vertex_attribs();
2962 resources.MaxVertexUniformVectors =
2963 group_->max_vertex_uniform_vectors();
2964 resources.MaxVaryingVectors = group_->max_varying_vectors();
2965 resources.MaxVertexTextureImageUnits =
2966 group_->max_vertex_texture_image_units();
2967 resources.MaxCombinedTextureImageUnits = group_->max_texture_units();
2968 resources.MaxTextureImageUnits = group_->max_texture_image_units();
2969 resources.MaxFragmentUniformVectors =
2970 group_->max_fragment_uniform_vectors();
2971 resources.MaxDrawBuffers = group_->max_draw_buffers();
2972 resources.MaxExpressionComplexity = 256;
2973 resources.MaxCallStackDepth = 256;
2975 GLint range[2] = { 0, 0 };
2976 GLint precision = 0;
2977 GetShaderPrecisionFormatImpl(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT,
2978 range, &precision);
2979 resources.FragmentPrecisionHigh =
2980 PrecisionMeetsSpecForHighpFloat(range[0], range[1], precision);
2982 if (force_webgl_glsl_validation_) {
2983 resources.OES_standard_derivatives = derivatives_explicitly_enabled_;
2984 resources.EXT_frag_depth = frag_depth_explicitly_enabled_;
2985 resources.EXT_draw_buffers = draw_buffers_explicitly_enabled_;
2986 if (!draw_buffers_explicitly_enabled_)
2987 resources.MaxDrawBuffers = 1;
2988 resources.EXT_shader_texture_lod = shader_texture_lod_explicitly_enabled_;
2989 resources.NV_draw_buffers =
2990 draw_buffers_explicitly_enabled_ && features().nv_draw_buffers;
2991 } else {
2992 resources.OES_standard_derivatives =
2993 features().oes_standard_derivatives ? 1 : 0;
2994 resources.ARB_texture_rectangle =
2995 features().arb_texture_rectangle ? 1 : 0;
2996 resources.OES_EGL_image_external =
2997 features().oes_egl_image_external ? 1 : 0;
2998 resources.EXT_draw_buffers =
2999 features().ext_draw_buffers ? 1 : 0;
3000 resources.EXT_frag_depth =
3001 features().ext_frag_depth ? 1 : 0;
3002 resources.EXT_shader_texture_lod =
3003 features().ext_shader_texture_lod ? 1 : 0;
3004 resources.NV_draw_buffers =
3005 features().nv_draw_buffers ? 1 : 0;
3008 ShShaderSpec shader_spec;
3009 if (force_webgl_glsl_validation_) {
3010 shader_spec = unsafe_es3_apis_enabled() ? SH_WEBGL2_SPEC : SH_WEBGL_SPEC;
3011 } else {
3012 shader_spec = unsafe_es3_apis_enabled() ? SH_GLES3_SPEC : SH_GLES2_SPEC;
3015 if ((shader_spec == SH_WEBGL_SPEC || shader_spec == SH_WEBGL2_SPEC) &&
3016 features().enable_shader_name_hashing)
3017 resources.HashFunction = &CityHash64;
3018 else
3019 resources.HashFunction = NULL;
3020 ShaderTranslatorInterface::GlslImplementationType implementation_type =
3021 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 ?
3022 ShaderTranslatorInterface::kGlslES : ShaderTranslatorInterface::kGlsl;
3023 int driver_bug_workarounds = 0;
3024 if (workarounds().needs_glsl_built_in_function_emulation)
3025 driver_bug_workarounds |= SH_EMULATE_BUILT_IN_FUNCTIONS;
3026 if (workarounds().init_gl_position_in_vertex_shader)
3027 driver_bug_workarounds |= SH_INIT_GL_POSITION;
3028 if (workarounds().unfold_short_circuit_as_ternary_operation)
3029 driver_bug_workarounds |= SH_UNFOLD_SHORT_CIRCUIT;
3030 if (workarounds().init_varyings_without_static_use)
3031 driver_bug_workarounds |= SH_INIT_VARYINGS_WITHOUT_STATIC_USE;
3032 if (workarounds().unroll_for_loop_with_sampler_array_index)
3033 driver_bug_workarounds |= SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX;
3034 if (workarounds().scalarize_vec_and_mat_constructor_args)
3035 driver_bug_workarounds |= SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS;
3036 if (workarounds().regenerate_struct_names)
3037 driver_bug_workarounds |= SH_REGENERATE_STRUCT_NAMES;
3039 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
3040 switches::kEmulateShaderPrecision))
3041 resources.WEBGL_debug_shader_precision = true;
3043 vertex_translator_ = shader_translator_cache()->GetTranslator(
3044 GL_VERTEX_SHADER,
3045 shader_spec,
3046 &resources,
3047 implementation_type,
3048 static_cast<ShCompileOptions>(driver_bug_workarounds));
3049 if (!vertex_translator_.get()) {
3050 LOG(ERROR) << "Could not initialize vertex shader translator.";
3051 Destroy(true);
3052 return false;
3055 fragment_translator_ = shader_translator_cache()->GetTranslator(
3056 GL_FRAGMENT_SHADER,
3057 shader_spec,
3058 &resources,
3059 implementation_type,
3060 static_cast<ShCompileOptions>(driver_bug_workarounds));
3061 if (!fragment_translator_.get()) {
3062 LOG(ERROR) << "Could not initialize fragment shader translator.";
3063 Destroy(true);
3064 return false;
3066 return true;
3069 bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
3070 for (GLsizei ii = 0; ii < n; ++ii) {
3071 if (GetBuffer(client_ids[ii])) {
3072 return false;
3075 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3076 glGenBuffersARB(n, service_ids.get());
3077 for (GLsizei ii = 0; ii < n; ++ii) {
3078 CreateBuffer(client_ids[ii], service_ids[ii]);
3080 return true;
3083 bool GLES2DecoderImpl::GenFramebuffersHelper(
3084 GLsizei n, const GLuint* client_ids) {
3085 for (GLsizei ii = 0; ii < n; ++ii) {
3086 if (GetFramebuffer(client_ids[ii])) {
3087 return false;
3090 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3091 glGenFramebuffersEXT(n, service_ids.get());
3092 for (GLsizei ii = 0; ii < n; ++ii) {
3093 CreateFramebuffer(client_ids[ii], service_ids[ii]);
3095 return true;
3098 bool GLES2DecoderImpl::GenRenderbuffersHelper(
3099 GLsizei n, const GLuint* client_ids) {
3100 for (GLsizei ii = 0; ii < n; ++ii) {
3101 if (GetRenderbuffer(client_ids[ii])) {
3102 return false;
3105 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3106 glGenRenderbuffersEXT(n, service_ids.get());
3107 for (GLsizei ii = 0; ii < n; ++ii) {
3108 CreateRenderbuffer(client_ids[ii], service_ids[ii]);
3110 return true;
3113 bool GLES2DecoderImpl::GenValuebuffersCHROMIUMHelper(GLsizei n,
3114 const GLuint* client_ids) {
3115 for (GLsizei ii = 0; ii < n; ++ii) {
3116 if (GetValuebuffer(client_ids[ii])) {
3117 return false;
3120 for (GLsizei ii = 0; ii < n; ++ii) {
3121 CreateValuebuffer(client_ids[ii]);
3123 return true;
3126 bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
3127 for (GLsizei ii = 0; ii < n; ++ii) {
3128 if (GetTexture(client_ids[ii])) {
3129 return false;
3132 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3133 glGenTextures(n, service_ids.get());
3134 for (GLsizei ii = 0; ii < n; ++ii) {
3135 CreateTexture(client_ids[ii], service_ids[ii]);
3137 return true;
3140 void GLES2DecoderImpl::DeleteBuffersHelper(
3141 GLsizei n, const GLuint* client_ids) {
3142 for (GLsizei ii = 0; ii < n; ++ii) {
3143 Buffer* buffer = GetBuffer(client_ids[ii]);
3144 if (buffer && !buffer->IsDeleted()) {
3145 buffer->RemoveMappedRange();
3146 state_.vertex_attrib_manager->Unbind(buffer);
3147 if (state_.bound_array_buffer.get() == buffer) {
3148 state_.bound_array_buffer = NULL;
3150 RemoveBuffer(client_ids[ii]);
3155 void GLES2DecoderImpl::DeleteFramebuffersHelper(
3156 GLsizei n, const GLuint* client_ids) {
3157 bool supports_separate_framebuffer_binds =
3158 features().chromium_framebuffer_multisample;
3160 for (GLsizei ii = 0; ii < n; ++ii) {
3161 Framebuffer* framebuffer =
3162 GetFramebuffer(client_ids[ii]);
3163 if (framebuffer && !framebuffer->IsDeleted()) {
3164 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
3165 GLenum target = supports_separate_framebuffer_binds ?
3166 GL_DRAW_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
3168 // Unbind attachments on FBO before deletion.
3169 if (workarounds().unbind_attachments_on_bound_render_fbo_delete)
3170 framebuffer->DoUnbindGLAttachmentsForWorkaround(target);
3172 glBindFramebufferEXT(target, GetBackbufferServiceId());
3173 framebuffer_state_.bound_draw_framebuffer = NULL;
3174 framebuffer_state_.clear_state_dirty = true;
3176 if (framebuffer == framebuffer_state_.bound_read_framebuffer.get()) {
3177 framebuffer_state_.bound_read_framebuffer = NULL;
3178 GLenum target = supports_separate_framebuffer_binds ?
3179 GL_READ_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
3180 glBindFramebufferEXT(target, GetBackbufferServiceId());
3182 OnFboChanged();
3183 RemoveFramebuffer(client_ids[ii]);
3188 void GLES2DecoderImpl::DeleteRenderbuffersHelper(
3189 GLsizei n, const GLuint* client_ids) {
3190 bool supports_separate_framebuffer_binds =
3191 features().chromium_framebuffer_multisample;
3192 for (GLsizei ii = 0; ii < n; ++ii) {
3193 Renderbuffer* renderbuffer =
3194 GetRenderbuffer(client_ids[ii]);
3195 if (renderbuffer && !renderbuffer->IsDeleted()) {
3196 if (state_.bound_renderbuffer.get() == renderbuffer) {
3197 state_.bound_renderbuffer = NULL;
3199 // Unbind from current framebuffers.
3200 if (supports_separate_framebuffer_binds) {
3201 if (framebuffer_state_.bound_read_framebuffer.get()) {
3202 framebuffer_state_.bound_read_framebuffer
3203 ->UnbindRenderbuffer(GL_READ_FRAMEBUFFER_EXT, renderbuffer);
3205 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3206 framebuffer_state_.bound_draw_framebuffer
3207 ->UnbindRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT, renderbuffer);
3209 } else {
3210 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3211 framebuffer_state_.bound_draw_framebuffer
3212 ->UnbindRenderbuffer(GL_FRAMEBUFFER, renderbuffer);
3215 framebuffer_state_.clear_state_dirty = true;
3216 RemoveRenderbuffer(client_ids[ii]);
3221 void GLES2DecoderImpl::DeleteValuebuffersCHROMIUMHelper(
3222 GLsizei n,
3223 const GLuint* client_ids) {
3224 for (GLsizei ii = 0; ii < n; ++ii) {
3225 Valuebuffer* valuebuffer = GetValuebuffer(client_ids[ii]);
3226 if (valuebuffer) {
3227 if (state_.bound_valuebuffer.get() == valuebuffer) {
3228 state_.bound_valuebuffer = NULL;
3230 RemoveValuebuffer(client_ids[ii]);
3235 void GLES2DecoderImpl::DeleteTexturesHelper(
3236 GLsizei n, const GLuint* client_ids) {
3237 bool supports_separate_framebuffer_binds =
3238 features().chromium_framebuffer_multisample;
3239 for (GLsizei ii = 0; ii < n; ++ii) {
3240 TextureRef* texture_ref = GetTexture(client_ids[ii]);
3241 if (texture_ref) {
3242 Texture* texture = texture_ref->texture();
3243 if (texture->IsAttachedToFramebuffer()) {
3244 framebuffer_state_.clear_state_dirty = true;
3246 // Unbind texture_ref from texture_ref units.
3247 for (size_t jj = 0; jj < state_.texture_units.size(); ++jj) {
3248 state_.texture_units[jj].Unbind(texture_ref);
3250 // Unbind from current framebuffers.
3251 if (supports_separate_framebuffer_binds) {
3252 if (framebuffer_state_.bound_read_framebuffer.get()) {
3253 framebuffer_state_.bound_read_framebuffer
3254 ->UnbindTexture(GL_READ_FRAMEBUFFER_EXT, texture_ref);
3256 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3257 framebuffer_state_.bound_draw_framebuffer
3258 ->UnbindTexture(GL_DRAW_FRAMEBUFFER_EXT, texture_ref);
3260 } else {
3261 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3262 framebuffer_state_.bound_draw_framebuffer
3263 ->UnbindTexture(GL_FRAMEBUFFER, texture_ref);
3266 #if defined(OS_MACOSX)
3267 GLuint service_id = texture->service_id();
3268 if (texture->target() == GL_TEXTURE_RECTANGLE_ARB) {
3269 ReleaseIOSurfaceForTexture(service_id);
3271 #endif
3272 RemoveTexture(client_ids[ii]);
3277 // } // anonymous namespace
3279 bool GLES2DecoderImpl::MakeCurrent() {
3280 if (!context_.get())
3281 return false;
3283 if (!context_->MakeCurrent(surface_.get()) || WasContextLost()) {
3284 LOG(ERROR) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
3286 MaybeExitOnContextLost();
3288 return false;
3291 ProcessFinishedAsyncTransfers();
3293 // Rebind the FBO if it was unbound by the context.
3294 if (workarounds().unbind_fbo_on_context_switch)
3295 RestoreFramebufferBindings();
3297 framebuffer_state_.clear_state_dirty = true;
3299 return true;
3302 void GLES2DecoderImpl::ProcessFinishedAsyncTransfers() {
3303 ProcessPendingReadPixels();
3304 if (engine() && query_manager_.get())
3305 query_manager_->ProcessPendingTransferQueries();
3307 // TODO(epenner): Is there a better place to do this?
3308 // This needs to occur before we execute any batch of commands
3309 // from the client, as the client may have recieved an async
3310 // completion while issuing those commands.
3311 // "DidFlushStart" would be ideal if we had such a callback.
3312 async_pixel_transfer_manager_->BindCompletedAsyncTransfers();
3315 static void RebindCurrentFramebuffer(
3316 GLenum target,
3317 Framebuffer* framebuffer,
3318 GLuint back_buffer_service_id) {
3319 GLuint framebuffer_id = framebuffer ? framebuffer->service_id() : 0;
3321 if (framebuffer_id == 0) {
3322 framebuffer_id = back_buffer_service_id;
3325 glBindFramebufferEXT(target, framebuffer_id);
3328 void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
3329 framebuffer_state_.clear_state_dirty = true;
3331 if (!features().chromium_framebuffer_multisample) {
3332 RebindCurrentFramebuffer(
3333 GL_FRAMEBUFFER,
3334 framebuffer_state_.bound_draw_framebuffer.get(),
3335 GetBackbufferServiceId());
3336 } else {
3337 RebindCurrentFramebuffer(
3338 GL_READ_FRAMEBUFFER_EXT,
3339 framebuffer_state_.bound_read_framebuffer.get(),
3340 GetBackbufferServiceId());
3341 RebindCurrentFramebuffer(
3342 GL_DRAW_FRAMEBUFFER_EXT,
3343 framebuffer_state_.bound_draw_framebuffer.get(),
3344 GetBackbufferServiceId());
3346 OnFboChanged();
3349 bool GLES2DecoderImpl::CheckFramebufferValid(
3350 Framebuffer* framebuffer,
3351 GLenum target, const char* func_name) {
3352 if (!framebuffer) {
3353 if (surfaceless_)
3354 return false;
3355 if (backbuffer_needs_clear_bits_) {
3356 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3357 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1.f);
3358 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3359 glClearStencil(0);
3360 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
3361 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
3362 glClearDepth(1.0f);
3363 state_.SetDeviceDepthMask(GL_TRUE);
3364 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
3365 bool reset_draw_buffer = false;
3366 if ((backbuffer_needs_clear_bits_ & GL_COLOR_BUFFER_BIT) != 0 &&
3367 group_->draw_buffer() == GL_NONE) {
3368 reset_draw_buffer = true;
3369 GLenum buf = GL_BACK;
3370 if (GetBackbufferServiceId() != 0) // emulated backbuffer
3371 buf = GL_COLOR_ATTACHMENT0;
3372 glDrawBuffersARB(1, &buf);
3374 glClear(backbuffer_needs_clear_bits_);
3375 if (reset_draw_buffer) {
3376 GLenum buf = GL_NONE;
3377 glDrawBuffersARB(1, &buf);
3379 backbuffer_needs_clear_bits_ = 0;
3380 RestoreClearState();
3382 return true;
3385 if (framebuffer_manager()->IsComplete(framebuffer)) {
3386 return true;
3389 GLenum completeness = framebuffer->IsPossiblyComplete();
3390 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
3391 LOCAL_SET_GL_ERROR(
3392 GL_INVALID_FRAMEBUFFER_OPERATION, func_name, "framebuffer incomplete");
3393 return false;
3396 // Are all the attachments cleared?
3397 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
3398 texture_manager()->HaveUnclearedMips()) {
3399 if (!framebuffer->IsCleared()) {
3400 // Can we clear them?
3401 if (framebuffer->GetStatus(texture_manager(), target) !=
3402 GL_FRAMEBUFFER_COMPLETE) {
3403 LOCAL_SET_GL_ERROR(
3404 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
3405 "framebuffer incomplete (clear)");
3406 return false;
3408 ClearUnclearedAttachments(target, framebuffer);
3412 if (!framebuffer_manager()->IsComplete(framebuffer)) {
3413 if (framebuffer->GetStatus(texture_manager(), target) !=
3414 GL_FRAMEBUFFER_COMPLETE) {
3415 LOCAL_SET_GL_ERROR(
3416 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
3417 "framebuffer incomplete (check)");
3418 return false;
3420 framebuffer_manager()->MarkAsComplete(framebuffer);
3423 // NOTE: At this point we don't know if the framebuffer is complete but
3424 // we DO know that everything that needs to be cleared has been cleared.
3425 return true;
3428 bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name) {
3429 if (!features().chromium_framebuffer_multisample) {
3430 bool valid = CheckFramebufferValid(
3431 framebuffer_state_.bound_draw_framebuffer.get(), GL_FRAMEBUFFER_EXT,
3432 func_name);
3434 if (valid)
3435 OnUseFramebuffer();
3437 return valid;
3439 return CheckFramebufferValid(framebuffer_state_.bound_draw_framebuffer.get(),
3440 GL_DRAW_FRAMEBUFFER_EXT,
3441 func_name) &&
3442 CheckFramebufferValid(framebuffer_state_.bound_read_framebuffer.get(),
3443 GL_READ_FRAMEBUFFER_EXT,
3444 func_name);
3447 bool GLES2DecoderImpl::CheckBoundReadFramebufferColorAttachment(
3448 const char* func_name) {
3449 Framebuffer* framebuffer = features().chromium_framebuffer_multisample ?
3450 framebuffer_state_.bound_read_framebuffer.get() :
3451 framebuffer_state_.bound_draw_framebuffer.get();
3452 if (!framebuffer)
3453 return true;
3454 if (framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0) == NULL) {
3455 LOCAL_SET_GL_ERROR(
3456 GL_INVALID_OPERATION, func_name, "no color image attached");
3457 return false;
3459 return true;
3462 bool GLES2DecoderImpl::FormsTextureCopyingFeedbackLoop(
3463 TextureRef* texture, GLint level) {
3464 Framebuffer* framebuffer = features().chromium_framebuffer_multisample ?
3465 framebuffer_state_.bound_read_framebuffer.get() :
3466 framebuffer_state_.bound_draw_framebuffer.get();
3467 if (!framebuffer)
3468 return false;
3469 const Framebuffer::Attachment* attachment = framebuffer->GetAttachment(
3470 GL_COLOR_ATTACHMENT0);
3471 if (!attachment)
3472 return false;
3473 return attachment->FormsFeedbackLoop(texture, level);
3476 gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
3477 Framebuffer* framebuffer =
3478 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3479 if (framebuffer != NULL) {
3480 const Framebuffer::Attachment* attachment =
3481 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
3482 if (attachment) {
3483 return gfx::Size(attachment->width(), attachment->height());
3485 return gfx::Size(0, 0);
3486 } else if (offscreen_target_frame_buffer_.get()) {
3487 return offscreen_size_;
3488 } else {
3489 return surface_->GetSize();
3493 GLenum GLES2DecoderImpl::GetBoundReadFrameBufferTextureType() {
3494 Framebuffer* framebuffer =
3495 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3496 if (framebuffer != NULL) {
3497 return framebuffer->GetColorAttachmentTextureType();
3498 } else {
3499 return GL_UNSIGNED_BYTE;
3503 GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
3504 Framebuffer* framebuffer =
3505 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3506 if (framebuffer != NULL) {
3507 return framebuffer->GetColorAttachmentFormat();
3508 } else if (offscreen_target_frame_buffer_.get()) {
3509 return offscreen_target_color_format_;
3510 } else {
3511 return back_buffer_color_format_;
3515 GLenum GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
3516 Framebuffer* framebuffer =
3517 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3518 if (framebuffer != NULL) {
3519 return framebuffer->GetColorAttachmentFormat();
3520 } else if (offscreen_target_frame_buffer_.get()) {
3521 return offscreen_target_color_format_;
3522 } else {
3523 return back_buffer_color_format_;
3527 void GLES2DecoderImpl::UpdateParentTextureInfo() {
3528 if (!offscreen_saved_color_texture_info_.get())
3529 return;
3530 GLenum target = offscreen_saved_color_texture_info_->texture()->target();
3531 glBindTexture(target, offscreen_saved_color_texture_info_->service_id());
3532 texture_manager()->SetLevelInfo(
3533 offscreen_saved_color_texture_info_.get(),
3534 GL_TEXTURE_2D,
3535 0, // level
3536 GL_RGBA,
3537 offscreen_size_.width(),
3538 offscreen_size_.height(),
3539 1, // depth
3540 0, // border
3541 GL_RGBA,
3542 GL_UNSIGNED_BYTE,
3543 true);
3544 texture_manager()->SetParameteri(
3545 "UpdateParentTextureInfo",
3546 GetErrorState(),
3547 offscreen_saved_color_texture_info_.get(),
3548 GL_TEXTURE_MAG_FILTER,
3549 GL_LINEAR);
3550 texture_manager()->SetParameteri(
3551 "UpdateParentTextureInfo",
3552 GetErrorState(),
3553 offscreen_saved_color_texture_info_.get(),
3554 GL_TEXTURE_MIN_FILTER,
3555 GL_LINEAR);
3556 texture_manager()->SetParameteri(
3557 "UpdateParentTextureInfo",
3558 GetErrorState(),
3559 offscreen_saved_color_texture_info_.get(),
3560 GL_TEXTURE_WRAP_S,
3561 GL_CLAMP_TO_EDGE);
3562 texture_manager()->SetParameteri(
3563 "UpdateParentTextureInfo",
3564 GetErrorState(),
3565 offscreen_saved_color_texture_info_.get(),
3566 GL_TEXTURE_WRAP_T,
3567 GL_CLAMP_TO_EDGE);
3568 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
3569 &state_, target);
3570 glBindTexture(target, texture_ref ? texture_ref->service_id() : 0);
3573 void GLES2DecoderImpl::SetResizeCallback(
3574 const base::Callback<void(gfx::Size, float)>& callback) {
3575 resize_callback_ = callback;
3578 Logger* GLES2DecoderImpl::GetLogger() {
3579 return &logger_;
3582 void GLES2DecoderImpl::BeginDecoding() {
3583 gpu_tracer_->BeginDecoding();
3584 gpu_trace_commands_ = gpu_tracer_->IsTracing() && *gpu_decoder_category_;
3585 gpu_debug_commands_ = log_commands() || debug() || gpu_trace_commands_ ||
3586 (*cb_command_trace_category_ != 0);
3589 void GLES2DecoderImpl::EndDecoding() {
3590 gpu_tracer_->EndDecoding();
3593 ErrorState* GLES2DecoderImpl::GetErrorState() {
3594 return state_.GetErrorState();
3597 void GLES2DecoderImpl::SetShaderCacheCallback(
3598 const ShaderCacheCallback& callback) {
3599 shader_cache_callback_ = callback;
3602 void GLES2DecoderImpl::SetWaitSyncPointCallback(
3603 const WaitSyncPointCallback& callback) {
3604 wait_sync_point_callback_ = callback;
3607 AsyncPixelTransferManager*
3608 GLES2DecoderImpl::GetAsyncPixelTransferManager() {
3609 return async_pixel_transfer_manager_.get();
3612 void GLES2DecoderImpl::ResetAsyncPixelTransferManagerForTest() {
3613 async_pixel_transfer_manager_.reset();
3616 void GLES2DecoderImpl::SetAsyncPixelTransferManagerForTest(
3617 AsyncPixelTransferManager* manager) {
3618 async_pixel_transfer_manager_ = make_scoped_ptr(manager);
3621 bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
3622 uint32* service_texture_id) {
3623 TextureRef* texture_ref = texture_manager()->GetTexture(client_texture_id);
3624 if (texture_ref) {
3625 *service_texture_id = texture_ref->service_id();
3626 return true;
3628 return false;
3631 uint32 GLES2DecoderImpl::GetTextureUploadCount() {
3632 return texture_state_.texture_upload_count +
3633 async_pixel_transfer_manager_->GetTextureUploadCount();
3636 base::TimeDelta GLES2DecoderImpl::GetTotalTextureUploadTime() {
3637 return texture_state_.total_texture_upload_time +
3638 async_pixel_transfer_manager_->GetTotalTextureUploadTime();
3641 base::TimeDelta GLES2DecoderImpl::GetTotalProcessingCommandsTime() {
3642 return total_processing_commands_time_;
3645 void GLES2DecoderImpl::AddProcessingCommandsTime(base::TimeDelta time) {
3646 total_processing_commands_time_ += time;
3649 void GLES2DecoderImpl::Destroy(bool have_context) {
3650 if (!initialized())
3651 return;
3653 DCHECK(!have_context || context_->IsCurrent(NULL));
3655 // Unbind everything.
3656 state_.vertex_attrib_manager = NULL;
3657 state_.default_vertex_attrib_manager = NULL;
3658 state_.texture_units.clear();
3659 state_.bound_array_buffer = NULL;
3660 state_.current_queries.clear();
3661 framebuffer_state_.bound_read_framebuffer = NULL;
3662 framebuffer_state_.bound_draw_framebuffer = NULL;
3663 state_.bound_renderbuffer = NULL;
3664 state_.bound_valuebuffer = NULL;
3666 if (offscreen_saved_color_texture_info_.get()) {
3667 DCHECK(offscreen_target_color_texture_);
3668 DCHECK_EQ(offscreen_saved_color_texture_info_->service_id(),
3669 offscreen_saved_color_texture_->id());
3670 offscreen_saved_color_texture_->Invalidate();
3671 offscreen_saved_color_texture_info_ = NULL;
3673 if (have_context) {
3674 if (copy_texture_CHROMIUM_.get()) {
3675 copy_texture_CHROMIUM_->Destroy();
3676 copy_texture_CHROMIUM_.reset();
3679 clear_framebuffer_blit_.reset();
3681 if (state_.current_program.get()) {
3682 program_manager()->UnuseProgram(shader_manager(),
3683 state_.current_program.get());
3686 if (attrib_0_buffer_id_) {
3687 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
3689 if (fixed_attrib_buffer_id_) {
3690 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_);
3693 if (validation_texture_) {
3694 glDeleteTextures(1, &validation_texture_);
3695 glDeleteFramebuffersEXT(1, &validation_fbo_multisample_);
3696 glDeleteFramebuffersEXT(1, &validation_fbo_);
3699 if (offscreen_target_frame_buffer_.get())
3700 offscreen_target_frame_buffer_->Destroy();
3701 if (offscreen_target_color_texture_.get())
3702 offscreen_target_color_texture_->Destroy();
3703 if (offscreen_target_color_render_buffer_.get())
3704 offscreen_target_color_render_buffer_->Destroy();
3705 if (offscreen_target_depth_render_buffer_.get())
3706 offscreen_target_depth_render_buffer_->Destroy();
3707 if (offscreen_target_stencil_render_buffer_.get())
3708 offscreen_target_stencil_render_buffer_->Destroy();
3709 if (offscreen_saved_frame_buffer_.get())
3710 offscreen_saved_frame_buffer_->Destroy();
3711 if (offscreen_saved_color_texture_.get())
3712 offscreen_saved_color_texture_->Destroy();
3713 if (offscreen_resolved_frame_buffer_.get())
3714 offscreen_resolved_frame_buffer_->Destroy();
3715 if (offscreen_resolved_color_texture_.get())
3716 offscreen_resolved_color_texture_->Destroy();
3717 } else {
3718 if (offscreen_target_frame_buffer_.get())
3719 offscreen_target_frame_buffer_->Invalidate();
3720 if (offscreen_target_color_texture_.get())
3721 offscreen_target_color_texture_->Invalidate();
3722 if (offscreen_target_color_render_buffer_.get())
3723 offscreen_target_color_render_buffer_->Invalidate();
3724 if (offscreen_target_depth_render_buffer_.get())
3725 offscreen_target_depth_render_buffer_->Invalidate();
3726 if (offscreen_target_stencil_render_buffer_.get())
3727 offscreen_target_stencil_render_buffer_->Invalidate();
3728 if (offscreen_saved_frame_buffer_.get())
3729 offscreen_saved_frame_buffer_->Invalidate();
3730 if (offscreen_saved_color_texture_.get())
3731 offscreen_saved_color_texture_->Invalidate();
3732 if (offscreen_resolved_frame_buffer_.get())
3733 offscreen_resolved_frame_buffer_->Invalidate();
3734 if (offscreen_resolved_color_texture_.get())
3735 offscreen_resolved_color_texture_->Invalidate();
3738 // Current program must be cleared after calling ProgramManager::UnuseProgram.
3739 // Otherwise, we can leak objects. http://crbug.com/258772.
3740 // state_.current_program must be reset before group_ is reset because
3741 // the later deletes the ProgramManager object that referred by
3742 // state_.current_program object.
3743 state_.current_program = NULL;
3745 copy_texture_CHROMIUM_.reset();
3746 clear_framebuffer_blit_.reset();
3748 if (query_manager_.get()) {
3749 query_manager_->Destroy(have_context);
3750 query_manager_.reset();
3753 if (vertex_array_manager_ .get()) {
3754 vertex_array_manager_->Destroy(have_context);
3755 vertex_array_manager_.reset();
3758 if (image_manager_.get()) {
3759 image_manager_->Destroy(have_context);
3760 image_manager_.reset();
3763 offscreen_target_frame_buffer_.reset();
3764 offscreen_target_color_texture_.reset();
3765 offscreen_target_color_render_buffer_.reset();
3766 offscreen_target_depth_render_buffer_.reset();
3767 offscreen_target_stencil_render_buffer_.reset();
3768 offscreen_saved_frame_buffer_.reset();
3769 offscreen_saved_color_texture_.reset();
3770 offscreen_resolved_frame_buffer_.reset();
3771 offscreen_resolved_color_texture_.reset();
3773 // Need to release these before releasing |group_| which may own the
3774 // ShaderTranslatorCache.
3775 fragment_translator_ = NULL;
3776 vertex_translator_ = NULL;
3778 // Should destroy the transfer manager before the texture manager held
3779 // by the context group.
3780 async_pixel_transfer_manager_.reset();
3782 // Destroy the GPU Tracer which may own some in process GPU Timings.
3783 if (gpu_tracer_) {
3784 gpu_tracer_->Destroy(have_context);
3785 gpu_tracer_.reset();
3788 if (group_.get()) {
3789 framebuffer_manager()->RemoveObserver(this);
3790 group_->Destroy(this, have_context);
3791 group_ = NULL;
3794 if (context_.get()) {
3795 context_->ReleaseCurrent(NULL);
3796 context_ = NULL;
3799 #if defined(OS_MACOSX)
3800 for (TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.begin();
3801 it != texture_to_io_surface_map_.end(); ++it) {
3802 CFRelease(it->second);
3804 texture_to_io_surface_map_.clear();
3805 #endif
3808 void GLES2DecoderImpl::SetSurface(
3809 const scoped_refptr<gfx::GLSurface>& surface) {
3810 DCHECK(context_->IsCurrent(NULL));
3811 DCHECK(surface_.get());
3812 surface_ = surface;
3813 RestoreCurrentFramebufferBindings();
3816 void GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox& mailbox) {
3817 if (!offscreen_saved_color_texture_.get()) {
3818 LOG(ERROR) << "Called ProduceFrontBuffer on a non-offscreen context";
3819 return;
3821 if (!offscreen_saved_color_texture_info_.get()) {
3822 GLuint service_id = offscreen_saved_color_texture_->id();
3823 offscreen_saved_color_texture_info_ = TextureRef::Create(
3824 texture_manager(), 0, service_id);
3825 texture_manager()->SetTarget(offscreen_saved_color_texture_info_.get(),
3826 GL_TEXTURE_2D);
3827 UpdateParentTextureInfo();
3829 mailbox_manager()->ProduceTexture(
3830 mailbox, offscreen_saved_color_texture_info_->texture());
3833 bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
3834 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
3835 if (!is_offscreen) {
3836 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
3837 << " with an onscreen framebuffer.";
3838 return false;
3841 if (offscreen_size_ == size)
3842 return true;
3844 offscreen_size_ = size;
3845 int w = offscreen_size_.width();
3846 int h = offscreen_size_.height();
3847 if (w < 0 || h < 0 || h >= (INT_MAX / 4) / (w ? w : 1)) {
3848 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3849 << "to allocate storage due to excessive dimensions.";
3850 return false;
3853 // Reallocate the offscreen target buffers.
3854 DCHECK(offscreen_target_color_format_);
3855 if (IsOffscreenBufferMultisampled()) {
3856 if (!offscreen_target_color_render_buffer_->AllocateStorage(
3857 feature_info_.get(),
3858 offscreen_size_,
3859 offscreen_target_color_format_,
3860 offscreen_target_samples_)) {
3861 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3862 << "to allocate storage for offscreen target color buffer.";
3863 return false;
3865 } else {
3866 if (!offscreen_target_color_texture_->AllocateStorage(
3867 offscreen_size_, offscreen_target_color_format_, false)) {
3868 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3869 << "to allocate storage for offscreen target color texture.";
3870 return false;
3873 if (offscreen_target_depth_format_ &&
3874 !offscreen_target_depth_render_buffer_->AllocateStorage(
3875 feature_info_.get(),
3876 offscreen_size_,
3877 offscreen_target_depth_format_,
3878 offscreen_target_samples_)) {
3879 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3880 << "to allocate storage for offscreen target depth buffer.";
3881 return false;
3883 if (offscreen_target_stencil_format_ &&
3884 !offscreen_target_stencil_render_buffer_->AllocateStorage(
3885 feature_info_.get(),
3886 offscreen_size_,
3887 offscreen_target_stencil_format_,
3888 offscreen_target_samples_)) {
3889 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3890 << "to allocate storage for offscreen target stencil buffer.";
3891 return false;
3894 // Attach the offscreen target buffers to the target frame buffer.
3895 if (IsOffscreenBufferMultisampled()) {
3896 offscreen_target_frame_buffer_->AttachRenderBuffer(
3897 GL_COLOR_ATTACHMENT0,
3898 offscreen_target_color_render_buffer_.get());
3899 } else {
3900 offscreen_target_frame_buffer_->AttachRenderTexture(
3901 offscreen_target_color_texture_.get());
3903 if (offscreen_target_depth_format_) {
3904 offscreen_target_frame_buffer_->AttachRenderBuffer(
3905 GL_DEPTH_ATTACHMENT,
3906 offscreen_target_depth_render_buffer_.get());
3908 const bool packed_depth_stencil =
3909 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
3910 if (packed_depth_stencil) {
3911 offscreen_target_frame_buffer_->AttachRenderBuffer(
3912 GL_STENCIL_ATTACHMENT,
3913 offscreen_target_depth_render_buffer_.get());
3914 } else if (offscreen_target_stencil_format_) {
3915 offscreen_target_frame_buffer_->AttachRenderBuffer(
3916 GL_STENCIL_ATTACHMENT,
3917 offscreen_target_stencil_render_buffer_.get());
3920 if (offscreen_target_frame_buffer_->CheckStatus() !=
3921 GL_FRAMEBUFFER_COMPLETE) {
3922 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3923 << "because offscreen FBO was incomplete.";
3924 return false;
3927 // Clear the target frame buffer.
3929 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
3930 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3931 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1.f);
3932 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3933 glClearStencil(0);
3934 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
3935 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
3936 glClearDepth(0);
3937 state_.SetDeviceDepthMask(GL_TRUE);
3938 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
3939 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3940 RestoreClearState();
3943 // Destroy the offscreen resolved framebuffers.
3944 if (offscreen_resolved_frame_buffer_.get())
3945 offscreen_resolved_frame_buffer_->Destroy();
3946 if (offscreen_resolved_color_texture_.get())
3947 offscreen_resolved_color_texture_->Destroy();
3948 offscreen_resolved_color_texture_.reset();
3949 offscreen_resolved_frame_buffer_.reset();
3951 return true;
3954 error::Error GLES2DecoderImpl::HandleResizeCHROMIUM(uint32 immediate_data_size,
3955 const void* cmd_data) {
3956 const gles2::cmds::ResizeCHROMIUM& c =
3957 *static_cast<const gles2::cmds::ResizeCHROMIUM*>(cmd_data);
3958 if (!offscreen_target_frame_buffer_.get() && surface_->DeferDraws())
3959 return error::kDeferCommandUntilLater;
3961 GLuint width = static_cast<GLuint>(c.width);
3962 GLuint height = static_cast<GLuint>(c.height);
3963 GLfloat scale_factor = c.scale_factor;
3964 TRACE_EVENT2("gpu", "glResizeChromium", "width", width, "height", height);
3966 width = std::max(1U, width);
3967 height = std::max(1U, height);
3969 #if defined(OS_POSIX) && !defined(OS_MACOSX) && \
3970 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
3971 // Make sure that we are done drawing to the back buffer before resizing.
3972 glFinish();
3973 #endif
3974 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
3975 if (is_offscreen) {
3976 if (!ResizeOffscreenFrameBuffer(gfx::Size(width, height))) {
3977 LOG(ERROR) << "GLES2DecoderImpl: Context lost because "
3978 << "ResizeOffscreenFrameBuffer failed.";
3979 return error::kLostContext;
3983 if (!resize_callback_.is_null()) {
3984 resize_callback_.Run(gfx::Size(width, height), scale_factor);
3985 DCHECK(context_->IsCurrent(surface_.get()));
3986 if (!context_->IsCurrent(surface_.get())) {
3987 LOG(ERROR) << "GLES2DecoderImpl: Context lost because context no longer "
3988 << "current after resize callback.";
3989 return error::kLostContext;
3993 return error::kNoError;
3996 const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
3997 if (command_id > kStartPoint && command_id < kNumCommands) {
3998 return gles2::GetCommandName(static_cast<CommandId>(command_id));
4000 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
4003 // Decode a command, and call the corresponding GL functions.
4004 // NOTE: DoCommand() is slower than calling DoCommands() on larger batches
4005 // of commands at once, and is now only used for tests that need to track
4006 // individual commands.
4007 error::Error GLES2DecoderImpl::DoCommand(unsigned int command,
4008 unsigned int arg_count,
4009 const void* cmd_data) {
4010 return DoCommands(1, cmd_data, arg_count + 1, 0);
4013 // Decode multiple commands, and call the corresponding GL functions.
4014 // NOTE: 'buffer' is a pointer to the command buffer. As such, it could be
4015 // changed by a (malicious) client at any time, so if validation has to happen,
4016 // it should operate on a copy of them.
4017 // NOTE: This is duplicating code from AsyncAPIInterface::DoCommands() in the
4018 // interest of performance in this critical execution loop.
4019 template <bool DebugImpl>
4020 error::Error GLES2DecoderImpl::DoCommandsImpl(unsigned int num_commands,
4021 const void* buffer,
4022 int num_entries,
4023 int* entries_processed) {
4024 commands_to_process_ = num_commands;
4025 error::Error result = error::kNoError;
4026 const CommandBufferEntry* cmd_data =
4027 static_cast<const CommandBufferEntry*>(buffer);
4028 int process_pos = 0;
4029 unsigned int command = 0;
4031 while (process_pos < num_entries && result == error::kNoError &&
4032 commands_to_process_--) {
4033 const unsigned int size = cmd_data->value_header.size;
4034 command = cmd_data->value_header.command;
4036 if (size == 0) {
4037 result = error::kInvalidSize;
4038 break;
4041 if (static_cast<int>(size) + process_pos > num_entries) {
4042 result = error::kOutOfBounds;
4043 break;
4046 if (DebugImpl) {
4047 TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
4048 GetCommandName(command));
4050 if (log_commands()) {
4051 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "]"
4052 << "cmd: " << GetCommandName(command);
4056 const unsigned int arg_count = size - 1;
4057 unsigned int command_index = command - kStartPoint - 1;
4058 if (command_index < arraysize(command_info)) {
4059 const CommandInfo& info = command_info[command_index];
4060 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
4061 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
4062 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
4063 bool doing_gpu_trace = false;
4064 if (DebugImpl && gpu_trace_commands_) {
4065 if (CMD_FLAG_GET_TRACE_LEVEL(info.cmd_flags) <= gpu_trace_level_) {
4066 doing_gpu_trace = true;
4067 gpu_tracer_->Begin(TRACE_DISABLED_BY_DEFAULT("gpu_decoder"),
4068 GetCommandName(command),
4069 kTraceDecoder);
4073 uint32 immediate_data_size = (arg_count - info_arg_count) *
4074 sizeof(CommandBufferEntry); // NOLINT
4076 result = (this->*info.cmd_handler)(immediate_data_size, cmd_data);
4078 if (DebugImpl && doing_gpu_trace)
4079 gpu_tracer_->End(kTraceDecoder);
4081 if (DebugImpl && debug()) {
4082 GLenum error;
4083 while ((error = glGetError()) != GL_NO_ERROR) {
4084 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "] "
4085 << "GL ERROR: " << GLES2Util::GetStringEnum(error)
4086 << " : " << GetCommandName(command);
4087 LOCAL_SET_GL_ERROR(error, "DoCommand", "GL error from driver");
4090 } else {
4091 result = error::kInvalidArguments;
4093 } else {
4094 result = DoCommonCommand(command, arg_count, cmd_data);
4097 if (DebugImpl) {
4098 TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
4099 GetCommandName(command));
4102 if (result == error::kNoError &&
4103 current_decoder_error_ != error::kNoError) {
4104 result = current_decoder_error_;
4105 current_decoder_error_ = error::kNoError;
4108 if (result != error::kDeferCommandUntilLater) {
4109 process_pos += size;
4110 cmd_data += size;
4114 if (entries_processed)
4115 *entries_processed = process_pos;
4117 if (error::IsError(result)) {
4118 LOG(ERROR) << "Error: " << result << " for Command "
4119 << GetCommandName(command);
4122 return result;
4125 error::Error GLES2DecoderImpl::DoCommands(unsigned int num_commands,
4126 const void* buffer,
4127 int num_entries,
4128 int* entries_processed) {
4129 if (gpu_debug_commands_) {
4130 return DoCommandsImpl<true>(
4131 num_commands, buffer, num_entries, entries_processed);
4132 } else {
4133 return DoCommandsImpl<false>(
4134 num_commands, buffer, num_entries, entries_processed);
4138 void GLES2DecoderImpl::RemoveBuffer(GLuint client_id) {
4139 buffer_manager()->RemoveBuffer(client_id);
4142 void GLES2DecoderImpl::DoFinish() {
4143 glFinish();
4144 ProcessPendingReadPixels();
4145 ProcessPendingQueries(true);
4148 void GLES2DecoderImpl::DoFlush() {
4149 glFlush();
4150 ProcessPendingQueries(false);
4153 void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
4154 GLuint texture_index = texture_unit - GL_TEXTURE0;
4155 if (texture_index >= state_.texture_units.size()) {
4156 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4157 "glActiveTexture", texture_unit, "texture_unit");
4158 return;
4160 state_.active_texture_unit = texture_index;
4161 glActiveTexture(texture_unit);
4164 void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
4165 Buffer* buffer = NULL;
4166 GLuint service_id = 0;
4167 if (client_id != 0) {
4168 buffer = GetBuffer(client_id);
4169 if (!buffer) {
4170 if (!group_->bind_generates_resource()) {
4171 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4172 "glBindBuffer",
4173 "id not generated by glGenBuffers");
4174 return;
4177 // It's a new id so make a buffer buffer for it.
4178 glGenBuffersARB(1, &service_id);
4179 CreateBuffer(client_id, service_id);
4180 buffer = GetBuffer(client_id);
4183 LogClientServiceForInfo(buffer, client_id, "glBindBuffer");
4184 if (buffer) {
4185 if (!buffer_manager()->SetTarget(buffer, target)) {
4186 LOCAL_SET_GL_ERROR(
4187 GL_INVALID_OPERATION,
4188 "glBindBuffer", "buffer bound to more than 1 target");
4189 return;
4191 service_id = buffer->service_id();
4193 switch (target) {
4194 case GL_ARRAY_BUFFER:
4195 state_.bound_array_buffer = buffer;
4196 break;
4197 case GL_ELEMENT_ARRAY_BUFFER:
4198 state_.vertex_attrib_manager->SetElementArrayBuffer(buffer);
4199 break;
4200 default:
4201 NOTREACHED(); // Validation should prevent us getting here.
4202 break;
4204 glBindBuffer(target, service_id);
4207 bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha(
4208 bool all_draw_buffers) {
4209 Framebuffer* framebuffer =
4210 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4211 if (!all_draw_buffers || !framebuffer) {
4212 return (GLES2Util::GetChannelsForFormat(
4213 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
4215 return framebuffer->HasAlphaMRT();
4218 bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
4219 Framebuffer* framebuffer =
4220 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4221 if (framebuffer) {
4222 return framebuffer->HasDepthAttachment();
4224 if (offscreen_target_frame_buffer_.get()) {
4225 return offscreen_target_depth_format_ != 0;
4227 return back_buffer_has_depth_;
4230 bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
4231 Framebuffer* framebuffer =
4232 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4233 if (framebuffer) {
4234 return framebuffer->HasStencilAttachment();
4236 if (offscreen_target_frame_buffer_.get()) {
4237 return offscreen_target_stencil_format_ != 0 ||
4238 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
4240 return back_buffer_has_stencil_;
4243 void GLES2DecoderImpl::ApplyDirtyState() {
4244 if (framebuffer_state_.clear_state_dirty) {
4245 bool have_alpha = BoundFramebufferHasColorAttachmentWithAlpha(true);
4246 state_.SetDeviceColorMask(state_.color_mask_red,
4247 state_.color_mask_green,
4248 state_.color_mask_blue,
4249 state_.color_mask_alpha && have_alpha);
4251 bool have_depth = BoundFramebufferHasDepthAttachment();
4252 state_.SetDeviceDepthMask(state_.depth_mask && have_depth);
4254 bool have_stencil = BoundFramebufferHasStencilAttachment();
4255 state_.SetDeviceStencilMaskSeparate(
4256 GL_FRONT, have_stencil ? state_.stencil_front_writemask : 0);
4257 state_.SetDeviceStencilMaskSeparate(
4258 GL_BACK, have_stencil ? state_.stencil_back_writemask : 0);
4260 state_.SetDeviceCapabilityState(
4261 GL_DEPTH_TEST, state_.enable_flags.depth_test && have_depth);
4262 state_.SetDeviceCapabilityState(
4263 GL_STENCIL_TEST, state_.enable_flags.stencil_test && have_stencil);
4264 framebuffer_state_.clear_state_dirty = false;
4268 GLuint GLES2DecoderImpl::GetBackbufferServiceId() const {
4269 return (offscreen_target_frame_buffer_.get())
4270 ? offscreen_target_frame_buffer_->id()
4271 : (surface_.get() ? surface_->GetBackingFrameBufferObject() : 0);
4274 void GLES2DecoderImpl::RestoreState(const ContextState* prev_state) {
4275 TRACE_EVENT1("gpu", "GLES2DecoderImpl::RestoreState",
4276 "context", logger_.GetLogPrefix());
4277 // Restore the Framebuffer first because of bugs in Intel drivers.
4278 // Intel drivers incorrectly clip the viewport settings to
4279 // the size of the current framebuffer object.
4280 RestoreFramebufferBindings();
4281 state_.RestoreState(prev_state);
4284 void GLES2DecoderImpl::RestoreFramebufferBindings() const {
4285 GLuint service_id =
4286 framebuffer_state_.bound_draw_framebuffer.get()
4287 ? framebuffer_state_.bound_draw_framebuffer->service_id()
4288 : GetBackbufferServiceId();
4289 if (!features().chromium_framebuffer_multisample) {
4290 glBindFramebufferEXT(GL_FRAMEBUFFER, service_id);
4291 } else {
4292 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, service_id);
4293 service_id = framebuffer_state_.bound_read_framebuffer.get()
4294 ? framebuffer_state_.bound_read_framebuffer->service_id()
4295 : GetBackbufferServiceId();
4296 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, service_id);
4298 OnFboChanged();
4301 void GLES2DecoderImpl::RestoreRenderbufferBindings() {
4302 state_.RestoreRenderbufferBindings();
4305 void GLES2DecoderImpl::RestoreTextureState(unsigned service_id) const {
4306 Texture* texture = texture_manager()->GetTextureForServiceId(service_id);
4307 if (texture) {
4308 GLenum target = texture->target();
4309 glBindTexture(target, service_id);
4310 glTexParameteri(
4311 target, GL_TEXTURE_WRAP_S, texture->wrap_s());
4312 glTexParameteri(
4313 target, GL_TEXTURE_WRAP_T, texture->wrap_t());
4314 glTexParameteri(
4315 target, GL_TEXTURE_MIN_FILTER, texture->min_filter());
4316 glTexParameteri(
4317 target, GL_TEXTURE_MAG_FILTER, texture->mag_filter());
4318 RestoreTextureUnitBindings(state_.active_texture_unit);
4322 void GLES2DecoderImpl::ClearAllAttributes() const {
4323 // Must use native VAO 0, as RestoreAllAttributes can't fully restore
4324 // other VAOs.
4325 if (feature_info_->feature_flags().native_vertex_array_object)
4326 glBindVertexArrayOES(0);
4328 for (uint32 i = 0; i < group_->max_vertex_attribs(); ++i) {
4329 if (i != 0) // Never disable attribute 0
4330 glDisableVertexAttribArray(i);
4331 if (features().angle_instanced_arrays)
4332 glVertexAttribDivisorANGLE(i, 0);
4336 void GLES2DecoderImpl::RestoreAllAttributes() const {
4337 state_.RestoreVertexAttribs();
4340 void GLES2DecoderImpl::SetIgnoreCachedStateForTest(bool ignore) {
4341 state_.SetIgnoreCachedStateForTest(ignore);
4344 void GLES2DecoderImpl::OnFboChanged() const {
4345 if (workarounds().restore_scissor_on_fbo_change)
4346 state_.fbo_binding_for_scissor_workaround_dirty_ = true;
4348 if (workarounds().gl_begin_gl_end_on_fbo_change_to_backbuffer) {
4349 GLint bound_fbo_unsigned = -1;
4350 glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &bound_fbo_unsigned);
4351 GLuint bound_fbo = static_cast<GLuint>(bound_fbo_unsigned);
4352 if (surface_ && surface_->GetBackingFrameBufferObject() == bound_fbo)
4353 surface_->NotifyWasBound();
4357 // Called after the FBO is checked for completeness.
4358 void GLES2DecoderImpl::OnUseFramebuffer() const {
4359 if (state_.fbo_binding_for_scissor_workaround_dirty_) {
4360 state_.fbo_binding_for_scissor_workaround_dirty_ = false;
4361 // The driver forgets the correct scissor when modifying the FBO binding.
4362 glScissor(state_.scissor_x,
4363 state_.scissor_y,
4364 state_.scissor_width,
4365 state_.scissor_height);
4367 // crbug.com/222018 - Also on QualComm, the flush here avoids flicker,
4368 // it's unclear how this bug works.
4369 glFlush();
4373 void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
4374 Framebuffer* framebuffer = NULL;
4375 GLuint service_id = 0;
4376 if (client_id != 0) {
4377 framebuffer = GetFramebuffer(client_id);
4378 if (!framebuffer) {
4379 if (!group_->bind_generates_resource()) {
4380 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4381 "glBindFramebuffer",
4382 "id not generated by glGenFramebuffers");
4383 return;
4386 // It's a new id so make a framebuffer framebuffer for it.
4387 glGenFramebuffersEXT(1, &service_id);
4388 CreateFramebuffer(client_id, service_id);
4389 framebuffer = GetFramebuffer(client_id);
4390 } else {
4391 service_id = framebuffer->service_id();
4393 framebuffer->MarkAsValid();
4395 LogClientServiceForInfo(framebuffer, client_id, "glBindFramebuffer");
4397 if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) {
4398 framebuffer_state_.bound_draw_framebuffer = framebuffer;
4401 // vmiura: This looks like dup code
4402 if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) {
4403 framebuffer_state_.bound_read_framebuffer = framebuffer;
4406 framebuffer_state_.clear_state_dirty = true;
4408 // If we are rendering to the backbuffer get the FBO id for any simulated
4409 // backbuffer.
4410 if (framebuffer == NULL) {
4411 service_id = GetBackbufferServiceId();
4414 glBindFramebufferEXT(target, service_id);
4415 OnFboChanged();
4418 void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
4419 Renderbuffer* renderbuffer = NULL;
4420 GLuint service_id = 0;
4421 if (client_id != 0) {
4422 renderbuffer = GetRenderbuffer(client_id);
4423 if (!renderbuffer) {
4424 if (!group_->bind_generates_resource()) {
4425 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4426 "glBindRenderbuffer",
4427 "id not generated by glGenRenderbuffers");
4428 return;
4431 // It's a new id so make a renderbuffer for it.
4432 glGenRenderbuffersEXT(1, &service_id);
4433 CreateRenderbuffer(client_id, service_id);
4434 renderbuffer = GetRenderbuffer(client_id);
4435 } else {
4436 service_id = renderbuffer->service_id();
4438 renderbuffer->MarkAsValid();
4440 LogClientServiceForInfo(renderbuffer, client_id, "glBindRenderbuffer");
4441 state_.bound_renderbuffer = renderbuffer;
4442 state_.bound_renderbuffer_valid = true;
4443 glBindRenderbufferEXT(GL_RENDERBUFFER, service_id);
4446 void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
4447 TextureRef* texture_ref = NULL;
4448 GLuint service_id = 0;
4449 if (client_id != 0) {
4450 texture_ref = GetTexture(client_id);
4451 if (!texture_ref) {
4452 if (!group_->bind_generates_resource()) {
4453 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4454 "glBindTexture",
4455 "id not generated by glGenTextures");
4456 return;
4459 // It's a new id so make a texture texture for it.
4460 glGenTextures(1, &service_id);
4461 DCHECK_NE(0u, service_id);
4462 CreateTexture(client_id, service_id);
4463 texture_ref = GetTexture(client_id);
4465 } else {
4466 texture_ref = texture_manager()->GetDefaultTextureInfo(target);
4469 // Check the texture exists
4470 if (texture_ref) {
4471 Texture* texture = texture_ref->texture();
4472 // Check that we are not trying to bind it to a different target.
4473 if (texture->target() != 0 && texture->target() != target) {
4474 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4475 "glBindTexture",
4476 "texture bound to more than 1 target.");
4477 return;
4479 LogClientServiceForInfo(texture, client_id, "glBindTexture");
4480 if (texture->target() == 0) {
4481 texture_manager()->SetTarget(texture_ref, target);
4483 glBindTexture(target, texture->service_id());
4484 } else {
4485 glBindTexture(target, 0);
4488 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4489 unit.bind_target = target;
4490 switch (target) {
4491 case GL_TEXTURE_2D:
4492 unit.bound_texture_2d = texture_ref;
4493 break;
4494 case GL_TEXTURE_CUBE_MAP:
4495 unit.bound_texture_cube_map = texture_ref;
4496 break;
4497 case GL_TEXTURE_EXTERNAL_OES:
4498 unit.bound_texture_external_oes = texture_ref;
4499 break;
4500 case GL_TEXTURE_RECTANGLE_ARB:
4501 unit.bound_texture_rectangle_arb = texture_ref;
4502 break;
4503 default:
4504 NOTREACHED(); // Validation should prevent us getting here.
4505 break;
4509 void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
4510 if (state_.vertex_attrib_manager->Enable(index, false)) {
4511 if (index != 0 ||
4512 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
4513 glDisableVertexAttribArray(index);
4515 } else {
4516 LOCAL_SET_GL_ERROR(
4517 GL_INVALID_VALUE,
4518 "glDisableVertexAttribArray", "index out of range");
4522 void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target,
4523 GLsizei numAttachments,
4524 const GLenum* attachments) {
4525 if (workarounds().disable_discard_framebuffer)
4526 return;
4528 Framebuffer* framebuffer =
4529 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4531 // Validates the attachments. If one of them fails
4532 // the whole command fails.
4533 for (GLsizei i = 0; i < numAttachments; ++i) {
4534 if ((framebuffer &&
4535 !validators_->attachment.IsValid(attachments[i])) ||
4536 (!framebuffer &&
4537 !validators_->backbuffer_attachment.IsValid(attachments[i]))) {
4538 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4539 "glDiscardFramebufferEXT", attachments[i], "attachments");
4540 return;
4544 // Marks each one of them as not cleared
4545 for (GLsizei i = 0; i < numAttachments; ++i) {
4546 if (framebuffer) {
4547 framebuffer->MarkAttachmentAsCleared(renderbuffer_manager(),
4548 texture_manager(),
4549 attachments[i],
4550 false);
4551 } else {
4552 switch (attachments[i]) {
4553 case GL_COLOR_EXT:
4554 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
4555 break;
4556 case GL_DEPTH_EXT:
4557 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
4558 case GL_STENCIL_EXT:
4559 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
4560 break;
4561 default:
4562 NOTREACHED();
4563 break;
4568 // If the default framebuffer is bound but we are still rendering to an
4569 // FBO, translate attachment names that refer to default framebuffer
4570 // channels to corresponding framebuffer attachments.
4571 scoped_ptr<GLenum[]> translated_attachments(new GLenum[numAttachments]);
4572 for (GLsizei i = 0; i < numAttachments; ++i) {
4573 GLenum attachment = attachments[i];
4574 if (!framebuffer && GetBackbufferServiceId()) {
4575 switch (attachment) {
4576 case GL_COLOR_EXT:
4577 attachment = GL_COLOR_ATTACHMENT0;
4578 break;
4579 case GL_DEPTH_EXT:
4580 attachment = GL_DEPTH_ATTACHMENT;
4581 break;
4582 case GL_STENCIL_EXT:
4583 attachment = GL_STENCIL_ATTACHMENT;
4584 break;
4585 default:
4586 NOTREACHED();
4587 return;
4590 translated_attachments[i] = attachment;
4593 ScopedRenderTo do_render(framebuffer);
4594 if (feature_info_->gl_version_info().is_es3) {
4595 glInvalidateFramebuffer(
4596 target, numAttachments, translated_attachments.get());
4597 } else {
4598 glDiscardFramebufferEXT(
4599 target, numAttachments, translated_attachments.get());
4603 void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
4604 if (state_.vertex_attrib_manager->Enable(index, true)) {
4605 glEnableVertexAttribArray(index);
4606 } else {
4607 LOCAL_SET_GL_ERROR(
4608 GL_INVALID_VALUE, "glEnableVertexAttribArray", "index out of range");
4612 void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
4613 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
4614 &state_, target);
4615 if (!texture_ref ||
4616 !texture_manager()->CanGenerateMipmaps(texture_ref)) {
4617 LOCAL_SET_GL_ERROR(
4618 GL_INVALID_OPERATION, "glGenerateMipmap", "Can not generate mips");
4619 return;
4622 if (target == GL_TEXTURE_CUBE_MAP) {
4623 for (int i = 0; i < 6; ++i) {
4624 GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;
4625 if (!texture_manager()->ClearTextureLevel(this, texture_ref, face, 0)) {
4626 LOCAL_SET_GL_ERROR(
4627 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
4628 return;
4631 } else {
4632 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, 0)) {
4633 LOCAL_SET_GL_ERROR(
4634 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
4635 return;
4639 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glGenerateMipmap");
4640 // Workaround for Mac driver bug. In the large scheme of things setting
4641 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
4642 // hit so there's probably no need to make this conditional. The bug appears
4643 // to be that if the filtering mode is set to something that doesn't require
4644 // mipmaps for rendering, or is never set to something other than the default,
4645 // then glGenerateMipmap misbehaves.
4646 if (workarounds().set_texture_filter_before_generating_mipmap) {
4647 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
4649 glGenerateMipmapEXT(target);
4650 if (workarounds().set_texture_filter_before_generating_mipmap) {
4651 glTexParameteri(target, GL_TEXTURE_MIN_FILTER,
4652 texture_ref->texture()->min_filter());
4654 GLenum error = LOCAL_PEEK_GL_ERROR("glGenerateMipmap");
4655 if (error == GL_NO_ERROR) {
4656 texture_manager()->MarkMipmapsGenerated(texture_ref);
4660 bool GLES2DecoderImpl::GetHelper(
4661 GLenum pname, GLint* params, GLsizei* num_written) {
4662 DCHECK(num_written);
4663 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
4664 switch (pname) {
4665 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
4666 *num_written = 1;
4667 // Return the GL implementation's preferred format and (see below type)
4668 // if we have the GL extension that exposes this. This allows the GPU
4669 // client to use the implementation's preferred format for glReadPixels
4670 // for optimisation.
4672 // A conflicting extension (GL_ARB_ES2_compatibility) specifies an error
4673 // case when requested on integer/floating point buffers but which is
4674 // acceptable on GLES2 and with the GL_OES_read_format extension.
4676 // Therefore if an error occurs we swallow the error and use the
4677 // internal implementation.
4678 if (params) {
4679 if (context_->HasExtension("GL_OES_read_format")) {
4680 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper",
4681 GetErrorState());
4682 glGetIntegerv(pname, params);
4683 if (glGetError() == GL_NO_ERROR)
4684 return true;
4686 *params = GLES2Util::GetPreferredGLReadPixelsFormat(
4687 GetBoundReadFrameBufferInternalFormat());
4689 return true;
4690 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
4691 *num_written = 1;
4692 if (params) {
4693 if (context_->HasExtension("GL_OES_read_format")) {
4694 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper",
4695 GetErrorState());
4696 glGetIntegerv(pname, params);
4697 if (glGetError() == GL_NO_ERROR)
4698 return true;
4700 *params = GLES2Util::GetPreferredGLReadPixelsType(
4701 GetBoundReadFrameBufferInternalFormat(),
4702 GetBoundReadFrameBufferTextureType());
4704 return true;
4705 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
4706 *num_written = 1;
4707 if (params) {
4708 *params = group_->max_fragment_uniform_vectors();
4710 return true;
4711 case GL_MAX_VARYING_VECTORS:
4712 *num_written = 1;
4713 if (params) {
4714 *params = group_->max_varying_vectors();
4716 return true;
4717 case GL_MAX_VERTEX_UNIFORM_VECTORS:
4718 *num_written = 1;
4719 if (params) {
4720 *params = group_->max_vertex_uniform_vectors();
4722 return true;
4725 switch (pname) {
4726 case GL_MAX_VIEWPORT_DIMS:
4727 if (offscreen_target_frame_buffer_.get()) {
4728 *num_written = 2;
4729 if (params) {
4730 params[0] = renderbuffer_manager()->max_renderbuffer_size();
4731 params[1] = renderbuffer_manager()->max_renderbuffer_size();
4733 return true;
4735 return false;
4736 case GL_MAX_SAMPLES:
4737 *num_written = 1;
4738 if (params) {
4739 params[0] = renderbuffer_manager()->max_samples();
4741 return true;
4742 case GL_MAX_RENDERBUFFER_SIZE:
4743 *num_written = 1;
4744 if (params) {
4745 params[0] = renderbuffer_manager()->max_renderbuffer_size();
4747 return true;
4748 case GL_MAX_TEXTURE_SIZE:
4749 *num_written = 1;
4750 if (params) {
4751 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D);
4753 return true;
4754 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
4755 *num_written = 1;
4756 if (params) {
4757 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP);
4759 return true;
4760 case GL_MAX_COLOR_ATTACHMENTS_EXT:
4761 *num_written = 1;
4762 if (params) {
4763 params[0] = group_->max_color_attachments();
4765 return true;
4766 case GL_MAX_DRAW_BUFFERS_ARB:
4767 *num_written = 1;
4768 if (params) {
4769 params[0] = group_->max_draw_buffers();
4771 return true;
4772 case GL_ALPHA_BITS:
4773 *num_written = 1;
4774 if (params) {
4775 GLint v = 0;
4776 if (feature_info_->gl_version_info().is_desktop_core_profile) {
4777 Framebuffer* framebuffer =
4778 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4779 if (framebuffer) {
4780 glGetFramebufferAttachmentParameterivEXT(
4781 GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
4782 GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE, &v);
4783 } else {
4784 v = (back_buffer_color_format_ == GL_RGBA ? 8 : 0);
4786 } else {
4787 glGetIntegerv(GL_ALPHA_BITS, &v);
4789 params[0] =
4790 BoundFramebufferHasColorAttachmentWithAlpha(false) ? v : 0;
4792 return true;
4793 case GL_DEPTH_BITS:
4794 *num_written = 1;
4795 if (params) {
4796 GLint v = 0;
4797 if (feature_info_->gl_version_info().is_desktop_core_profile) {
4798 Framebuffer* framebuffer =
4799 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4800 if (framebuffer) {
4801 glGetFramebufferAttachmentParameterivEXT(
4802 GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
4803 GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE, &v);
4804 } else {
4805 v = (back_buffer_has_depth_ ? 24 : 0);
4807 } else {
4808 glGetIntegerv(GL_DEPTH_BITS, &v);
4810 params[0] = BoundFramebufferHasDepthAttachment() ? v : 0;
4812 return true;
4813 case GL_RED_BITS:
4814 case GL_GREEN_BITS:
4815 case GL_BLUE_BITS:
4816 *num_written = 1;
4817 if (params) {
4818 GLint v = 0;
4819 if (feature_info_->gl_version_info().is_desktop_core_profile) {
4820 Framebuffer* framebuffer =
4821 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4822 if (framebuffer) {
4823 GLenum framebuffer_enum = 0;
4824 switch (pname) {
4825 case GL_RED_BITS:
4826 framebuffer_enum = GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE;
4827 break;
4828 case GL_GREEN_BITS:
4829 framebuffer_enum = GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE;
4830 break;
4831 case GL_BLUE_BITS:
4832 framebuffer_enum = GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE;
4833 break;
4835 glGetFramebufferAttachmentParameterivEXT(
4836 GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, framebuffer_enum, &v);
4837 } else {
4838 v = 8;
4840 } else {
4841 glGetIntegerv(pname, &v);
4843 params[0] = v;
4845 return true;
4846 case GL_STENCIL_BITS:
4847 *num_written = 1;
4848 if (params) {
4849 GLint v = 0;
4850 if (feature_info_->gl_version_info().is_desktop_core_profile) {
4851 Framebuffer* framebuffer =
4852 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4853 if (framebuffer) {
4854 glGetFramebufferAttachmentParameterivEXT(
4855 GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
4856 GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE, &v);
4857 } else {
4858 v = (back_buffer_has_stencil_ ? 8 : 0);
4860 } else {
4861 glGetIntegerv(GL_STENCIL_BITS, &v);
4863 params[0] = BoundFramebufferHasStencilAttachment() ? v : 0;
4865 return true;
4866 case GL_COMPRESSED_TEXTURE_FORMATS:
4867 *num_written = validators_->compressed_texture_format.GetValues().size();
4868 if (params) {
4869 for (GLint ii = 0; ii < *num_written; ++ii) {
4870 params[ii] = validators_->compressed_texture_format.GetValues()[ii];
4873 return true;
4874 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
4875 *num_written = 1;
4876 if (params) {
4877 *params = validators_->compressed_texture_format.GetValues().size();
4879 return true;
4880 case GL_NUM_SHADER_BINARY_FORMATS:
4881 *num_written = 1;
4882 if (params) {
4883 *params = validators_->shader_binary_format.GetValues().size();
4885 return true;
4886 case GL_SHADER_BINARY_FORMATS:
4887 *num_written = validators_->shader_binary_format.GetValues().size();
4888 if (params) {
4889 for (GLint ii = 0; ii < *num_written; ++ii) {
4890 params[ii] = validators_->shader_binary_format.GetValues()[ii];
4893 return true;
4894 case GL_SHADER_COMPILER:
4895 *num_written = 1;
4896 if (params) {
4897 *params = GL_TRUE;
4899 return true;
4900 case GL_ARRAY_BUFFER_BINDING:
4901 *num_written = 1;
4902 if (params) {
4903 if (state_.bound_array_buffer.get()) {
4904 GLuint client_id = 0;
4905 buffer_manager()->GetClientId(state_.bound_array_buffer->service_id(),
4906 &client_id);
4907 *params = client_id;
4908 } else {
4909 *params = 0;
4912 return true;
4913 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
4914 *num_written = 1;
4915 if (params) {
4916 if (state_.vertex_attrib_manager->element_array_buffer()) {
4917 GLuint client_id = 0;
4918 buffer_manager()->GetClientId(
4919 state_.vertex_attrib_manager->element_array_buffer()->
4920 service_id(), &client_id);
4921 *params = client_id;
4922 } else {
4923 *params = 0;
4926 return true;
4927 case GL_FRAMEBUFFER_BINDING:
4928 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
4929 *num_written = 1;
4930 if (params) {
4931 Framebuffer* framebuffer =
4932 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4933 if (framebuffer) {
4934 GLuint client_id = 0;
4935 framebuffer_manager()->GetClientId(
4936 framebuffer->service_id(), &client_id);
4937 *params = client_id;
4938 } else {
4939 *params = 0;
4942 return true;
4943 case GL_READ_FRAMEBUFFER_BINDING_EXT:
4944 *num_written = 1;
4945 if (params) {
4946 Framebuffer* framebuffer =
4947 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
4948 if (framebuffer) {
4949 GLuint client_id = 0;
4950 framebuffer_manager()->GetClientId(
4951 framebuffer->service_id(), &client_id);
4952 *params = client_id;
4953 } else {
4954 *params = 0;
4957 return true;
4958 case GL_RENDERBUFFER_BINDING:
4959 *num_written = 1;
4960 if (params) {
4961 Renderbuffer* renderbuffer =
4962 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4963 if (renderbuffer) {
4964 *params = renderbuffer->client_id();
4965 } else {
4966 *params = 0;
4969 return true;
4970 case GL_CURRENT_PROGRAM:
4971 *num_written = 1;
4972 if (params) {
4973 if (state_.current_program.get()) {
4974 GLuint client_id = 0;
4975 program_manager()->GetClientId(
4976 state_.current_program->service_id(), &client_id);
4977 *params = client_id;
4978 } else {
4979 *params = 0;
4982 return true;
4983 case GL_VERTEX_ARRAY_BINDING_OES:
4984 *num_written = 1;
4985 if (params) {
4986 if (state_.vertex_attrib_manager.get() !=
4987 state_.default_vertex_attrib_manager.get()) {
4988 GLuint client_id = 0;
4989 vertex_array_manager_->GetClientId(
4990 state_.vertex_attrib_manager->service_id(), &client_id);
4991 *params = client_id;
4992 } else {
4993 *params = 0;
4996 return true;
4997 case GL_TEXTURE_BINDING_2D:
4998 *num_written = 1;
4999 if (params) {
5000 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
5001 if (unit.bound_texture_2d.get()) {
5002 *params = unit.bound_texture_2d->client_id();
5003 } else {
5004 *params = 0;
5007 return true;
5008 case GL_TEXTURE_BINDING_CUBE_MAP:
5009 *num_written = 1;
5010 if (params) {
5011 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
5012 if (unit.bound_texture_cube_map.get()) {
5013 *params = unit.bound_texture_cube_map->client_id();
5014 } else {
5015 *params = 0;
5018 return true;
5019 case GL_TEXTURE_BINDING_EXTERNAL_OES:
5020 *num_written = 1;
5021 if (params) {
5022 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
5023 if (unit.bound_texture_external_oes.get()) {
5024 *params = unit.bound_texture_external_oes->client_id();
5025 } else {
5026 *params = 0;
5029 return true;
5030 case GL_TEXTURE_BINDING_RECTANGLE_ARB:
5031 *num_written = 1;
5032 if (params) {
5033 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
5034 if (unit.bound_texture_rectangle_arb.get()) {
5035 *params = unit.bound_texture_rectangle_arb->client_id();
5036 } else {
5037 *params = 0;
5040 return true;
5041 case GL_UNPACK_FLIP_Y_CHROMIUM:
5042 *num_written = 1;
5043 if (params) {
5044 params[0] = unpack_flip_y_;
5046 return true;
5047 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
5048 *num_written = 1;
5049 if (params) {
5050 params[0] = unpack_premultiply_alpha_;
5052 return true;
5053 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM:
5054 *num_written = 1;
5055 if (params) {
5056 params[0] = unpack_unpremultiply_alpha_;
5058 return true;
5059 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
5060 *num_written = 1;
5061 if (params) {
5062 params[0] = group_->bind_generates_resource() ? 1 : 0;
5064 return true;
5065 default:
5066 if (pname >= GL_DRAW_BUFFER0_ARB &&
5067 pname < GL_DRAW_BUFFER0_ARB + group_->max_draw_buffers()) {
5068 *num_written = 1;
5069 if (params) {
5070 Framebuffer* framebuffer =
5071 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
5072 if (framebuffer) {
5073 params[0] = framebuffer->GetDrawBuffer(pname);
5074 } else { // backbuffer
5075 if (pname == GL_DRAW_BUFFER0_ARB)
5076 params[0] = group_->draw_buffer();
5077 else
5078 params[0] = GL_NONE;
5081 return true;
5083 *num_written = util_.GLGetNumValuesReturned(pname);
5084 return false;
5088 bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
5089 GLenum pname, GLsizei* num_values) {
5090 if (state_.GetStateAsGLint(pname, NULL, num_values)) {
5091 return true;
5093 return GetHelper(pname, NULL, num_values);
5096 GLenum GLES2DecoderImpl::AdjustGetPname(GLenum pname) {
5097 if (GL_MAX_SAMPLES == pname &&
5098 features().use_img_for_multisampled_render_to_texture) {
5099 return GL_MAX_SAMPLES_IMG;
5101 return pname;
5104 void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
5105 DCHECK(params);
5106 GLsizei num_written = 0;
5107 if (GetNumValuesReturnedForGLGet(pname, &num_written)) {
5108 scoped_ptr<GLint[]> values(new GLint[num_written]);
5109 if (!state_.GetStateAsGLint(pname, values.get(), &num_written)) {
5110 GetHelper(pname, values.get(), &num_written);
5112 for (GLsizei ii = 0; ii < num_written; ++ii) {
5113 params[ii] = static_cast<GLboolean>(values[ii]);
5115 } else {
5116 pname = AdjustGetPname(pname);
5117 glGetBooleanv(pname, params);
5121 void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
5122 DCHECK(params);
5123 GLsizei num_written = 0;
5124 if (!state_.GetStateAsGLfloat(pname, params, &num_written)) {
5125 if (GetHelper(pname, NULL, &num_written)) {
5126 scoped_ptr<GLint[]> values(new GLint[num_written]);
5127 GetHelper(pname, values.get(), &num_written);
5128 for (GLsizei ii = 0; ii < num_written; ++ii) {
5129 params[ii] = static_cast<GLfloat>(values[ii]);
5131 } else {
5132 pname = AdjustGetPname(pname);
5133 glGetFloatv(pname, params);
5138 void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
5139 DCHECK(params);
5140 GLsizei num_written;
5141 if (!state_.GetStateAsGLint(pname, params, &num_written) &&
5142 !GetHelper(pname, params, &num_written)) {
5143 pname = AdjustGetPname(pname);
5144 glGetIntegerv(pname, params);
5148 void GLES2DecoderImpl::DoGetProgramiv(
5149 GLuint program_id, GLenum pname, GLint* params) {
5150 Program* program = GetProgramInfoNotShader(program_id, "glGetProgramiv");
5151 if (!program) {
5152 return;
5154 program->GetProgramiv(pname, params);
5157 void GLES2DecoderImpl::DoGetBufferParameteriv(
5158 GLenum target, GLenum pname, GLint* params) {
5159 // Just delegate it. Some validation is actually done before this.
5160 buffer_manager()->ValidateAndDoGetBufferParameteriv(
5161 &state_, target, pname, params);
5164 void GLES2DecoderImpl::DoBindAttribLocation(
5165 GLuint program_id, GLuint index, const char* name) {
5166 if (!StringIsValidForGLES(name)) {
5167 LOCAL_SET_GL_ERROR(
5168 GL_INVALID_VALUE, "glBindAttribLocation", "Invalid character");
5169 return;
5171 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
5172 LOCAL_SET_GL_ERROR(
5173 GL_INVALID_OPERATION, "glBindAttribLocation", "reserved prefix");
5174 return;
5176 if (index >= group_->max_vertex_attribs()) {
5177 LOCAL_SET_GL_ERROR(
5178 GL_INVALID_VALUE, "glBindAttribLocation", "index out of range");
5179 return;
5181 Program* program = GetProgramInfoNotShader(
5182 program_id, "glBindAttribLocation");
5183 if (!program) {
5184 return;
5186 // At this point, the program's shaders may not be translated yet,
5187 // therefore, we may not find the hashed attribute name.
5188 // glBindAttribLocation call with original name is useless.
5189 // So instead, we should simply cache the binding, and then call
5190 // Program::ExecuteBindAttribLocationCalls() right before link.
5191 program->SetAttribLocationBinding(name, static_cast<GLint>(index));
5192 // TODO(zmo): Get rid of the following glBindAttribLocation call.
5193 glBindAttribLocation(program->service_id(), index, name);
5196 error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
5197 uint32 immediate_data_size,
5198 const void* cmd_data) {
5199 const gles2::cmds::BindAttribLocationBucket& c =
5200 *static_cast<const gles2::cmds::BindAttribLocationBucket*>(cmd_data);
5201 GLuint program = static_cast<GLuint>(c.program);
5202 GLuint index = static_cast<GLuint>(c.index);
5203 Bucket* bucket = GetBucket(c.name_bucket_id);
5204 if (!bucket || bucket->size() == 0) {
5205 return error::kInvalidArguments;
5207 std::string name_str;
5208 if (!bucket->GetAsString(&name_str)) {
5209 return error::kInvalidArguments;
5211 DoBindAttribLocation(program, index, name_str.c_str());
5212 return error::kNoError;
5215 void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM(
5216 GLuint program_id, GLint location, const char* name) {
5217 if (!StringIsValidForGLES(name)) {
5218 LOCAL_SET_GL_ERROR(
5219 GL_INVALID_VALUE,
5220 "glBindUniformLocationCHROMIUM", "Invalid character");
5221 return;
5223 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
5224 LOCAL_SET_GL_ERROR(
5225 GL_INVALID_OPERATION,
5226 "glBindUniformLocationCHROMIUM", "reserved prefix");
5227 return;
5229 if (location < 0 || static_cast<uint32>(location) >=
5230 (group_->max_fragment_uniform_vectors() +
5231 group_->max_vertex_uniform_vectors()) * 4) {
5232 LOCAL_SET_GL_ERROR(
5233 GL_INVALID_VALUE,
5234 "glBindUniformLocationCHROMIUM", "location out of range");
5235 return;
5237 Program* program = GetProgramInfoNotShader(
5238 program_id, "glBindUniformLocationCHROMIUM");
5239 if (!program) {
5240 return;
5242 if (!program->SetUniformLocationBinding(name, location)) {
5243 LOCAL_SET_GL_ERROR(
5244 GL_INVALID_VALUE,
5245 "glBindUniformLocationCHROMIUM", "location out of range");
5249 error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMBucket(
5250 uint32 immediate_data_size,
5251 const void* cmd_data) {
5252 const gles2::cmds::BindUniformLocationCHROMIUMBucket& c =
5253 *static_cast<const gles2::cmds::BindUniformLocationCHROMIUMBucket*>(
5254 cmd_data);
5255 GLuint program = static_cast<GLuint>(c.program);
5256 GLint location = static_cast<GLint>(c.location);
5257 Bucket* bucket = GetBucket(c.name_bucket_id);
5258 if (!bucket || bucket->size() == 0) {
5259 return error::kInvalidArguments;
5261 std::string name_str;
5262 if (!bucket->GetAsString(&name_str)) {
5263 return error::kInvalidArguments;
5265 DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
5266 return error::kNoError;
5269 error::Error GLES2DecoderImpl::HandleDeleteShader(uint32 immediate_data_size,
5270 const void* cmd_data) {
5271 const gles2::cmds::DeleteShader& c =
5272 *static_cast<const gles2::cmds::DeleteShader*>(cmd_data);
5273 GLuint client_id = c.shader;
5274 if (client_id) {
5275 Shader* shader = GetShader(client_id);
5276 if (shader) {
5277 if (!shader->IsDeleted()) {
5278 shader_manager()->Delete(shader);
5280 } else {
5281 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glDeleteShader", "unknown shader");
5284 return error::kNoError;
5287 error::Error GLES2DecoderImpl::HandleDeleteProgram(uint32 immediate_data_size,
5288 const void* cmd_data) {
5289 const gles2::cmds::DeleteProgram& c =
5290 *static_cast<const gles2::cmds::DeleteProgram*>(cmd_data);
5291 GLuint client_id = c.program;
5292 if (client_id) {
5293 Program* program = GetProgram(client_id);
5294 if (program) {
5295 if (!program->IsDeleted()) {
5296 program_manager()->MarkAsDeleted(shader_manager(), program);
5298 } else {
5299 LOCAL_SET_GL_ERROR(
5300 GL_INVALID_VALUE, "glDeleteProgram", "unknown program");
5303 return error::kNoError;
5306 error::Error GLES2DecoderImpl::DoClear(GLbitfield mask) {
5307 DCHECK(!ShouldDeferDraws());
5308 if (CheckBoundFramebuffersValid("glClear")) {
5309 ApplyDirtyState();
5310 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
5311 if (workarounds().gl_clear_broken) {
5312 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::ClearWorkaround",
5313 GetErrorState());
5314 if (!BoundFramebufferHasDepthAttachment())
5315 mask &= ~GL_DEPTH_BUFFER_BIT;
5316 if (!BoundFramebufferHasStencilAttachment())
5317 mask &= ~GL_STENCIL_BUFFER_BIT;
5318 clear_framebuffer_blit_->ClearFramebuffer(
5319 this, GetBoundReadFrameBufferSize(), mask, state_.color_clear_red,
5320 state_.color_clear_green, state_.color_clear_blue,
5321 state_.color_clear_alpha, state_.depth_clear, state_.stencil_clear);
5322 return error::kNoError;
5324 glClear(mask);
5326 return error::kNoError;
5329 void GLES2DecoderImpl::DoFramebufferRenderbuffer(
5330 GLenum target, GLenum attachment, GLenum renderbuffertarget,
5331 GLuint client_renderbuffer_id) {
5332 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5333 if (!framebuffer) {
5334 LOCAL_SET_GL_ERROR(
5335 GL_INVALID_OPERATION,
5336 "glFramebufferRenderbuffer", "no framebuffer bound");
5337 return;
5339 GLuint service_id = 0;
5340 Renderbuffer* renderbuffer = NULL;
5341 if (client_renderbuffer_id) {
5342 renderbuffer = GetRenderbuffer(client_renderbuffer_id);
5343 if (!renderbuffer) {
5344 LOCAL_SET_GL_ERROR(
5345 GL_INVALID_OPERATION,
5346 "glFramebufferRenderbuffer", "unknown renderbuffer");
5347 return;
5349 service_id = renderbuffer->service_id();
5351 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glFramebufferRenderbuffer");
5352 glFramebufferRenderbufferEXT(
5353 target, attachment, renderbuffertarget, service_id);
5354 GLenum error = LOCAL_PEEK_GL_ERROR("glFramebufferRenderbuffer");
5355 if (error == GL_NO_ERROR) {
5356 framebuffer->AttachRenderbuffer(attachment, renderbuffer);
5358 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
5359 framebuffer_state_.clear_state_dirty = true;
5361 OnFboChanged();
5364 void GLES2DecoderImpl::DoDisable(GLenum cap) {
5365 if (SetCapabilityState(cap, false)) {
5366 glDisable(cap);
5370 void GLES2DecoderImpl::DoEnable(GLenum cap) {
5371 if (SetCapabilityState(cap, true)) {
5372 glEnable(cap);
5376 void GLES2DecoderImpl::DoDepthRangef(GLclampf znear, GLclampf zfar) {
5377 state_.z_near = std::min(1.0f, std::max(0.0f, znear));
5378 state_.z_far = std::min(1.0f, std::max(0.0f, zfar));
5379 glDepthRange(znear, zfar);
5382 void GLES2DecoderImpl::DoSampleCoverage(GLclampf value, GLboolean invert) {
5383 state_.sample_coverage_value = std::min(1.0f, std::max(0.0f, value));
5384 state_.sample_coverage_invert = (invert != 0);
5385 glSampleCoverage(state_.sample_coverage_value, invert);
5388 // Assumes framebuffer is complete.
5389 void GLES2DecoderImpl::ClearUnclearedAttachments(
5390 GLenum target, Framebuffer* framebuffer) {
5391 if (target == GL_READ_FRAMEBUFFER_EXT) {
5392 // bind this to the DRAW point, clear then bind back to READ
5393 // TODO(gman): I don't think there is any guarantee that an FBO that
5394 // is complete on the READ attachment will be complete as a DRAW
5395 // attachment.
5396 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
5397 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, framebuffer->service_id());
5399 GLbitfield clear_bits = 0;
5400 if (framebuffer->HasUnclearedColorAttachments()) {
5401 glClearColor(
5402 0.0f, 0.0f, 0.0f,
5403 (GLES2Util::GetChannelsForFormat(
5404 framebuffer->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0.0f :
5405 1.0f);
5406 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
5407 clear_bits |= GL_COLOR_BUFFER_BIT;
5408 if (feature_info_->feature_flags().ext_draw_buffers)
5409 framebuffer->PrepareDrawBuffersForClear();
5412 if (framebuffer->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) ||
5413 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
5414 glClearStencil(0);
5415 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
5416 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
5417 clear_bits |= GL_STENCIL_BUFFER_BIT;
5420 if (framebuffer->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
5421 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
5422 glClearDepth(1.0f);
5423 state_.SetDeviceDepthMask(GL_TRUE);
5424 clear_bits |= GL_DEPTH_BUFFER_BIT;
5427 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
5428 glClear(clear_bits);
5430 if ((clear_bits & GL_COLOR_BUFFER_BIT) != 0 &&
5431 feature_info_->feature_flags().ext_draw_buffers)
5432 framebuffer->RestoreDrawBuffersAfterClear();
5434 framebuffer_manager()->MarkAttachmentsAsCleared(
5435 framebuffer, renderbuffer_manager(), texture_manager());
5437 RestoreClearState();
5439 if (target == GL_READ_FRAMEBUFFER_EXT) {
5440 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, framebuffer->service_id());
5441 Framebuffer* draw_framebuffer =
5442 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
5443 GLuint service_id = draw_framebuffer ? draw_framebuffer->service_id() :
5444 GetBackbufferServiceId();
5445 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, service_id);
5449 void GLES2DecoderImpl::RestoreClearState() {
5450 framebuffer_state_.clear_state_dirty = true;
5451 glClearColor(
5452 state_.color_clear_red, state_.color_clear_green, state_.color_clear_blue,
5453 state_.color_clear_alpha);
5454 glClearStencil(state_.stencil_clear);
5455 glClearDepth(state_.depth_clear);
5456 if (state_.enable_flags.scissor_test) {
5457 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
5461 GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
5462 Framebuffer* framebuffer =
5463 GetFramebufferInfoForTarget(target);
5464 if (!framebuffer) {
5465 return GL_FRAMEBUFFER_COMPLETE;
5467 GLenum completeness = framebuffer->IsPossiblyComplete();
5468 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
5469 return completeness;
5471 return framebuffer->GetStatus(texture_manager(), target);
5474 void GLES2DecoderImpl::DoFramebufferTexture2D(
5475 GLenum target, GLenum attachment, GLenum textarget,
5476 GLuint client_texture_id, GLint level) {
5477 DoFramebufferTexture2DCommon(
5478 "glFramebufferTexture2D", target, attachment,
5479 textarget, client_texture_id, level, 0);
5482 void GLES2DecoderImpl::DoFramebufferTexture2DMultisample(
5483 GLenum target, GLenum attachment, GLenum textarget,
5484 GLuint client_texture_id, GLint level, GLsizei samples) {
5485 DoFramebufferTexture2DCommon(
5486 "glFramebufferTexture2DMultisample", target, attachment,
5487 textarget, client_texture_id, level, samples);
5490 void GLES2DecoderImpl::DoFramebufferTexture2DCommon(
5491 const char* name, GLenum target, GLenum attachment, GLenum textarget,
5492 GLuint client_texture_id, GLint level, GLsizei samples) {
5493 if (samples > renderbuffer_manager()->max_samples()) {
5494 LOCAL_SET_GL_ERROR(
5495 GL_INVALID_VALUE,
5496 "glFramebufferTexture2DMultisample", "samples too large");
5497 return;
5499 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5500 if (!framebuffer) {
5501 LOCAL_SET_GL_ERROR(
5502 GL_INVALID_OPERATION,
5503 name, "no framebuffer bound.");
5504 return;
5506 GLuint service_id = 0;
5507 TextureRef* texture_ref = NULL;
5508 if (client_texture_id) {
5509 texture_ref = GetTexture(client_texture_id);
5510 if (!texture_ref) {
5511 LOCAL_SET_GL_ERROR(
5512 GL_INVALID_OPERATION,
5513 name, "unknown texture_ref");
5514 return;
5516 service_id = texture_ref->service_id();
5519 if (!texture_manager()->ValidForTarget(textarget, level, 0, 0, 1)) {
5520 LOCAL_SET_GL_ERROR(
5521 GL_INVALID_VALUE,
5522 name, "level out of range");
5523 return;
5526 if (texture_ref)
5527 DoWillUseTexImageIfNeeded(texture_ref->texture(), textarget);
5529 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(name);
5530 if (0 == samples) {
5531 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
5532 } else {
5533 if (features().use_img_for_multisampled_render_to_texture) {
5534 glFramebufferTexture2DMultisampleIMG(target, attachment, textarget,
5535 service_id, level, samples);
5536 } else {
5537 glFramebufferTexture2DMultisampleEXT(target, attachment, textarget,
5538 service_id, level, samples);
5541 GLenum error = LOCAL_PEEK_GL_ERROR(name);
5542 if (error == GL_NO_ERROR) {
5543 framebuffer->AttachTexture(attachment, texture_ref, textarget, level,
5544 samples);
5546 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
5547 framebuffer_state_.clear_state_dirty = true;
5550 if (texture_ref)
5551 DoDidUseTexImageIfNeeded(texture_ref->texture(), textarget);
5553 OnFboChanged();
5556 void GLES2DecoderImpl::DoFramebufferTextureLayer(
5557 GLenum target, GLenum attachment, GLuint client_texture_id,
5558 GLint level, GLint layer) {
5559 // TODO(zmo): Unsafe ES3 API, missing states update.
5560 GLuint service_id = 0;
5561 TextureRef* texture_ref = NULL;
5562 if (client_texture_id) {
5563 texture_ref = GetTexture(client_texture_id);
5564 if (!texture_ref) {
5565 LOCAL_SET_GL_ERROR(
5566 GL_INVALID_OPERATION,
5567 "glFramebufferTextureLayer", "unknown texture_ref");
5568 return;
5570 service_id = texture_ref->service_id();
5572 glFramebufferTextureLayer(target, attachment, service_id, level, layer);
5575 void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
5576 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
5577 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5578 if (!framebuffer) {
5579 LOCAL_SET_GL_ERROR(
5580 GL_INVALID_OPERATION,
5581 "glGetFramebufferAttachmentParameteriv", "no framebuffer bound");
5582 return;
5584 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
5585 const Framebuffer::Attachment* attachment_object =
5586 framebuffer->GetAttachment(attachment);
5587 *params = attachment_object ? attachment_object->object_name() : 0;
5588 } else {
5589 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT &&
5590 features().use_img_for_multisampled_render_to_texture) {
5591 pname = GL_TEXTURE_SAMPLES_IMG;
5593 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
5597 void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
5598 GLenum target, GLenum pname, GLint* params) {
5599 Renderbuffer* renderbuffer =
5600 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5601 if (!renderbuffer) {
5602 LOCAL_SET_GL_ERROR(
5603 GL_INVALID_OPERATION,
5604 "glGetRenderbufferParameteriv", "no renderbuffer bound");
5605 return;
5608 EnsureRenderbufferBound();
5609 switch (pname) {
5610 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5611 *params = renderbuffer->internal_format();
5612 break;
5613 case GL_RENDERBUFFER_WIDTH:
5614 *params = renderbuffer->width();
5615 break;
5616 case GL_RENDERBUFFER_HEIGHT:
5617 *params = renderbuffer->height();
5618 break;
5619 case GL_RENDERBUFFER_SAMPLES_EXT:
5620 if (features().use_img_for_multisampled_render_to_texture) {
5621 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_IMG,
5622 params);
5623 } else {
5624 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_EXT,
5625 params);
5627 default:
5628 glGetRenderbufferParameterivEXT(target, pname, params);
5629 break;
5633 void GLES2DecoderImpl::DoBlitFramebufferCHROMIUM(
5634 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
5635 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
5636 GLbitfield mask, GLenum filter) {
5637 DCHECK(!ShouldDeferReads() && !ShouldDeferDraws());
5639 if (!CheckBoundFramebuffersValid("glBlitFramebufferCHROMIUM")) {
5640 return;
5643 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
5644 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
5645 BlitFramebufferHelper(
5646 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5647 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST,
5648 state_.enable_flags.scissor_test);
5651 void GLES2DecoderImpl::EnsureRenderbufferBound() {
5652 if (!state_.bound_renderbuffer_valid) {
5653 state_.bound_renderbuffer_valid = true;
5654 glBindRenderbufferEXT(GL_RENDERBUFFER,
5655 state_.bound_renderbuffer.get()
5656 ? state_.bound_renderbuffer->service_id()
5657 : 0);
5661 void GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(
5662 const FeatureInfo* feature_info,
5663 GLenum target,
5664 GLsizei samples,
5665 GLenum internal_format,
5666 GLsizei width,
5667 GLsizei height) {
5668 // TODO(sievers): This could be resolved at the GL binding level, but the
5669 // binding process is currently a bit too 'brute force'.
5670 if (feature_info->gl_version_info().is_angle) {
5671 glRenderbufferStorageMultisampleANGLE(
5672 target, samples, internal_format, width, height);
5673 } else if (feature_info->feature_flags().use_core_framebuffer_multisample) {
5674 glRenderbufferStorageMultisample(
5675 target, samples, internal_format, width, height);
5676 } else {
5677 glRenderbufferStorageMultisampleEXT(
5678 target, samples, internal_format, width, height);
5682 void GLES2DecoderImpl::BlitFramebufferHelper(GLint srcX0,
5683 GLint srcY0,
5684 GLint srcX1,
5685 GLint srcY1,
5686 GLint dstX0,
5687 GLint dstY0,
5688 GLint dstX1,
5689 GLint dstY1,
5690 GLbitfield mask,
5691 GLenum filter) {
5692 // TODO(sievers): This could be resolved at the GL binding level, but the
5693 // binding process is currently a bit too 'brute force'.
5694 if (feature_info_->gl_version_info().is_angle) {
5695 glBlitFramebufferANGLE(
5696 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5697 } else if (feature_info_->feature_flags().use_core_framebuffer_multisample) {
5698 glBlitFramebuffer(
5699 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5700 } else {
5701 glBlitFramebufferEXT(
5702 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5706 bool GLES2DecoderImpl::ValidateRenderbufferStorageMultisample(
5707 GLsizei samples,
5708 GLenum internalformat,
5709 GLsizei width,
5710 GLsizei height) {
5711 if (samples > renderbuffer_manager()->max_samples()) {
5712 LOCAL_SET_GL_ERROR(
5713 GL_INVALID_VALUE,
5714 "glRenderbufferStorageMultisample", "samples too large");
5715 return false;
5718 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
5719 height > renderbuffer_manager()->max_renderbuffer_size()) {
5720 LOCAL_SET_GL_ERROR(
5721 GL_INVALID_VALUE,
5722 "glRenderbufferStorageMultisample", "dimensions too large");
5723 return false;
5726 uint32 estimated_size = 0;
5727 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
5728 width, height, samples, internalformat, &estimated_size)) {
5729 LOCAL_SET_GL_ERROR(
5730 GL_OUT_OF_MEMORY,
5731 "glRenderbufferStorageMultisample", "dimensions too large");
5732 return false;
5735 if (!EnsureGPUMemoryAvailable(estimated_size)) {
5736 LOCAL_SET_GL_ERROR(
5737 GL_OUT_OF_MEMORY,
5738 "glRenderbufferStorageMultisample", "out of memory");
5739 return false;
5742 return true;
5745 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleCHROMIUM(
5746 GLenum target, GLsizei samples, GLenum internalformat,
5747 GLsizei width, GLsizei height) {
5748 Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5749 if (!renderbuffer) {
5750 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
5751 "glRenderbufferStorageMultisampleCHROMIUM",
5752 "no renderbuffer bound");
5753 return;
5756 if (!ValidateRenderbufferStorageMultisample(
5757 samples, internalformat, width, height)) {
5758 return;
5761 EnsureRenderbufferBound();
5762 GLenum impl_format =
5763 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5764 internalformat);
5765 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(
5766 "glRenderbufferStorageMultisampleCHROMIUM");
5767 RenderbufferStorageMultisampleHelper(
5768 feature_info_.get(), target, samples, impl_format, width, height);
5769 GLenum error =
5770 LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleCHROMIUM");
5771 if (error == GL_NO_ERROR) {
5772 if (workarounds().validate_multisample_buffer_allocation) {
5773 if (!VerifyMultisampleRenderbufferIntegrity(
5774 renderbuffer->service_id(), impl_format)) {
5775 LOCAL_SET_GL_ERROR(
5776 GL_OUT_OF_MEMORY,
5777 "glRenderbufferStorageMultisampleCHROMIUM", "out of memory");
5778 return;
5782 // TODO(gman): If renderbuffers tracked which framebuffers they were
5783 // attached to we could just mark those framebuffers as not complete.
5784 framebuffer_manager()->IncFramebufferStateChangeCount();
5785 renderbuffer_manager()->SetInfo(
5786 renderbuffer, samples, internalformat, width, height);
5790 // This is the handler for multisampled_render_to_texture extensions.
5791 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleEXT(
5792 GLenum target, GLsizei samples, GLenum internalformat,
5793 GLsizei width, GLsizei height) {
5794 Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5795 if (!renderbuffer) {
5796 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
5797 "glRenderbufferStorageMultisampleEXT",
5798 "no renderbuffer bound");
5799 return;
5802 if (!ValidateRenderbufferStorageMultisample(
5803 samples, internalformat, width, height)) {
5804 return;
5807 EnsureRenderbufferBound();
5808 GLenum impl_format =
5809 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5810 internalformat);
5811 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorageMultisampleEXT");
5812 if (features().use_img_for_multisampled_render_to_texture) {
5813 glRenderbufferStorageMultisampleIMG(
5814 target, samples, impl_format, width, height);
5815 } else {
5816 glRenderbufferStorageMultisampleEXT(
5817 target, samples, impl_format, width, height);
5819 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleEXT");
5820 if (error == GL_NO_ERROR) {
5821 // TODO(gman): If renderbuffers tracked which framebuffers they were
5822 // attached to we could just mark those framebuffers as not complete.
5823 framebuffer_manager()->IncFramebufferStateChangeCount();
5824 renderbuffer_manager()->SetInfo(
5825 renderbuffer, samples, internalformat, width, height);
5829 // This function validates the allocation of a multisampled renderbuffer
5830 // by clearing it to a key color, blitting the contents to a texture, and
5831 // reading back the color to ensure it matches the key.
5832 bool GLES2DecoderImpl::VerifyMultisampleRenderbufferIntegrity(
5833 GLuint renderbuffer, GLenum format) {
5835 // Only validate color buffers.
5836 // These formats have been selected because they are very common or are known
5837 // to be used by the WebGL backbuffer. If problems are observed with other
5838 // color formats they can be added here.
5839 switch (format) {
5840 case GL_RGB:
5841 case GL_RGB8:
5842 case GL_RGBA:
5843 case GL_RGBA8:
5844 break;
5845 default:
5846 return true;
5849 GLint draw_framebuffer, read_framebuffer;
5851 // Cache framebuffer and texture bindings.
5852 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &draw_framebuffer);
5853 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &read_framebuffer);
5855 if (!validation_texture_) {
5856 GLint bound_texture;
5857 glGetIntegerv(GL_TEXTURE_BINDING_2D, &bound_texture);
5859 // Create additional resources needed for the verification.
5860 glGenTextures(1, &validation_texture_);
5861 glGenFramebuffersEXT(1, &validation_fbo_multisample_);
5862 glGenFramebuffersEXT(1, &validation_fbo_);
5864 // Texture only needs to be 1x1.
5865 glBindTexture(GL_TEXTURE_2D, validation_texture_);
5866 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB,
5867 GL_UNSIGNED_BYTE, NULL);
5869 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
5870 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5871 GL_TEXTURE_2D, validation_texture_, 0);
5873 glBindTexture(GL_TEXTURE_2D, bound_texture);
5876 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
5877 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5878 GL_RENDERBUFFER, renderbuffer);
5880 // Cache current state and reset it to the values we require.
5881 GLboolean scissor_enabled = false;
5882 glGetBooleanv(GL_SCISSOR_TEST, &scissor_enabled);
5883 if (scissor_enabled)
5884 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
5886 GLboolean color_mask[4] = {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE};
5887 glGetBooleanv(GL_COLOR_WRITEMASK, color_mask);
5888 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
5890 GLfloat clear_color[4] = {0.0f, 0.0f, 0.0f, 0.0f};
5891 glGetFloatv(GL_COLOR_CLEAR_VALUE, clear_color);
5892 glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
5894 // Clear the buffer to the desired key color.
5895 glClear(GL_COLOR_BUFFER_BIT);
5897 // Blit from the multisample buffer to a standard texture.
5898 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, validation_fbo_multisample_);
5899 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, validation_fbo_);
5901 BlitFramebufferHelper(
5902 0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
5904 // Read a pixel from the buffer.
5905 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
5907 unsigned char pixel[3] = {0, 0, 0};
5908 glReadPixels(0, 0, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &pixel);
5910 // Detach the renderbuffer.
5911 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
5912 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5913 GL_RENDERBUFFER, 0);
5915 // Restore cached state.
5916 if (scissor_enabled)
5917 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
5919 state_.SetDeviceColorMask(
5920 color_mask[0], color_mask[1], color_mask[2], color_mask[3]);
5921 glClearColor(clear_color[0], clear_color[1], clear_color[2], clear_color[3]);
5922 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, draw_framebuffer);
5923 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, read_framebuffer);
5925 // Return true if the pixel matched the desired key color.
5926 return (pixel[0] == 0xFF &&
5927 pixel[1] == 0x00 &&
5928 pixel[2] == 0xFF);
5931 void GLES2DecoderImpl::DoRenderbufferStorage(
5932 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
5933 Renderbuffer* renderbuffer =
5934 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5935 if (!renderbuffer) {
5936 LOCAL_SET_GL_ERROR(
5937 GL_INVALID_OPERATION,
5938 "glRenderbufferStorage", "no renderbuffer bound");
5939 return;
5942 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
5943 height > renderbuffer_manager()->max_renderbuffer_size()) {
5944 LOCAL_SET_GL_ERROR(
5945 GL_INVALID_VALUE, "glRenderbufferStorage", "dimensions too large");
5946 return;
5949 uint32 estimated_size = 0;
5950 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
5951 width, height, 1, internalformat, &estimated_size)) {
5952 LOCAL_SET_GL_ERROR(
5953 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "dimensions too large");
5954 return;
5957 if (!EnsureGPUMemoryAvailable(estimated_size)) {
5958 LOCAL_SET_GL_ERROR(
5959 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "out of memory");
5960 return;
5963 EnsureRenderbufferBound();
5964 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorage");
5965 glRenderbufferStorageEXT(
5966 target,
5967 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5968 internalformat),
5969 width,
5970 height);
5971 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorage");
5972 if (error == GL_NO_ERROR) {
5973 // TODO(gman): If tetxures tracked which framebuffers they were attached to
5974 // we could just mark those framebuffers as not complete.
5975 framebuffer_manager()->IncFramebufferStateChangeCount();
5976 renderbuffer_manager()->SetInfo(
5977 renderbuffer, 1, internalformat, width, height);
5981 void GLES2DecoderImpl::DoLinkProgram(GLuint program_id) {
5982 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
5983 Program* program = GetProgramInfoNotShader(
5984 program_id, "glLinkProgram");
5985 if (!program) {
5986 return;
5989 LogClientServiceForInfo(program, program_id, "glLinkProgram");
5990 if (program->Link(shader_manager(),
5991 workarounds().count_all_in_varyings_packing ?
5992 Program::kCountAll : Program::kCountOnlyStaticallyUsed,
5993 shader_cache_callback_)) {
5994 if (program == state_.current_program.get()) {
5995 if (workarounds().use_current_program_after_successful_link)
5996 glUseProgram(program->service_id());
5997 if (workarounds().clear_uniforms_before_first_program_use)
5998 program_manager()->ClearUniforms(program);
6002 // LinkProgram can be very slow. Exit command processing to allow for
6003 // context preemption and GPU watchdog checks.
6004 ExitCommandProcessingEarly();
6007 void GLES2DecoderImpl::DoSamplerParameterfv(
6008 GLuint sampler, GLenum pname, const GLfloat* params) {
6009 DCHECK(params);
6010 glSamplerParameterf(sampler, pname, params[0]);
6013 void GLES2DecoderImpl::DoSamplerParameteriv(
6014 GLuint sampler, GLenum pname, const GLint* params) {
6015 DCHECK(params);
6016 glSamplerParameteri(sampler, pname, params[0]);
6019 void GLES2DecoderImpl::DoTexParameterf(
6020 GLenum target, GLenum pname, GLfloat param) {
6021 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
6022 &state_, target);
6023 if (!texture) {
6024 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterf", "unknown texture");
6025 return;
6028 texture_manager()->SetParameterf(
6029 "glTexParameterf", GetErrorState(), texture, pname, param);
6032 void GLES2DecoderImpl::DoTexParameteri(
6033 GLenum target, GLenum pname, GLint param) {
6034 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
6035 &state_, target);
6036 if (!texture) {
6037 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameteri", "unknown texture");
6038 return;
6041 texture_manager()->SetParameteri(
6042 "glTexParameteri", GetErrorState(), texture, pname, param);
6045 void GLES2DecoderImpl::DoTexParameterfv(
6046 GLenum target, GLenum pname, const GLfloat* params) {
6047 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
6048 &state_, target);
6049 if (!texture) {
6050 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterfv", "unknown texture");
6051 return;
6054 texture_manager()->SetParameterf(
6055 "glTexParameterfv", GetErrorState(), texture, pname, *params);
6058 void GLES2DecoderImpl::DoTexParameteriv(
6059 GLenum target, GLenum pname, const GLint* params) {
6060 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
6061 &state_, target);
6062 if (!texture) {
6063 LOCAL_SET_GL_ERROR(
6064 GL_INVALID_VALUE, "glTexParameteriv", "unknown texture");
6065 return;
6068 texture_manager()->SetParameteri(
6069 "glTexParameteriv", GetErrorState(), texture, pname, *params);
6072 bool GLES2DecoderImpl::CheckCurrentValuebuffer(const char* function_name) {
6073 if (!state_.bound_valuebuffer.get()) {
6074 // There is no valuebuffer bound
6075 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
6076 "no valuebuffer in use");
6077 return false;
6079 return true;
6082 bool GLES2DecoderImpl::CheckCurrentValuebufferForSubscription(
6083 GLenum subscription,
6084 const char* function_name) {
6085 if (!CheckCurrentValuebuffer(function_name)) {
6086 return false;
6088 if (!state_.bound_valuebuffer.get()->IsSubscribed(subscription)) {
6089 // The valuebuffer is not subscribed to the target
6090 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
6091 "valuebuffer is not subscribed");
6092 return false;
6094 return true;
6097 bool GLES2DecoderImpl::CheckSubscriptionTarget(GLint location,
6098 GLenum subscription,
6099 const char* function_name) {
6100 if (!CheckCurrentProgramForUniform(location, function_name)) {
6101 return false;
6103 GLint real_location = -1;
6104 GLint array_index = -1;
6105 const Program::UniformInfo* info =
6106 state_.current_program->GetUniformInfoByFakeLocation(
6107 location, &real_location, &array_index);
6108 if (!info) {
6109 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, "unknown location");
6110 return false;
6112 if ((ValuebufferManager::ApiTypeForSubscriptionTarget(subscription) &
6113 info->accepts_api_type) == 0) {
6114 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
6115 "wrong type for subscription");
6116 return false;
6118 return true;
6121 bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
6122 if (!state_.current_program.get()) {
6123 // The program does not exist.
6124 LOCAL_SET_GL_ERROR(
6125 GL_INVALID_OPERATION, function_name, "no program in use");
6126 return false;
6128 if (!state_.current_program->InUse()) {
6129 LOCAL_SET_GL_ERROR(
6130 GL_INVALID_OPERATION, function_name, "program not linked");
6131 return false;
6133 return true;
6136 bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
6137 GLint location, const char* function_name) {
6138 if (!CheckCurrentProgram(function_name)) {
6139 return false;
6141 return location != -1;
6144 bool GLES2DecoderImpl::CheckDrawingFeedbackLoops() {
6145 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
6146 if (!framebuffer)
6147 return false;
6148 const Framebuffer::Attachment* attachment =
6149 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
6150 if (!attachment)
6151 return false;
6153 DCHECK(state_.current_program.get());
6154 const Program::SamplerIndices& sampler_indices =
6155 state_.current_program->sampler_indices();
6156 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6157 const Program::UniformInfo* uniform_info =
6158 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6159 DCHECK(uniform_info);
6160 if (uniform_info->type != GL_SAMPLER_2D)
6161 continue;
6162 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6163 GLuint texture_unit_index = uniform_info->texture_units[jj];
6164 if (texture_unit_index >= state_.texture_units.size())
6165 continue;
6166 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6167 TextureRef* texture_ref =
6168 texture_unit.GetInfoForSamplerType(GL_SAMPLER_2D).get();
6169 if (attachment->IsTexture(texture_ref))
6170 return true;
6173 return false;
6176 bool GLES2DecoderImpl::CheckUniformForApiType(
6177 const Program::UniformInfo* info,
6178 const char* function_name,
6179 Program::UniformApiType api_type) {
6180 DCHECK(info);
6181 if ((api_type & info->accepts_api_type) == 0) {
6182 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
6183 "wrong uniform function for type");
6184 return false;
6186 return true;
6189 bool GLES2DecoderImpl::PrepForSetUniformByLocation(
6190 GLint fake_location,
6191 const char* function_name,
6192 Program::UniformApiType api_type,
6193 GLint* real_location,
6194 GLenum* type,
6195 GLsizei* count) {
6196 DCHECK(type);
6197 DCHECK(count);
6198 DCHECK(real_location);
6200 if (!CheckCurrentProgramForUniform(fake_location, function_name)) {
6201 return false;
6203 GLint array_index = -1;
6204 const Program::UniformInfo* info =
6205 state_.current_program->GetUniformInfoByFakeLocation(
6206 fake_location, real_location, &array_index);
6207 if (!info) {
6208 LOCAL_SET_GL_ERROR(
6209 GL_INVALID_OPERATION, function_name, "unknown location");
6210 return false;
6212 if (!CheckUniformForApiType(info, function_name, api_type)) {
6213 return false;
6215 if (*count > 1 && !info->is_array) {
6216 LOCAL_SET_GL_ERROR(
6217 GL_INVALID_OPERATION, function_name, "count > 1 for non-array");
6218 return false;
6220 *count = std::min(info->size - array_index, *count);
6221 if (*count <= 0) {
6222 return false;
6224 *type = info->type;
6225 return true;
6228 void GLES2DecoderImpl::DoUniform1i(GLint fake_location, GLint v0) {
6229 GLenum type = 0;
6230 GLsizei count = 1;
6231 GLint real_location = -1;
6232 if (!PrepForSetUniformByLocation(fake_location,
6233 "glUniform1i",
6234 Program::kUniform1i,
6235 &real_location,
6236 &type,
6237 &count)) {
6238 return;
6240 if (!state_.current_program->SetSamplers(
6241 state_.texture_units.size(), fake_location, 1, &v0)) {
6242 LOCAL_SET_GL_ERROR(
6243 GL_INVALID_VALUE, "glUniform1i", "texture unit out of range");
6244 return;
6246 glUniform1i(real_location, v0);
6249 void GLES2DecoderImpl::DoUniform1iv(
6250 GLint fake_location, GLsizei count, const GLint *value) {
6251 GLenum type = 0;
6252 GLint real_location = -1;
6253 if (!PrepForSetUniformByLocation(fake_location,
6254 "glUniform1iv",
6255 Program::kUniform1i,
6256 &real_location,
6257 &type,
6258 &count)) {
6259 return;
6261 if (type == GL_SAMPLER_2D || type == GL_SAMPLER_2D_RECT_ARB ||
6262 type == GL_SAMPLER_CUBE || type == GL_SAMPLER_EXTERNAL_OES) {
6263 if (!state_.current_program->SetSamplers(
6264 state_.texture_units.size(), fake_location, count, value)) {
6265 LOCAL_SET_GL_ERROR(
6266 GL_INVALID_VALUE, "glUniform1iv", "texture unit out of range");
6267 return;
6270 glUniform1iv(real_location, count, value);
6273 void GLES2DecoderImpl::DoUniform1fv(
6274 GLint fake_location, GLsizei count, const GLfloat* value) {
6275 GLenum type = 0;
6276 GLint real_location = -1;
6277 if (!PrepForSetUniformByLocation(fake_location,
6278 "glUniform1fv",
6279 Program::kUniform1f,
6280 &real_location,
6281 &type,
6282 &count)) {
6283 return;
6285 if (type == GL_BOOL) {
6286 scoped_ptr<GLint[]> temp(new GLint[count]);
6287 for (GLsizei ii = 0; ii < count; ++ii) {
6288 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6290 DoUniform1iv(real_location, count, temp.get());
6291 } else {
6292 glUniform1fv(real_location, count, value);
6296 void GLES2DecoderImpl::DoUniform2fv(
6297 GLint fake_location, GLsizei count, const GLfloat* value) {
6298 GLenum type = 0;
6299 GLint real_location = -1;
6300 if (!PrepForSetUniformByLocation(fake_location,
6301 "glUniform2fv",
6302 Program::kUniform2f,
6303 &real_location,
6304 &type,
6305 &count)) {
6306 return;
6308 if (type == GL_BOOL_VEC2) {
6309 GLsizei num_values = count * 2;
6310 scoped_ptr<GLint[]> temp(new GLint[num_values]);
6311 for (GLsizei ii = 0; ii < num_values; ++ii) {
6312 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6314 glUniform2iv(real_location, count, temp.get());
6315 } else {
6316 glUniform2fv(real_location, count, value);
6320 void GLES2DecoderImpl::DoUniform3fv(
6321 GLint fake_location, GLsizei count, const GLfloat* value) {
6322 GLenum type = 0;
6323 GLint real_location = -1;
6324 if (!PrepForSetUniformByLocation(fake_location,
6325 "glUniform3fv",
6326 Program::kUniform3f,
6327 &real_location,
6328 &type,
6329 &count)) {
6330 return;
6332 if (type == GL_BOOL_VEC3) {
6333 GLsizei num_values = count * 3;
6334 scoped_ptr<GLint[]> temp(new GLint[num_values]);
6335 for (GLsizei ii = 0; ii < num_values; ++ii) {
6336 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6338 glUniform3iv(real_location, count, temp.get());
6339 } else {
6340 glUniform3fv(real_location, count, value);
6344 void GLES2DecoderImpl::DoUniform4fv(
6345 GLint fake_location, GLsizei count, const GLfloat* value) {
6346 GLenum type = 0;
6347 GLint real_location = -1;
6348 if (!PrepForSetUniformByLocation(fake_location,
6349 "glUniform4fv",
6350 Program::kUniform4f,
6351 &real_location,
6352 &type,
6353 &count)) {
6354 return;
6356 if (type == GL_BOOL_VEC4) {
6357 GLsizei num_values = count * 4;
6358 scoped_ptr<GLint[]> temp(new GLint[num_values]);
6359 for (GLsizei ii = 0; ii < num_values; ++ii) {
6360 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6362 glUniform4iv(real_location, count, temp.get());
6363 } else {
6364 glUniform4fv(real_location, count, value);
6368 void GLES2DecoderImpl::DoUniform2iv(
6369 GLint fake_location, GLsizei count, const GLint* value) {
6370 GLenum type = 0;
6371 GLint real_location = -1;
6372 if (!PrepForSetUniformByLocation(fake_location,
6373 "glUniform2iv",
6374 Program::kUniform2i,
6375 &real_location,
6376 &type,
6377 &count)) {
6378 return;
6380 glUniform2iv(real_location, count, value);
6383 void GLES2DecoderImpl::DoUniform3iv(
6384 GLint fake_location, GLsizei count, const GLint* value) {
6385 GLenum type = 0;
6386 GLint real_location = -1;
6387 if (!PrepForSetUniformByLocation(fake_location,
6388 "glUniform3iv",
6389 Program::kUniform3i,
6390 &real_location,
6391 &type,
6392 &count)) {
6393 return;
6395 glUniform3iv(real_location, count, value);
6398 void GLES2DecoderImpl::DoUniform4iv(
6399 GLint fake_location, GLsizei count, const GLint* value) {
6400 GLenum type = 0;
6401 GLint real_location = -1;
6402 if (!PrepForSetUniformByLocation(fake_location,
6403 "glUniform4iv",
6404 Program::kUniform4i,
6405 &real_location,
6406 &type,
6407 &count)) {
6408 return;
6410 glUniform4iv(real_location, count, value);
6413 void GLES2DecoderImpl::DoUniformMatrix2fv(
6414 GLint fake_location, GLsizei count, GLboolean transpose,
6415 const GLfloat* value) {
6416 GLenum type = 0;
6417 GLint real_location = -1;
6418 if (!PrepForSetUniformByLocation(fake_location,
6419 "glUniformMatrix2fv",
6420 Program::kUniformMatrix2f,
6421 &real_location,
6422 &type,
6423 &count)) {
6424 return;
6426 glUniformMatrix2fv(real_location, count, transpose, value);
6429 void GLES2DecoderImpl::DoUniformMatrix3fv(
6430 GLint fake_location, GLsizei count, GLboolean transpose,
6431 const GLfloat* value) {
6432 GLenum type = 0;
6433 GLint real_location = -1;
6434 if (!PrepForSetUniformByLocation(fake_location,
6435 "glUniformMatrix3fv",
6436 Program::kUniformMatrix3f,
6437 &real_location,
6438 &type,
6439 &count)) {
6440 return;
6442 glUniformMatrix3fv(real_location, count, transpose, value);
6445 void GLES2DecoderImpl::DoUniformMatrix4fv(
6446 GLint fake_location, GLsizei count, GLboolean transpose,
6447 const GLfloat* value) {
6448 GLenum type = 0;
6449 GLint real_location = -1;
6450 if (!PrepForSetUniformByLocation(fake_location,
6451 "glUniformMatrix4fv",
6452 Program::kUniformMatrix4f,
6453 &real_location,
6454 &type,
6455 &count)) {
6456 return;
6458 glUniformMatrix4fv(real_location, count, transpose, value);
6461 void GLES2DecoderImpl::DoUseProgram(GLuint program_id) {
6462 GLuint service_id = 0;
6463 Program* program = NULL;
6464 if (program_id) {
6465 program = GetProgramInfoNotShader(program_id, "glUseProgram");
6466 if (!program) {
6467 return;
6469 if (!program->IsValid()) {
6470 // Program was not linked successfully. (ie, glLinkProgram)
6471 LOCAL_SET_GL_ERROR(
6472 GL_INVALID_OPERATION, "glUseProgram", "program not linked");
6473 return;
6475 service_id = program->service_id();
6477 if (state_.current_program.get()) {
6478 program_manager()->UnuseProgram(shader_manager(),
6479 state_.current_program.get());
6481 state_.current_program = program;
6482 LogClientServiceMapping("glUseProgram", program_id, service_id);
6483 glUseProgram(service_id);
6484 if (state_.current_program.get()) {
6485 program_manager()->UseProgram(state_.current_program.get());
6486 if (workarounds().clear_uniforms_before_first_program_use)
6487 program_manager()->ClearUniforms(program);
6491 void GLES2DecoderImpl::RenderWarning(
6492 const char* filename, int line, const std::string& msg) {
6493 logger_.LogMessage(filename, line, std::string("RENDER WARNING: ") + msg);
6496 void GLES2DecoderImpl::PerformanceWarning(
6497 const char* filename, int line, const std::string& msg) {
6498 logger_.LogMessage(filename, line,
6499 std::string("PERFORMANCE WARNING: ") + msg);
6502 void GLES2DecoderImpl::DoWillUseTexImageIfNeeded(
6503 Texture* texture, GLenum textarget) {
6504 // Image is already in use if texture is attached to a framebuffer.
6505 if (texture && !texture->IsAttachedToFramebuffer()) {
6506 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6507 if (image) {
6508 ScopedGLErrorSuppressor suppressor(
6509 "GLES2DecoderImpl::DoWillUseTexImageIfNeeded",
6510 GetErrorState());
6511 glBindTexture(textarget, texture->service_id());
6512 image->WillUseTexImage();
6513 RestoreCurrentTextureBindings(&state_, textarget);
6518 void GLES2DecoderImpl::DoDidUseTexImageIfNeeded(
6519 Texture* texture, GLenum textarget) {
6520 // Image is still in use if texture is attached to a framebuffer.
6521 if (texture && !texture->IsAttachedToFramebuffer()) {
6522 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6523 if (image) {
6524 ScopedGLErrorSuppressor suppressor(
6525 "GLES2DecoderImpl::DoDidUseTexImageIfNeeded",
6526 GetErrorState());
6527 glBindTexture(textarget, texture->service_id());
6528 image->DidUseTexImage();
6529 RestoreCurrentTextureBindings(&state_, textarget);
6534 bool GLES2DecoderImpl::PrepareTexturesForRender() {
6535 DCHECK(state_.current_program.get());
6536 if (!texture_manager()->HaveUnrenderableTextures() &&
6537 !texture_manager()->HaveImages()) {
6538 return true;
6541 bool textures_set = false;
6542 const Program::SamplerIndices& sampler_indices =
6543 state_.current_program->sampler_indices();
6544 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6545 const Program::UniformInfo* uniform_info =
6546 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6547 DCHECK(uniform_info);
6548 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6549 GLuint texture_unit_index = uniform_info->texture_units[jj];
6550 if (texture_unit_index < state_.texture_units.size()) {
6551 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6552 TextureRef* texture_ref =
6553 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6554 GLenum textarget = GetBindTargetForSamplerType(uniform_info->type);
6555 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
6556 textures_set = true;
6557 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6558 glBindTexture(
6559 textarget,
6560 texture_manager()->black_texture_id(uniform_info->type));
6561 if (!texture_ref) {
6562 LOCAL_RENDER_WARNING(
6563 std::string("there is no texture bound to the unit ") +
6564 base::IntToString(texture_unit_index));
6565 } else {
6566 LOCAL_RENDER_WARNING(
6567 std::string("texture bound to texture unit ") +
6568 base::IntToString(texture_unit_index) +
6569 " is not renderable. It maybe non-power-of-2 and have"
6570 " incompatible texture filtering.");
6572 continue;
6575 if (textarget != GL_TEXTURE_CUBE_MAP) {
6576 Texture* texture = texture_ref->texture();
6577 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6578 if (image && !texture->IsAttachedToFramebuffer()) {
6579 ScopedGLErrorSuppressor suppressor(
6580 "GLES2DecoderImpl::PrepareTexturesForRender", GetErrorState());
6581 textures_set = true;
6582 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6583 image->WillUseTexImage();
6584 continue;
6588 // else: should this be an error?
6591 return !textures_set;
6594 void GLES2DecoderImpl::RestoreStateForTextures() {
6595 DCHECK(state_.current_program.get());
6596 const Program::SamplerIndices& sampler_indices =
6597 state_.current_program->sampler_indices();
6598 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6599 const Program::UniformInfo* uniform_info =
6600 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6601 DCHECK(uniform_info);
6602 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6603 GLuint texture_unit_index = uniform_info->texture_units[jj];
6604 if (texture_unit_index < state_.texture_units.size()) {
6605 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6606 TextureRef* texture_ref =
6607 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6608 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
6609 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6610 // Get the texture_ref info that was previously bound here.
6611 texture_ref = texture_unit.bind_target == GL_TEXTURE_2D
6612 ? texture_unit.bound_texture_2d.get()
6613 : texture_unit.bound_texture_cube_map.get();
6614 glBindTexture(texture_unit.bind_target,
6615 texture_ref ? texture_ref->service_id() : 0);
6616 continue;
6619 if (texture_unit.bind_target != GL_TEXTURE_CUBE_MAP) {
6620 Texture* texture = texture_ref->texture();
6621 gfx::GLImage* image =
6622 texture->GetLevelImage(texture_unit.bind_target, 0);
6623 if (image && !texture->IsAttachedToFramebuffer()) {
6624 ScopedGLErrorSuppressor suppressor(
6625 "GLES2DecoderImpl::RestoreStateForTextures", GetErrorState());
6626 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6627 image->DidUseTexImage();
6628 continue;
6634 // Set the active texture back to whatever the user had it as.
6635 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
6638 bool GLES2DecoderImpl::ClearUnclearedTextures() {
6639 // Only check if there are some uncleared textures.
6640 if (!texture_manager()->HaveUnsafeTextures()) {
6641 return true;
6644 // 1: Check all textures we are about to render with.
6645 if (state_.current_program.get()) {
6646 const Program::SamplerIndices& sampler_indices =
6647 state_.current_program->sampler_indices();
6648 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6649 const Program::UniformInfo* uniform_info =
6650 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6651 DCHECK(uniform_info);
6652 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6653 GLuint texture_unit_index = uniform_info->texture_units[jj];
6654 if (texture_unit_index < state_.texture_units.size()) {
6655 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6656 TextureRef* texture_ref =
6657 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6658 if (texture_ref && !texture_ref->texture()->SafeToRenderFrom()) {
6659 if (!texture_manager()->ClearRenderableLevels(this, texture_ref)) {
6660 return false;
6667 return true;
6670 bool GLES2DecoderImpl::IsDrawValid(
6671 const char* function_name, GLuint max_vertex_accessed, bool instanced,
6672 GLsizei primcount) {
6673 DCHECK(instanced || primcount == 1);
6675 // NOTE: We specifically do not check current_program->IsValid() because
6676 // it could never be invalid since glUseProgram would have failed. While
6677 // glLinkProgram could later mark the program as invalid the previous
6678 // valid program will still function if it is still the current program.
6679 if (!state_.current_program.get()) {
6680 // The program does not exist.
6681 // But GL says no ERROR.
6682 LOCAL_RENDER_WARNING("Drawing with no current shader program.");
6683 return false;
6686 if (CheckDrawingFeedbackLoops()) {
6687 LOCAL_SET_GL_ERROR(
6688 GL_INVALID_OPERATION, function_name,
6689 "Source and destination textures of the draw are the same.");
6690 return false;
6693 return state_.vertex_attrib_manager
6694 ->ValidateBindings(function_name,
6695 this,
6696 feature_info_.get(),
6697 state_.current_program.get(),
6698 max_vertex_accessed,
6699 instanced,
6700 primcount);
6703 bool GLES2DecoderImpl::SimulateAttrib0(
6704 const char* function_name, GLuint max_vertex_accessed, bool* simulated) {
6705 DCHECK(simulated);
6706 *simulated = false;
6708 if (feature_info_->gl_version_info().BehavesLikeGLES())
6709 return true;
6711 const VertexAttrib* attrib =
6712 state_.vertex_attrib_manager->GetVertexAttrib(0);
6713 // If it's enabled or it's not used then we don't need to do anything.
6714 bool attrib_0_used =
6715 state_.current_program->GetAttribInfoByLocation(0) != NULL;
6716 if (attrib->enabled() && attrib_0_used) {
6717 return true;
6720 // Make a buffer with a single repeated vec4 value enough to
6721 // simulate the constant value that is supposed to be here.
6722 // This is required to emulate GLES2 on GL.
6723 GLuint num_vertices = max_vertex_accessed + 1;
6724 uint32 size_needed = 0;
6726 if (num_vertices == 0 ||
6727 !SafeMultiplyUint32(num_vertices, sizeof(Vec4), &size_needed) ||
6728 size_needed > 0x7FFFFFFFU) {
6729 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6730 return false;
6733 LOCAL_PERFORMANCE_WARNING(
6734 "Attribute 0 is disabled. This has signficant performance penalty");
6736 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
6737 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
6739 bool new_buffer = static_cast<GLsizei>(size_needed) > attrib_0_size_;
6740 if (new_buffer) {
6741 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
6742 GLenum error = glGetError();
6743 if (error != GL_NO_ERROR) {
6744 LOCAL_SET_GL_ERROR(
6745 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6746 return false;
6750 const Vec4& value = state_.attrib_values[0];
6751 if (new_buffer ||
6752 (attrib_0_used &&
6753 (!attrib_0_buffer_matches_value_ ||
6754 (value.v[0] != attrib_0_value_.v[0] ||
6755 value.v[1] != attrib_0_value_.v[1] ||
6756 value.v[2] != attrib_0_value_.v[2] ||
6757 value.v[3] != attrib_0_value_.v[3])))) {
6758 std::vector<Vec4> temp(num_vertices, value);
6759 glBufferSubData(GL_ARRAY_BUFFER, 0, size_needed, &temp[0].v[0]);
6760 attrib_0_buffer_matches_value_ = true;
6761 attrib_0_value_ = value;
6762 attrib_0_size_ = size_needed;
6765 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
6767 if (attrib->divisor())
6768 glVertexAttribDivisorANGLE(0, 0);
6770 *simulated = true;
6771 return true;
6774 void GLES2DecoderImpl::RestoreStateForAttrib(
6775 GLuint attrib_index, bool restore_array_binding) {
6776 const VertexAttrib* attrib =
6777 state_.vertex_attrib_manager->GetVertexAttrib(attrib_index);
6778 if (restore_array_binding) {
6779 const void* ptr = reinterpret_cast<const void*>(attrib->offset());
6780 Buffer* buffer = attrib->buffer();
6781 glBindBuffer(GL_ARRAY_BUFFER, buffer ? buffer->service_id() : 0);
6782 glVertexAttribPointer(
6783 attrib_index, attrib->size(), attrib->type(), attrib->normalized(),
6784 attrib->gl_stride(), ptr);
6786 if (attrib->divisor())
6787 glVertexAttribDivisorANGLE(attrib_index, attrib->divisor());
6788 glBindBuffer(
6789 GL_ARRAY_BUFFER, state_.bound_array_buffer.get() ?
6790 state_.bound_array_buffer->service_id() : 0);
6792 // Never touch vertex attribute 0's state (in particular, never
6793 // disable it) when running on desktop GL because it will never be
6794 // re-enabled.
6795 if (attrib_index != 0 ||
6796 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
6797 if (attrib->enabled()) {
6798 glEnableVertexAttribArray(attrib_index);
6799 } else {
6800 glDisableVertexAttribArray(attrib_index);
6805 bool GLES2DecoderImpl::SimulateFixedAttribs(
6806 const char* function_name,
6807 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount) {
6808 DCHECK(simulated);
6809 *simulated = false;
6810 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
6811 return true;
6813 if (!state_.vertex_attrib_manager->HaveFixedAttribs()) {
6814 return true;
6817 LOCAL_PERFORMANCE_WARNING(
6818 "GL_FIXED attributes have a signficant performance penalty");
6820 // NOTE: we could be smart and try to check if a buffer is used
6821 // twice in 2 different attribs, find the overlapping parts and therefore
6822 // duplicate the minimum amount of data but this whole code path is not meant
6823 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
6824 // tests so we just add to the buffer attrib used.
6826 GLuint elements_needed = 0;
6827 const VertexAttribManager::VertexAttribList& enabled_attribs =
6828 state_.vertex_attrib_manager->GetEnabledVertexAttribs();
6829 for (VertexAttribManager::VertexAttribList::const_iterator it =
6830 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
6831 const VertexAttrib* attrib = *it;
6832 const Program::VertexAttrib* attrib_info =
6833 state_.current_program->GetAttribInfoByLocation(attrib->index());
6834 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
6835 max_vertex_accessed);
6836 GLuint num_vertices = max_accessed + 1;
6837 if (num_vertices == 0) {
6838 LOCAL_SET_GL_ERROR(
6839 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6840 return false;
6842 if (attrib_info &&
6843 attrib->CanAccess(max_accessed) &&
6844 attrib->type() == GL_FIXED) {
6845 uint32 elements_used = 0;
6846 if (!SafeMultiplyUint32(num_vertices, attrib->size(), &elements_used) ||
6847 !SafeAddUint32(elements_needed, elements_used, &elements_needed)) {
6848 LOCAL_SET_GL_ERROR(
6849 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
6850 return false;
6855 const uint32 kSizeOfFloat = sizeof(float); // NOLINT
6856 uint32 size_needed = 0;
6857 if (!SafeMultiplyUint32(elements_needed, kSizeOfFloat, &size_needed) ||
6858 size_needed > 0x7FFFFFFFU) {
6859 LOCAL_SET_GL_ERROR(
6860 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
6861 return false;
6864 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
6866 glBindBuffer(GL_ARRAY_BUFFER, fixed_attrib_buffer_id_);
6867 if (static_cast<GLsizei>(size_needed) > fixed_attrib_buffer_size_) {
6868 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
6869 GLenum error = glGetError();
6870 if (error != GL_NO_ERROR) {
6871 LOCAL_SET_GL_ERROR(
6872 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
6873 return false;
6877 // Copy the elements and convert to float
6878 GLintptr offset = 0;
6879 for (VertexAttribManager::VertexAttribList::const_iterator it =
6880 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
6881 const VertexAttrib* attrib = *it;
6882 const Program::VertexAttrib* attrib_info =
6883 state_.current_program->GetAttribInfoByLocation(attrib->index());
6884 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
6885 max_vertex_accessed);
6886 GLuint num_vertices = max_accessed + 1;
6887 if (num_vertices == 0) {
6888 LOCAL_SET_GL_ERROR(
6889 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6890 return false;
6892 if (attrib_info &&
6893 attrib->CanAccess(max_accessed) &&
6894 attrib->type() == GL_FIXED) {
6895 int num_elements = attrib->size() * num_vertices;
6896 const int src_size = num_elements * sizeof(int32);
6897 const int dst_size = num_elements * sizeof(float);
6898 scoped_ptr<float[]> data(new float[num_elements]);
6899 const int32* src = reinterpret_cast<const int32 *>(
6900 attrib->buffer()->GetRange(attrib->offset(), src_size));
6901 const int32* end = src + num_elements;
6902 float* dst = data.get();
6903 while (src != end) {
6904 *dst++ = static_cast<float>(*src++) / 65536.0f;
6906 glBufferSubData(GL_ARRAY_BUFFER, offset, dst_size, data.get());
6907 glVertexAttribPointer(
6908 attrib->index(), attrib->size(), GL_FLOAT, false, 0,
6909 reinterpret_cast<GLvoid*>(offset));
6910 offset += dst_size;
6913 *simulated = true;
6914 return true;
6917 void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
6918 // There's no need to call glVertexAttribPointer because we shadow all the
6919 // settings and passing GL_FIXED to it will not work.
6920 glBindBuffer(
6921 GL_ARRAY_BUFFER,
6922 state_.bound_array_buffer.get() ? state_.bound_array_buffer->service_id()
6923 : 0);
6926 error::Error GLES2DecoderImpl::DoDrawArrays(
6927 const char* function_name,
6928 bool instanced,
6929 GLenum mode,
6930 GLint first,
6931 GLsizei count,
6932 GLsizei primcount) {
6933 error::Error error = WillAccessBoundFramebufferForDraw();
6934 if (error != error::kNoError)
6935 return error;
6936 if (!validators_->draw_mode.IsValid(mode)) {
6937 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
6938 return error::kNoError;
6940 if (count < 0) {
6941 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
6942 return error::kNoError;
6944 if (primcount < 0) {
6945 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
6946 return error::kNoError;
6948 if (!CheckBoundFramebuffersValid(function_name)) {
6949 return error::kNoError;
6951 // We have to check this here because the prototype for glDrawArrays
6952 // is GLint not GLsizei.
6953 if (first < 0) {
6954 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "first < 0");
6955 return error::kNoError;
6958 if (count == 0 || primcount == 0) {
6959 LOCAL_RENDER_WARNING("Render count or primcount is 0.");
6960 return error::kNoError;
6963 GLuint max_vertex_accessed = first + count - 1;
6964 if (IsDrawValid(function_name, max_vertex_accessed, instanced, primcount)) {
6965 if (!ClearUnclearedTextures()) {
6966 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
6967 return error::kNoError;
6969 bool simulated_attrib_0 = false;
6970 if (!SimulateAttrib0(
6971 function_name, max_vertex_accessed, &simulated_attrib_0)) {
6972 return error::kNoError;
6974 bool simulated_fixed_attribs = false;
6975 if (SimulateFixedAttribs(
6976 function_name, max_vertex_accessed, &simulated_fixed_attribs,
6977 primcount)) {
6978 bool textures_set = !PrepareTexturesForRender();
6979 ApplyDirtyState();
6980 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
6981 if (!instanced) {
6982 glDrawArrays(mode, first, count);
6983 } else {
6984 glDrawArraysInstancedANGLE(mode, first, count, primcount);
6986 if (textures_set) {
6987 RestoreStateForTextures();
6989 if (simulated_fixed_attribs) {
6990 RestoreStateForSimulatedFixedAttribs();
6993 if (simulated_attrib_0) {
6994 // We don't have to restore attrib 0 generic data at the end of this
6995 // function even if it is simulated. This is because we will simulate
6996 // it in each draw call, and attrib 0 generic data queries use cached
6997 // values instead of passing down to the underlying driver.
6998 RestoreStateForAttrib(0, false);
7001 return error::kNoError;
7004 error::Error GLES2DecoderImpl::HandleDrawArrays(uint32 immediate_data_size,
7005 const void* cmd_data) {
7006 const cmds::DrawArrays& c = *static_cast<const cmds::DrawArrays*>(cmd_data);
7007 return DoDrawArrays("glDrawArrays",
7008 false,
7009 static_cast<GLenum>(c.mode),
7010 static_cast<GLint>(c.first),
7011 static_cast<GLsizei>(c.count),
7015 error::Error GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
7016 uint32 immediate_data_size,
7017 const void* cmd_data) {
7018 const gles2::cmds::DrawArraysInstancedANGLE& c =
7019 *static_cast<const gles2::cmds::DrawArraysInstancedANGLE*>(cmd_data);
7020 if (!features().angle_instanced_arrays) {
7021 LOCAL_SET_GL_ERROR(
7022 GL_INVALID_OPERATION,
7023 "glDrawArraysInstancedANGLE", "function not available");
7024 return error::kNoError;
7026 return DoDrawArrays("glDrawArraysIntancedANGLE",
7027 true,
7028 static_cast<GLenum>(c.mode),
7029 static_cast<GLint>(c.first),
7030 static_cast<GLsizei>(c.count),
7031 static_cast<GLsizei>(c.primcount));
7034 error::Error GLES2DecoderImpl::DoDrawElements(
7035 const char* function_name,
7036 bool instanced,
7037 GLenum mode,
7038 GLsizei count,
7039 GLenum type,
7040 int32 offset,
7041 GLsizei primcount) {
7042 error::Error error = WillAccessBoundFramebufferForDraw();
7043 if (error != error::kNoError)
7044 return error;
7045 if (!state_.vertex_attrib_manager->element_array_buffer()) {
7046 LOCAL_SET_GL_ERROR(
7047 GL_INVALID_OPERATION, function_name, "No element array buffer bound");
7048 return error::kNoError;
7051 if (count < 0) {
7052 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
7053 return error::kNoError;
7055 if (offset < 0) {
7056 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "offset < 0");
7057 return error::kNoError;
7059 if (!validators_->draw_mode.IsValid(mode)) {
7060 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
7061 return error::kNoError;
7063 if (!validators_->index_type.IsValid(type)) {
7064 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, type, "type");
7065 return error::kNoError;
7067 if (primcount < 0) {
7068 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
7069 return error::kNoError;
7072 if (!CheckBoundFramebuffersValid(function_name)) {
7073 return error::kNoError;
7076 if (count == 0 || primcount == 0) {
7077 return error::kNoError;
7080 GLuint max_vertex_accessed;
7081 Buffer* element_array_buffer =
7082 state_.vertex_attrib_manager->element_array_buffer();
7084 if (!element_array_buffer->GetMaxValueForRange(
7085 offset, count, type, &max_vertex_accessed)) {
7086 LOCAL_SET_GL_ERROR(
7087 GL_INVALID_OPERATION, function_name, "range out of bounds for buffer");
7088 return error::kNoError;
7091 if (IsDrawValid(function_name, max_vertex_accessed, instanced, primcount)) {
7092 if (!ClearUnclearedTextures()) {
7093 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
7094 return error::kNoError;
7096 bool simulated_attrib_0 = false;
7097 if (!SimulateAttrib0(
7098 function_name, max_vertex_accessed, &simulated_attrib_0)) {
7099 return error::kNoError;
7101 bool simulated_fixed_attribs = false;
7102 if (SimulateFixedAttribs(
7103 function_name, max_vertex_accessed, &simulated_fixed_attribs,
7104 primcount)) {
7105 bool textures_set = !PrepareTexturesForRender();
7106 ApplyDirtyState();
7107 // TODO(gman): Refactor to hide these details in BufferManager or
7108 // VertexAttribManager.
7109 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
7110 bool used_client_side_array = false;
7111 if (element_array_buffer->IsClientSideArray()) {
7112 used_client_side_array = true;
7113 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
7114 indices = element_array_buffer->GetRange(offset, 0);
7117 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
7118 if (!instanced) {
7119 glDrawElements(mode, count, type, indices);
7120 } else {
7121 glDrawElementsInstancedANGLE(mode, count, type, indices, primcount);
7124 if (used_client_side_array) {
7125 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
7126 element_array_buffer->service_id());
7129 if (textures_set) {
7130 RestoreStateForTextures();
7132 if (simulated_fixed_attribs) {
7133 RestoreStateForSimulatedFixedAttribs();
7136 if (simulated_attrib_0) {
7137 // We don't have to restore attrib 0 generic data at the end of this
7138 // function even if it is simulated. This is because we will simulate
7139 // it in each draw call, and attrib 0 generic data queries use cached
7140 // values instead of passing down to the underlying driver.
7141 RestoreStateForAttrib(0, false);
7144 return error::kNoError;
7147 error::Error GLES2DecoderImpl::HandleDrawElements(uint32 immediate_data_size,
7148 const void* cmd_data) {
7149 const gles2::cmds::DrawElements& c =
7150 *static_cast<const gles2::cmds::DrawElements*>(cmd_data);
7151 return DoDrawElements("glDrawElements",
7152 false,
7153 static_cast<GLenum>(c.mode),
7154 static_cast<GLsizei>(c.count),
7155 static_cast<GLenum>(c.type),
7156 static_cast<int32>(c.index_offset),
7160 error::Error GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
7161 uint32 immediate_data_size,
7162 const void* cmd_data) {
7163 const gles2::cmds::DrawElementsInstancedANGLE& c =
7164 *static_cast<const gles2::cmds::DrawElementsInstancedANGLE*>(cmd_data);
7165 if (!features().angle_instanced_arrays) {
7166 LOCAL_SET_GL_ERROR(
7167 GL_INVALID_OPERATION,
7168 "glDrawElementsInstancedANGLE", "function not available");
7169 return error::kNoError;
7171 return DoDrawElements("glDrawElementsInstancedANGLE",
7172 true,
7173 static_cast<GLenum>(c.mode),
7174 static_cast<GLsizei>(c.count),
7175 static_cast<GLenum>(c.type),
7176 static_cast<int32>(c.index_offset),
7177 static_cast<GLsizei>(c.primcount));
7180 GLuint GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
7181 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
7182 GLuint max_vertex_accessed = 0;
7183 Buffer* buffer = GetBuffer(buffer_id);
7184 if (!buffer) {
7185 // TODO(gman): Should this be a GL error or a command buffer error?
7186 LOCAL_SET_GL_ERROR(
7187 GL_INVALID_VALUE, "GetMaxValueInBufferCHROMIUM", "unknown buffer");
7188 } else {
7189 if (!buffer->GetMaxValueForRange(
7190 offset, count, type, &max_vertex_accessed)) {
7191 // TODO(gman): Should this be a GL error or a command buffer error?
7192 LOCAL_SET_GL_ERROR(
7193 GL_INVALID_OPERATION,
7194 "GetMaxValueInBufferCHROMIUM", "range out of bounds for buffer");
7197 return max_vertex_accessed;
7200 void GLES2DecoderImpl::DoShaderSource(
7201 GLuint client_id, GLsizei count, const char** data, const GLint* length) {
7202 std::string str;
7203 for (GLsizei ii = 0; ii < count; ++ii) {
7204 if (length && length[ii] > 0)
7205 str.append(data[ii], length[ii]);
7206 else
7207 str.append(data[ii]);
7209 Shader* shader = GetShaderInfoNotProgram(client_id, "glShaderSource");
7210 if (!shader) {
7211 return;
7213 // Note: We don't actually call glShaderSource here. We wait until
7214 // we actually compile the shader.
7215 shader->set_source(str);
7218 void GLES2DecoderImpl::DoTransformFeedbackVaryings(
7219 GLuint client_program_id, GLsizei count, const char* const* varyings,
7220 GLenum buffer_mode) {
7221 Program* program = GetProgramInfoNotShader(
7222 client_program_id, "glTransformFeedbackVaryings");
7223 if (!program) {
7224 return;
7226 program->TransformFeedbackVaryings(count, varyings, buffer_mode);
7227 glTransformFeedbackVaryings(
7228 program->service_id(), count, varyings, buffer_mode);
7231 void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
7232 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
7233 Shader* shader = GetShaderInfoNotProgram(client_id, "glCompileShader");
7234 if (!shader) {
7235 return;
7238 scoped_refptr<ShaderTranslatorInterface> translator;
7239 if (use_shader_translator_) {
7240 translator = shader->shader_type() == GL_VERTEX_SHADER ?
7241 vertex_translator_ : fragment_translator_;
7244 const Shader::TranslatedShaderSourceType source_type =
7245 feature_info_->feature_flags().angle_translated_shader_source ?
7246 Shader::kANGLE : Shader::kGL;
7247 shader->RequestCompile(translator, source_type);
7250 void GLES2DecoderImpl::DoGetShaderiv(
7251 GLuint shader_id, GLenum pname, GLint* params) {
7252 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderiv");
7253 if (!shader) {
7254 return;
7257 // Compile now for statuses that require it.
7258 switch (pname) {
7259 case GL_COMPILE_STATUS:
7260 case GL_INFO_LOG_LENGTH:
7261 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
7262 shader->DoCompile();
7263 break;
7265 default:
7266 break;
7269 switch (pname) {
7270 case GL_SHADER_SOURCE_LENGTH:
7271 *params = shader->source().size();
7272 if (*params)
7273 ++(*params);
7274 return;
7275 case GL_COMPILE_STATUS:
7276 *params = compile_shader_always_succeeds_ ? true : shader->valid();
7277 return;
7278 case GL_INFO_LOG_LENGTH:
7279 *params = shader->log_info().size();
7280 if (*params)
7281 ++(*params);
7282 return;
7283 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
7284 *params = shader->translated_source().size();
7285 if (*params)
7286 ++(*params);
7287 return;
7288 default:
7289 break;
7291 glGetShaderiv(shader->service_id(), pname, params);
7294 error::Error GLES2DecoderImpl::HandleGetShaderSource(uint32 immediate_data_size,
7295 const void* cmd_data) {
7296 const gles2::cmds::GetShaderSource& c =
7297 *static_cast<const gles2::cmds::GetShaderSource*>(cmd_data);
7298 GLuint shader_id = c.shader;
7299 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
7300 Bucket* bucket = CreateBucket(bucket_id);
7301 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderSource");
7302 if (!shader || shader->source().empty()) {
7303 bucket->SetSize(0);
7304 return error::kNoError;
7306 bucket->SetFromString(shader->source().c_str());
7307 return error::kNoError;
7310 error::Error GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
7311 uint32 immediate_data_size,
7312 const void* cmd_data) {
7313 const gles2::cmds::GetTranslatedShaderSourceANGLE& c =
7314 *static_cast<const gles2::cmds::GetTranslatedShaderSourceANGLE*>(
7315 cmd_data);
7316 GLuint shader_id = c.shader;
7317 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
7318 Bucket* bucket = CreateBucket(bucket_id);
7319 Shader* shader = GetShaderInfoNotProgram(
7320 shader_id, "glGetTranslatedShaderSourceANGLE");
7321 if (!shader) {
7322 bucket->SetSize(0);
7323 return error::kNoError;
7326 // Make sure translator has been utilized in compile.
7327 shader->DoCompile();
7329 bucket->SetFromString(shader->translated_source().c_str());
7330 return error::kNoError;
7333 error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
7334 uint32 immediate_data_size,
7335 const void* cmd_data) {
7336 const gles2::cmds::GetProgramInfoLog& c =
7337 *static_cast<const gles2::cmds::GetProgramInfoLog*>(cmd_data);
7338 GLuint program_id = c.program;
7339 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
7340 Bucket* bucket = CreateBucket(bucket_id);
7341 Program* program = GetProgramInfoNotShader(
7342 program_id, "glGetProgramInfoLog");
7343 if (!program || !program->log_info()) {
7344 bucket->SetFromString("");
7345 return error::kNoError;
7347 bucket->SetFromString(program->log_info()->c_str());
7348 return error::kNoError;
7351 error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
7352 uint32 immediate_data_size,
7353 const void* cmd_data) {
7354 const gles2::cmds::GetShaderInfoLog& c =
7355 *static_cast<const gles2::cmds::GetShaderInfoLog*>(cmd_data);
7356 GLuint shader_id = c.shader;
7357 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
7358 Bucket* bucket = CreateBucket(bucket_id);
7359 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderInfoLog");
7360 if (!shader) {
7361 bucket->SetFromString("");
7362 return error::kNoError;
7365 // Shader must be compiled in order to get the info log.
7366 shader->DoCompile();
7368 bucket->SetFromString(shader->log_info().c_str());
7369 return error::kNoError;
7372 bool GLES2DecoderImpl::DoIsEnabled(GLenum cap) {
7373 return state_.GetEnabled(cap);
7376 bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
7377 const Buffer* buffer = GetBuffer(client_id);
7378 return buffer && buffer->IsValid() && !buffer->IsDeleted();
7381 bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
7382 const Framebuffer* framebuffer =
7383 GetFramebuffer(client_id);
7384 return framebuffer && framebuffer->IsValid() && !framebuffer->IsDeleted();
7387 bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
7388 // IsProgram is true for programs as soon as they are created, until they are
7389 // deleted and no longer in use.
7390 const Program* program = GetProgram(client_id);
7391 return program != NULL && !program->IsDeleted();
7394 bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
7395 const Renderbuffer* renderbuffer =
7396 GetRenderbuffer(client_id);
7397 return renderbuffer && renderbuffer->IsValid() && !renderbuffer->IsDeleted();
7400 bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
7401 // IsShader is true for shaders as soon as they are created, until they
7402 // are deleted and not attached to any programs.
7403 const Shader* shader = GetShader(client_id);
7404 return shader != NULL && !shader->IsDeleted();
7407 bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
7408 const TextureRef* texture_ref = GetTexture(client_id);
7409 return texture_ref && texture_ref->texture()->IsValid();
7412 void GLES2DecoderImpl::DoAttachShader(
7413 GLuint program_client_id, GLint shader_client_id) {
7414 Program* program = GetProgramInfoNotShader(
7415 program_client_id, "glAttachShader");
7416 if (!program) {
7417 return;
7419 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glAttachShader");
7420 if (!shader) {
7421 return;
7423 if (!program->AttachShader(shader_manager(), shader)) {
7424 LOCAL_SET_GL_ERROR(
7425 GL_INVALID_OPERATION,
7426 "glAttachShader",
7427 "can not attach more than one shader of the same type.");
7428 return;
7430 glAttachShader(program->service_id(), shader->service_id());
7433 void GLES2DecoderImpl::DoDetachShader(
7434 GLuint program_client_id, GLint shader_client_id) {
7435 Program* program = GetProgramInfoNotShader(
7436 program_client_id, "glDetachShader");
7437 if (!program) {
7438 return;
7440 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glDetachShader");
7441 if (!shader) {
7442 return;
7444 if (!program->DetachShader(shader_manager(), shader)) {
7445 LOCAL_SET_GL_ERROR(
7446 GL_INVALID_OPERATION,
7447 "glDetachShader", "shader not attached to program");
7448 return;
7450 glDetachShader(program->service_id(), shader->service_id());
7453 void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
7454 Program* program = GetProgramInfoNotShader(
7455 program_client_id, "glValidateProgram");
7456 if (!program) {
7457 return;
7459 program->Validate();
7462 void GLES2DecoderImpl::GetVertexAttribHelper(
7463 const VertexAttrib* attrib, GLenum pname, GLint* params) {
7464 switch (pname) {
7465 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
7466 Buffer* buffer = attrib->buffer();
7467 if (buffer && !buffer->IsDeleted()) {
7468 GLuint client_id;
7469 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
7470 *params = client_id;
7472 break;
7474 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
7475 *params = attrib->enabled();
7476 break;
7477 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
7478 *params = attrib->size();
7479 break;
7480 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
7481 *params = attrib->gl_stride();
7482 break;
7483 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
7484 *params = attrib->type();
7485 break;
7486 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
7487 *params = attrib->normalized();
7488 break;
7489 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE:
7490 *params = attrib->divisor();
7491 break;
7492 default:
7493 NOTREACHED();
7494 break;
7498 void GLES2DecoderImpl::DoGetTexParameterfv(
7499 GLenum target, GLenum pname, GLfloat* params) {
7500 InitTextureMaxAnisotropyIfNeeded(target, pname);
7501 glGetTexParameterfv(target, pname, params);
7504 void GLES2DecoderImpl::DoGetTexParameteriv(
7505 GLenum target, GLenum pname, GLint* params) {
7506 InitTextureMaxAnisotropyIfNeeded(target, pname);
7507 glGetTexParameteriv(target, pname, params);
7510 void GLES2DecoderImpl::InitTextureMaxAnisotropyIfNeeded(
7511 GLenum target, GLenum pname) {
7512 if (!workarounds().init_texture_max_anisotropy)
7513 return;
7514 if (pname != GL_TEXTURE_MAX_ANISOTROPY_EXT ||
7515 !validators_->texture_parameter.IsValid(pname)) {
7516 return;
7519 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
7520 &state_, target);
7521 if (!texture_ref) {
7522 LOCAL_SET_GL_ERROR(
7523 GL_INVALID_OPERATION,
7524 "glGetTexParamter{fi}v", "unknown texture for target");
7525 return;
7527 Texture* texture = texture_ref->texture();
7528 texture->InitTextureMaxAnisotropyIfNeeded(target);
7531 void GLES2DecoderImpl::DoGetVertexAttribfv(
7532 GLuint index, GLenum pname, GLfloat* params) {
7533 VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(index);
7534 if (!attrib) {
7535 LOCAL_SET_GL_ERROR(
7536 GL_INVALID_VALUE, "glGetVertexAttribfv", "index out of range");
7537 return;
7539 switch (pname) {
7540 case GL_CURRENT_VERTEX_ATTRIB: {
7541 const Vec4& value = state_.attrib_values[index];
7542 params[0] = value.v[0];
7543 params[1] = value.v[1];
7544 params[2] = value.v[2];
7545 params[3] = value.v[3];
7546 break;
7548 default: {
7549 GLint value = 0;
7550 GetVertexAttribHelper(attrib, pname, &value);
7551 *params = static_cast<GLfloat>(value);
7552 break;
7557 void GLES2DecoderImpl::DoGetVertexAttribiv(
7558 GLuint index, GLenum pname, GLint* params) {
7559 VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(index);
7560 if (!attrib) {
7561 LOCAL_SET_GL_ERROR(
7562 GL_INVALID_VALUE, "glGetVertexAttribiv", "index out of range");
7563 return;
7565 switch (pname) {
7566 case GL_CURRENT_VERTEX_ATTRIB: {
7567 const Vec4& value = state_.attrib_values[index];
7568 params[0] = static_cast<GLint>(value.v[0]);
7569 params[1] = static_cast<GLint>(value.v[1]);
7570 params[2] = static_cast<GLint>(value.v[2]);
7571 params[3] = static_cast<GLint>(value.v[3]);
7572 break;
7574 default:
7575 GetVertexAttribHelper(attrib, pname, params);
7576 break;
7580 bool GLES2DecoderImpl::SetVertexAttribValue(
7581 const char* function_name, GLuint index, const GLfloat* value) {
7582 if (index >= state_.attrib_values.size()) {
7583 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "index out of range");
7584 return false;
7586 Vec4& v = state_.attrib_values[index];
7587 v.v[0] = value[0];
7588 v.v[1] = value[1];
7589 v.v[2] = value[2];
7590 v.v[3] = value[3];
7591 return true;
7594 void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
7595 GLfloat v[4] = { v0, 0.0f, 0.0f, 1.0f, };
7596 if (SetVertexAttribValue("glVertexAttrib1f", index, v)) {
7597 glVertexAttrib1f(index, v0);
7601 void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
7602 GLfloat v[4] = { v0, v1, 0.0f, 1.0f, };
7603 if (SetVertexAttribValue("glVertexAttrib2f", index, v)) {
7604 glVertexAttrib2f(index, v0, v1);
7608 void GLES2DecoderImpl::DoVertexAttrib3f(
7609 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
7610 GLfloat v[4] = { v0, v1, v2, 1.0f, };
7611 if (SetVertexAttribValue("glVertexAttrib3f", index, v)) {
7612 glVertexAttrib3f(index, v0, v1, v2);
7616 void GLES2DecoderImpl::DoVertexAttrib4f(
7617 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
7618 GLfloat v[4] = { v0, v1, v2, v3, };
7619 if (SetVertexAttribValue("glVertexAttrib4f", index, v)) {
7620 glVertexAttrib4f(index, v0, v1, v2, v3);
7624 void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
7625 GLfloat t[4] = { v[0], 0.0f, 0.0f, 1.0f, };
7626 if (SetVertexAttribValue("glVertexAttrib1fv", index, t)) {
7627 glVertexAttrib1fv(index, v);
7631 void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
7632 GLfloat t[4] = { v[0], v[1], 0.0f, 1.0f, };
7633 if (SetVertexAttribValue("glVertexAttrib2fv", index, t)) {
7634 glVertexAttrib2fv(index, v);
7638 void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
7639 GLfloat t[4] = { v[0], v[1], v[2], 1.0f, };
7640 if (SetVertexAttribValue("glVertexAttrib3fv", index, t)) {
7641 glVertexAttrib3fv(index, v);
7645 void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
7646 if (SetVertexAttribValue("glVertexAttrib4fv", index, v)) {
7647 glVertexAttrib4fv(index, v);
7651 error::Error GLES2DecoderImpl::HandleVertexAttribIPointer(
7652 uint32 immediate_data_size,
7653 const void* cmd_data) {
7654 // TODO(zmo): Unsafe ES3 API, missing states update.
7655 if (!unsafe_es3_apis_enabled())
7656 return error::kUnknownCommand;
7657 const gles2::cmds::VertexAttribIPointer& c =
7658 *static_cast<const gles2::cmds::VertexAttribIPointer*>(cmd_data);
7659 GLuint indx = c.indx;
7660 GLint size = c.size;
7661 GLenum type = c.type;
7662 GLsizei stride = c.stride;
7663 GLsizei offset = c.offset;
7664 const void* ptr = reinterpret_cast<const void*>(offset);
7665 glVertexAttribIPointer(indx, size, type, stride, ptr);
7666 return error::kNoError;
7669 error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
7670 uint32 immediate_data_size,
7671 const void* cmd_data) {
7672 const gles2::cmds::VertexAttribPointer& c =
7673 *static_cast<const gles2::cmds::VertexAttribPointer*>(cmd_data);
7675 if (!state_.bound_array_buffer.get() ||
7676 state_.bound_array_buffer->IsDeleted()) {
7677 if (state_.vertex_attrib_manager.get() ==
7678 state_.default_vertex_attrib_manager.get()) {
7679 LOCAL_SET_GL_ERROR(
7680 GL_INVALID_VALUE, "glVertexAttribPointer", "no array buffer bound");
7681 return error::kNoError;
7682 } else if (c.offset != 0) {
7683 LOCAL_SET_GL_ERROR(
7684 GL_INVALID_VALUE,
7685 "glVertexAttribPointer", "client side arrays are not allowed");
7686 return error::kNoError;
7690 GLuint indx = c.indx;
7691 GLint size = c.size;
7692 GLenum type = c.type;
7693 GLboolean normalized = static_cast<GLboolean>(c.normalized);
7694 GLsizei stride = c.stride;
7695 GLsizei offset = c.offset;
7696 const void* ptr = reinterpret_cast<const void*>(offset);
7697 if (!validators_->vertex_attrib_type.IsValid(type)) {
7698 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribPointer", type, "type");
7699 return error::kNoError;
7701 if (!validators_->vertex_attrib_size.IsValid(size)) {
7702 LOCAL_SET_GL_ERROR(
7703 GL_INVALID_VALUE, "glVertexAttribPointer", "size GL_INVALID_VALUE");
7704 return error::kNoError;
7706 if (indx >= group_->max_vertex_attribs()) {
7707 LOCAL_SET_GL_ERROR(
7708 GL_INVALID_VALUE, "glVertexAttribPointer", "index out of range");
7709 return error::kNoError;
7711 if (stride < 0) {
7712 LOCAL_SET_GL_ERROR(
7713 GL_INVALID_VALUE, "glVertexAttribPointer", "stride < 0");
7714 return error::kNoError;
7716 if (stride > 255) {
7717 LOCAL_SET_GL_ERROR(
7718 GL_INVALID_VALUE, "glVertexAttribPointer", "stride > 255");
7719 return error::kNoError;
7721 if (offset < 0) {
7722 LOCAL_SET_GL_ERROR(
7723 GL_INVALID_VALUE, "glVertexAttribPointer", "offset < 0");
7724 return error::kNoError;
7726 GLsizei component_size =
7727 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
7728 // component_size must be a power of two to use & as optimized modulo.
7729 DCHECK(GLES2Util::IsPOT(component_size));
7730 if (offset & (component_size - 1)) {
7731 LOCAL_SET_GL_ERROR(
7732 GL_INVALID_OPERATION,
7733 "glVertexAttribPointer", "offset not valid for type");
7734 return error::kNoError;
7736 if (stride & (component_size - 1)) {
7737 LOCAL_SET_GL_ERROR(
7738 GL_INVALID_OPERATION,
7739 "glVertexAttribPointer", "stride not valid for type");
7740 return error::kNoError;
7742 state_.vertex_attrib_manager
7743 ->SetAttribInfo(indx,
7744 state_.bound_array_buffer.get(),
7745 size,
7746 type,
7747 normalized,
7748 stride,
7749 stride != 0 ? stride : component_size * size,
7750 offset);
7751 if (type != GL_FIXED) {
7752 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
7754 return error::kNoError;
7757 void GLES2DecoderImpl::DoViewport(GLint x, GLint y, GLsizei width,
7758 GLsizei height) {
7759 state_.viewport_x = x;
7760 state_.viewport_y = y;
7761 state_.viewport_width = std::min(width, viewport_max_width_);
7762 state_.viewport_height = std::min(height, viewport_max_height_);
7763 glViewport(x, y, width, height);
7766 error::Error GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
7767 uint32 immediate_data_size,
7768 const void* cmd_data) {
7769 const gles2::cmds::VertexAttribDivisorANGLE& c =
7770 *static_cast<const gles2::cmds::VertexAttribDivisorANGLE*>(cmd_data);
7771 if (!features().angle_instanced_arrays) {
7772 LOCAL_SET_GL_ERROR(
7773 GL_INVALID_OPERATION,
7774 "glVertexAttribDivisorANGLE", "function not available");
7775 return error::kNoError;
7777 GLuint index = c.index;
7778 GLuint divisor = c.divisor;
7779 if (index >= group_->max_vertex_attribs()) {
7780 LOCAL_SET_GL_ERROR(
7781 GL_INVALID_VALUE,
7782 "glVertexAttribDivisorANGLE", "index out of range");
7783 return error::kNoError;
7786 state_.vertex_attrib_manager->SetDivisor(
7787 index,
7788 divisor);
7789 glVertexAttribDivisorANGLE(index, divisor);
7790 return error::kNoError;
7793 template <typename pixel_data_type>
7794 static void WriteAlphaData(
7795 void* pixels, uint32 row_count, uint32 channel_count,
7796 uint32 alpha_channel_index, uint32 unpadded_row_size,
7797 uint32 padded_row_size, pixel_data_type alpha_value) {
7798 DCHECK_GT(channel_count, 0U);
7799 DCHECK_EQ(unpadded_row_size % sizeof(pixel_data_type), 0U);
7800 uint32 unpadded_row_size_in_elements =
7801 unpadded_row_size / sizeof(pixel_data_type);
7802 DCHECK_EQ(padded_row_size % sizeof(pixel_data_type), 0U);
7803 uint32 padded_row_size_in_elements =
7804 padded_row_size / sizeof(pixel_data_type);
7805 pixel_data_type* dst =
7806 static_cast<pixel_data_type*>(pixels) + alpha_channel_index;
7807 for (uint32 yy = 0; yy < row_count; ++yy) {
7808 pixel_data_type* end = dst + unpadded_row_size_in_elements;
7809 for (pixel_data_type* d = dst; d < end; d += channel_count) {
7810 *d = alpha_value;
7812 dst += padded_row_size_in_elements;
7816 void GLES2DecoderImpl::FinishReadPixels(
7817 const cmds::ReadPixels& c,
7818 GLuint buffer) {
7819 TRACE_EVENT0("gpu", "GLES2DecoderImpl::FinishReadPixels");
7820 GLsizei width = c.width;
7821 GLsizei height = c.height;
7822 GLenum format = c.format;
7823 GLenum type = c.type;
7824 typedef cmds::ReadPixels::Result Result;
7825 uint32 pixels_size;
7826 Result* result = NULL;
7827 if (c.result_shm_id != 0) {
7828 result = GetSharedMemoryAs<Result*>(
7829 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7830 if (!result) {
7831 if (buffer != 0) {
7832 glDeleteBuffersARB(1, &buffer);
7834 return;
7837 GLES2Util::ComputeImageDataSizes(
7838 width, height, 1, format, type, state_.pack_alignment, &pixels_size,
7839 NULL, NULL);
7840 void* pixels = GetSharedMemoryAs<void*>(
7841 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
7842 if (!pixels) {
7843 if (buffer != 0) {
7844 glDeleteBuffersARB(1, &buffer);
7846 return;
7849 if (buffer != 0) {
7850 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
7851 void* data;
7852 if (features().map_buffer_range) {
7853 data = glMapBufferRange(
7854 GL_PIXEL_PACK_BUFFER_ARB, 0, pixels_size, GL_MAP_READ_BIT);
7855 } else {
7856 data = glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
7858 if (!data) {
7859 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glMapBuffer",
7860 "Unable to map memory for readback.");
7861 return;
7863 memcpy(pixels, data, pixels_size);
7864 // GL_PIXEL_PACK_BUFFER_ARB is currently unused, so we don't
7865 // have to restore the state.
7866 glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB);
7867 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
7868 glDeleteBuffersARB(1, &buffer);
7871 if (result != NULL) {
7872 *result = true;
7875 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
7876 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
7877 if ((channels_exist & 0x0008) == 0 &&
7878 workarounds().clear_alpha_in_readpixels) {
7879 // Set the alpha to 255 because some drivers are buggy in this regard.
7880 uint32 temp_size;
7882 uint32 unpadded_row_size;
7883 uint32 padded_row_size;
7884 if (!GLES2Util::ComputeImageDataSizes(
7885 width, 2, 1, format, type, state_.pack_alignment, &temp_size,
7886 &unpadded_row_size, &padded_row_size)) {
7887 return;
7890 uint32 channel_count = 0;
7891 uint32 alpha_channel = 0;
7892 switch (format) {
7893 case GL_RGBA:
7894 case GL_BGRA_EXT:
7895 channel_count = 4;
7896 alpha_channel = 3;
7897 break;
7898 case GL_ALPHA:
7899 channel_count = 1;
7900 alpha_channel = 0;
7901 break;
7904 if (channel_count > 0) {
7905 switch (type) {
7906 case GL_UNSIGNED_BYTE:
7907 WriteAlphaData<uint8>(
7908 pixels, height, channel_count, alpha_channel, unpadded_row_size,
7909 padded_row_size, 0xFF);
7910 break;
7911 case GL_FLOAT:
7912 WriteAlphaData<float>(
7913 pixels, height, channel_count, alpha_channel, unpadded_row_size,
7914 padded_row_size, 1.0f);
7915 break;
7916 case GL_HALF_FLOAT:
7917 WriteAlphaData<uint16>(
7918 pixels, height, channel_count, alpha_channel, unpadded_row_size,
7919 padded_row_size, 0x3C00);
7920 break;
7926 error::Error GLES2DecoderImpl::HandleReadPixels(uint32 immediate_data_size,
7927 const void* cmd_data) {
7928 const gles2::cmds::ReadPixels& c =
7929 *static_cast<const gles2::cmds::ReadPixels*>(cmd_data);
7930 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleReadPixels");
7931 error::Error fbo_error = WillAccessBoundFramebufferForRead();
7932 if (fbo_error != error::kNoError)
7933 return fbo_error;
7934 GLint x = c.x;
7935 GLint y = c.y;
7936 GLsizei width = c.width;
7937 GLsizei height = c.height;
7938 GLenum format = c.format;
7939 GLenum type = c.type;
7940 GLboolean async = static_cast<GLboolean>(c.async);
7941 if (width < 0 || height < 0) {
7942 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glReadPixels", "dimensions < 0");
7943 return error::kNoError;
7945 typedef cmds::ReadPixels::Result Result;
7946 uint32 pixels_size;
7947 if (!GLES2Util::ComputeImageDataSizes(
7948 width, height, 1, format, type, state_.pack_alignment, &pixels_size,
7949 NULL, NULL)) {
7950 return error::kOutOfBounds;
7952 void* pixels = GetSharedMemoryAs<void*>(
7953 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
7954 if (!pixels) {
7955 return error::kOutOfBounds;
7957 Result* result = NULL;
7958 if (c.result_shm_id != 0) {
7959 result = GetSharedMemoryAs<Result*>(
7960 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7961 if (!result) {
7962 return error::kOutOfBounds;
7966 if (!validators_->read_pixel_format.IsValid(format)) {
7967 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", format, "format");
7968 return error::kNoError;
7970 if (!validators_->read_pixel_type.IsValid(type)) {
7971 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", type, "type");
7972 return error::kNoError;
7974 if ((format != GL_RGBA && format != GL_BGRA_EXT && format != GL_RGB &&
7975 format != GL_ALPHA) || type != GL_UNSIGNED_BYTE) {
7976 // format and type are acceptable enums but not guaranteed to be supported
7977 // for this framebuffer. Have to ask gl if they are valid.
7978 GLint preferred_format = 0;
7979 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &preferred_format);
7980 GLint preferred_type = 0;
7981 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &preferred_type);
7982 if (format != static_cast<GLenum>(preferred_format) ||
7983 type != static_cast<GLenum>(preferred_type)) {
7984 LOCAL_SET_GL_ERROR(
7985 GL_INVALID_OPERATION, "glReadPixels", "format and type incompatible "
7986 "with the current read framebuffer");
7987 return error::kNoError;
7990 if (width == 0 || height == 0) {
7991 return error::kNoError;
7994 // Get the size of the current fbo or backbuffer.
7995 gfx::Size max_size = GetBoundReadFrameBufferSize();
7997 int32 max_x;
7998 int32 max_y;
7999 if (!SafeAddInt32(x, width, &max_x) || !SafeAddInt32(y, height, &max_y)) {
8000 LOCAL_SET_GL_ERROR(
8001 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
8002 return error::kNoError;
8005 if (!CheckBoundReadFramebufferColorAttachment("glReadPixels")) {
8006 return error::kNoError;
8009 if (!CheckBoundFramebuffersValid("glReadPixels")) {
8010 return error::kNoError;
8013 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixels");
8015 ScopedResolvedFrameBufferBinder binder(this, false, true);
8017 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
8018 // The user requested an out of range area. Get the results 1 line
8019 // at a time.
8020 uint32 temp_size;
8021 uint32 unpadded_row_size;
8022 uint32 padded_row_size;
8023 if (!GLES2Util::ComputeImageDataSizes(
8024 width, 2, 1, format, type, state_.pack_alignment, &temp_size,
8025 &unpadded_row_size, &padded_row_size)) {
8026 LOCAL_SET_GL_ERROR(
8027 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
8028 return error::kNoError;
8031 GLint dest_x_offset = std::max(-x, 0);
8032 uint32 dest_row_offset;
8033 if (!GLES2Util::ComputeImageDataSizes(
8034 dest_x_offset, 1, 1, format, type, state_.pack_alignment,
8035 &dest_row_offset, NULL, NULL)) {
8036 LOCAL_SET_GL_ERROR(
8037 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
8038 return error::kNoError;
8041 // Copy each row into the larger dest rect.
8042 int8* dst = static_cast<int8*>(pixels);
8043 GLint read_x = std::max(0, x);
8044 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
8045 GLint read_width = read_end_x - read_x;
8046 for (GLint yy = 0; yy < height; ++yy) {
8047 GLint ry = y + yy;
8049 // Clear the row.
8050 memset(dst, 0, unpadded_row_size);
8052 // If the row is in range, copy it.
8053 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
8054 glReadPixels(
8055 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
8057 dst += padded_row_size;
8059 } else {
8060 if (async && features().use_async_readpixels) {
8061 GLuint buffer = 0;
8062 glGenBuffersARB(1, &buffer);
8063 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
8064 // For ANGLE client version 2, GL_STREAM_READ is not available.
8065 const GLenum usage_hint = feature_info_->gl_version_info().is_angle ?
8066 GL_STATIC_DRAW : GL_STREAM_READ;
8067 glBufferData(GL_PIXEL_PACK_BUFFER_ARB, pixels_size, NULL, usage_hint);
8068 GLenum error = glGetError();
8069 if (error == GL_NO_ERROR) {
8070 glReadPixels(x, y, width, height, format, type, 0);
8071 pending_readpixel_fences_.push(linked_ptr<FenceCallback>(
8072 new FenceCallback()));
8073 WaitForReadPixels(base::Bind(
8074 &GLES2DecoderImpl::FinishReadPixels,
8075 base::internal::SupportsWeakPtrBase::StaticAsWeakPtr
8076 <GLES2DecoderImpl>(this),
8077 c, buffer));
8078 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
8079 return error::kNoError;
8080 } else {
8081 // On error, unbind pack buffer and fall through to sync readpixels
8082 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
8083 glDeleteBuffersARB(1, &buffer);
8086 glReadPixels(x, y, width, height, format, type, pixels);
8088 GLenum error = LOCAL_PEEK_GL_ERROR("glReadPixels");
8089 if (error == GL_NO_ERROR) {
8090 if (result != NULL) {
8091 *result = true;
8093 FinishReadPixels(c, 0);
8096 return error::kNoError;
8099 error::Error GLES2DecoderImpl::HandlePixelStorei(uint32 immediate_data_size,
8100 const void* cmd_data) {
8101 const gles2::cmds::PixelStorei& c =
8102 *static_cast<const gles2::cmds::PixelStorei*>(cmd_data);
8103 GLenum pname = c.pname;
8104 GLenum param = c.param;
8105 if (!validators_->pixel_store.IsValid(pname)) {
8106 LOCAL_SET_GL_ERROR_INVALID_ENUM("glPixelStorei", pname, "pname");
8107 return error::kNoError;
8109 switch (pname) {
8110 case GL_PACK_ALIGNMENT:
8111 case GL_UNPACK_ALIGNMENT:
8112 if (!validators_->pixel_store_alignment.IsValid(param)) {
8113 LOCAL_SET_GL_ERROR(
8114 GL_INVALID_VALUE, "glPixelStorei", "param GL_INVALID_VALUE");
8115 return error::kNoError;
8117 break;
8118 case GL_UNPACK_FLIP_Y_CHROMIUM:
8119 unpack_flip_y_ = (param != 0);
8120 return error::kNoError;
8121 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
8122 unpack_premultiply_alpha_ = (param != 0);
8123 return error::kNoError;
8124 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM:
8125 unpack_unpremultiply_alpha_ = (param != 0);
8126 return error::kNoError;
8127 default:
8128 break;
8130 glPixelStorei(pname, param);
8131 switch (pname) {
8132 case GL_PACK_ALIGNMENT:
8133 state_.pack_alignment = param;
8134 break;
8135 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
8136 state_.pack_reverse_row_order = (param != 0);
8137 break;
8138 case GL_UNPACK_ALIGNMENT:
8139 state_.unpack_alignment = param;
8140 break;
8141 default:
8142 // Validation should have prevented us from getting here.
8143 NOTREACHED();
8144 break;
8146 return error::kNoError;
8149 error::Error GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
8150 uint32 immediate_data_size,
8151 const void* cmd_data) {
8152 const gles2::cmds::PostSubBufferCHROMIUM& c =
8153 *static_cast<const gles2::cmds::PostSubBufferCHROMIUM*>(cmd_data);
8154 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
8156 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
8158 if (!supports_post_sub_buffer_) {
8159 LOCAL_SET_GL_ERROR(
8160 GL_INVALID_OPERATION,
8161 "glPostSubBufferCHROMIUM", "command not supported by surface");
8162 return error::kNoError;
8164 bool is_tracing;
8165 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
8166 &is_tracing);
8167 if (is_tracing) {
8168 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
8169 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
8170 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
8171 is_offscreen ? offscreen_size_ : surface_->GetSize());
8173 if (surface_->PostSubBuffer(c.x, c.y, c.width, c.height)) {
8174 return error::kNoError;
8175 } else {
8176 LOG(ERROR) << "Context lost because PostSubBuffer failed.";
8177 return error::kLostContext;
8181 error::Error GLES2DecoderImpl::HandleScheduleOverlayPlaneCHROMIUM(
8182 uint32 immediate_data_size,
8183 const void* cmd_data) {
8184 const gles2::cmds::ScheduleOverlayPlaneCHROMIUM& c =
8185 *static_cast<const gles2::cmds::ScheduleOverlayPlaneCHROMIUM*>(cmd_data);
8186 TextureRef* ref = texture_manager()->GetTexture(c.overlay_texture_id);
8187 if (!ref) {
8188 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
8189 "glScheduleOverlayPlaneCHROMIUM",
8190 "unknown texture");
8191 return error::kNoError;
8193 gfx::GLImage* image =
8194 ref->texture()->GetLevelImage(ref->texture()->target(), 0);
8195 if (!image) {
8196 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
8197 "glScheduleOverlayPlaneCHROMIUM",
8198 "unsupported texture format");
8199 return error::kNoError;
8201 gfx::OverlayTransform transform = GetGFXOverlayTransform(c.plane_transform);
8202 if (transform == gfx::OVERLAY_TRANSFORM_INVALID) {
8203 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM,
8204 "glScheduleOverlayPlaneCHROMIUM",
8205 "invalid transform enum");
8206 return error::kNoError;
8208 if (!surface_->ScheduleOverlayPlane(
8209 c.plane_z_order,
8210 transform,
8211 image,
8212 gfx::Rect(c.bounds_x, c.bounds_y, c.bounds_width, c.bounds_height),
8213 gfx::RectF(c.uv_x, c.uv_y, c.uv_width, c.uv_height))) {
8214 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
8215 "glScheduleOverlayPlaneCHROMIUM",
8216 "failed to schedule overlay");
8218 return error::kNoError;
8221 error::Error GLES2DecoderImpl::GetAttribLocationHelper(
8222 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
8223 const std::string& name_str) {
8224 if (!StringIsValidForGLES(name_str.c_str())) {
8225 LOCAL_SET_GL_ERROR(
8226 GL_INVALID_VALUE, "glGetAttribLocation", "Invalid character");
8227 return error::kNoError;
8229 Program* program = GetProgramInfoNotShader(
8230 client_id, "glGetAttribLocation");
8231 if (!program) {
8232 return error::kNoError;
8234 if (!program->IsValid()) {
8235 LOCAL_SET_GL_ERROR(
8236 GL_INVALID_OPERATION, "glGetAttribLocation", "program not linked");
8237 return error::kNoError;
8239 GLint* location = GetSharedMemoryAs<GLint*>(
8240 location_shm_id, location_shm_offset, sizeof(GLint));
8241 if (!location) {
8242 return error::kOutOfBounds;
8244 // Require the client to init this incase the context is lost and we are no
8245 // longer executing commands.
8246 if (*location != -1) {
8247 return error::kGenericError;
8249 *location = program->GetAttribLocation(name_str);
8250 return error::kNoError;
8253 error::Error GLES2DecoderImpl::HandleGetAttribLocation(
8254 uint32 immediate_data_size,
8255 const void* cmd_data) {
8256 const gles2::cmds::GetAttribLocation& c =
8257 *static_cast<const gles2::cmds::GetAttribLocation*>(cmd_data);
8258 Bucket* bucket = GetBucket(c.name_bucket_id);
8259 if (!bucket) {
8260 return error::kInvalidArguments;
8262 std::string name_str;
8263 if (!bucket->GetAsString(&name_str)) {
8264 return error::kInvalidArguments;
8266 return GetAttribLocationHelper(
8267 c.program, c.location_shm_id, c.location_shm_offset, name_str);
8270 error::Error GLES2DecoderImpl::GetUniformLocationHelper(
8271 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
8272 const std::string& name_str) {
8273 if (!StringIsValidForGLES(name_str.c_str())) {
8274 LOCAL_SET_GL_ERROR(
8275 GL_INVALID_VALUE, "glGetUniformLocation", "Invalid character");
8276 return error::kNoError;
8278 Program* program = GetProgramInfoNotShader(
8279 client_id, "glGetUniformLocation");
8280 if (!program) {
8281 return error::kNoError;
8283 if (!program->IsValid()) {
8284 LOCAL_SET_GL_ERROR(
8285 GL_INVALID_OPERATION, "glGetUniformLocation", "program not linked");
8286 return error::kNoError;
8288 GLint* location = GetSharedMemoryAs<GLint*>(
8289 location_shm_id, location_shm_offset, sizeof(GLint));
8290 if (!location) {
8291 return error::kOutOfBounds;
8293 // Require the client to init this incase the context is lost an we are no
8294 // longer executing commands.
8295 if (*location != -1) {
8296 return error::kGenericError;
8298 *location = program->GetUniformFakeLocation(name_str);
8299 return error::kNoError;
8302 error::Error GLES2DecoderImpl::HandleGetUniformLocation(
8303 uint32 immediate_data_size,
8304 const void* cmd_data) {
8305 const gles2::cmds::GetUniformLocation& c =
8306 *static_cast<const gles2::cmds::GetUniformLocation*>(cmd_data);
8307 Bucket* bucket = GetBucket(c.name_bucket_id);
8308 if (!bucket) {
8309 return error::kInvalidArguments;
8311 std::string name_str;
8312 if (!bucket->GetAsString(&name_str)) {
8313 return error::kInvalidArguments;
8315 return GetUniformLocationHelper(
8316 c.program, c.location_shm_id, c.location_shm_offset, name_str);
8319 error::Error GLES2DecoderImpl::HandleGetUniformIndices(
8320 uint32 immediate_data_size,
8321 const void* cmd_data) {
8322 if (!unsafe_es3_apis_enabled())
8323 return error::kUnknownCommand;
8324 const gles2::cmds::GetUniformIndices& c =
8325 *static_cast<const gles2::cmds::GetUniformIndices*>(cmd_data);
8326 Bucket* bucket = GetBucket(c.names_bucket_id);
8327 if (!bucket) {
8328 return error::kInvalidArguments;
8330 GLsizei count = 0;
8331 std::vector<char*> names;
8332 std::vector<GLint> len;
8333 if (!bucket->GetAsStrings(&count, &names, &len) || count <= 0) {
8334 return error::kInvalidArguments;
8336 typedef cmds::GetUniformIndices::Result Result;
8337 Result* result = GetSharedMemoryAs<Result*>(
8338 c.indices_shm_id, c.indices_shm_offset,
8339 Result::ComputeSize(static_cast<size_t>(count)));
8340 GLuint* indices = result ? result->GetData() : NULL;
8341 if (indices == NULL) {
8342 return error::kOutOfBounds;
8344 // Check that the client initialized the result.
8345 if (result->size != 0) {
8346 return error::kInvalidArguments;
8348 Program* program = GetProgramInfoNotShader(c.program, "glGetUniformIndices");
8349 if (!program) {
8350 return error::kNoError;
8352 GLuint service_id = program->service_id();
8353 GLint link_status = GL_FALSE;
8354 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
8355 if (link_status != GL_TRUE) {
8356 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
8357 "glGetUniformIndices", "program not linked");
8358 return error::kNoError;
8360 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetUniformIndices");
8361 glGetUniformIndices(service_id, count, &names[0], indices);
8362 GLenum error = glGetError();
8363 if (error == GL_NO_ERROR) {
8364 result->SetNumResults(count);
8365 } else {
8366 LOCAL_SET_GL_ERROR(error, "GetUniformIndices", "");
8368 return error::kNoError;
8371 error::Error GLES2DecoderImpl::GetFragDataLocationHelper(
8372 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
8373 const std::string& name_str) {
8374 GLint* location = GetSharedMemoryAs<GLint*>(
8375 location_shm_id, location_shm_offset, sizeof(GLint));
8376 if (!location) {
8377 return error::kOutOfBounds;
8379 // Require the client to init this incase the context is lost and we are no
8380 // longer executing commands.
8381 if (*location != -1) {
8382 return error::kGenericError;
8384 Program* program = GetProgramInfoNotShader(
8385 client_id, "glGetFragDataLocation");
8386 if (!program) {
8387 return error::kNoError;
8389 *location = glGetFragDataLocation(program->service_id(), name_str.c_str());
8390 return error::kNoError;
8393 error::Error GLES2DecoderImpl::HandleGetFragDataLocation(
8394 uint32 immediate_data_size,
8395 const void* cmd_data) {
8396 if (!unsafe_es3_apis_enabled())
8397 return error::kUnknownCommand;
8398 const gles2::cmds::GetFragDataLocation& c =
8399 *static_cast<const gles2::cmds::GetFragDataLocation*>(cmd_data);
8400 Bucket* bucket = GetBucket(c.name_bucket_id);
8401 if (!bucket) {
8402 return error::kInvalidArguments;
8404 std::string name_str;
8405 if (!bucket->GetAsString(&name_str)) {
8406 return error::kInvalidArguments;
8408 return GetFragDataLocationHelper(
8409 c.program, c.location_shm_id, c.location_shm_offset, name_str);
8412 error::Error GLES2DecoderImpl::HandleGetUniformBlockIndex(
8413 uint32 immediate_data_size, const void* cmd_data) {
8414 if (!unsafe_es3_apis_enabled())
8415 return error::kUnknownCommand;
8416 const gles2::cmds::GetUniformBlockIndex& c =
8417 *static_cast<const gles2::cmds::GetUniformBlockIndex*>(cmd_data);
8418 Bucket* bucket = GetBucket(c.name_bucket_id);
8419 if (!bucket) {
8420 return error::kInvalidArguments;
8422 std::string name_str;
8423 if (!bucket->GetAsString(&name_str)) {
8424 return error::kInvalidArguments;
8426 GLuint* index = GetSharedMemoryAs<GLuint*>(
8427 c.index_shm_id, c.index_shm_offset, sizeof(GLuint));
8428 if (!index) {
8429 return error::kOutOfBounds;
8431 // Require the client to init this in case the context is lost and we are no
8432 // longer executing commands.
8433 if (*index != GL_INVALID_INDEX) {
8434 return error::kGenericError;
8436 Program* program = GetProgramInfoNotShader(
8437 c.program, "glGetUniformBlockIndex");
8438 if (!program) {
8439 return error::kNoError;
8441 *index = glGetUniformBlockIndex(program->service_id(), name_str.c_str());
8442 return error::kNoError;
8445 error::Error GLES2DecoderImpl::HandleGetString(uint32 immediate_data_size,
8446 const void* cmd_data) {
8447 const gles2::cmds::GetString& c =
8448 *static_cast<const gles2::cmds::GetString*>(cmd_data);
8449 GLenum name = static_cast<GLenum>(c.name);
8450 if (!validators_->string_type.IsValid(name)) {
8451 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetString", name, "name");
8452 return error::kNoError;
8455 const char* str = nullptr;
8456 std::string extensions;
8457 switch (name) {
8458 case GL_VERSION:
8459 str = "OpenGL ES 2.0 Chromium";
8460 break;
8461 case GL_SHADING_LANGUAGE_VERSION:
8462 str = "OpenGL ES GLSL ES 1.0 Chromium";
8463 break;
8464 case GL_RENDERER:
8465 case GL_VENDOR:
8466 // Return the unmasked VENDOR/RENDERER string for WebGL contexts.
8467 // They are used by WEBGL_debug_renderer_info.
8468 if (!force_webgl_glsl_validation_)
8469 str = "Chromium";
8470 else
8471 str = reinterpret_cast<const char*>(glGetString(name));
8472 break;
8473 case GL_EXTENSIONS:
8475 // For WebGL contexts, strip out the OES derivatives and
8476 // EXT frag depth extensions if they have not been enabled.
8477 if (force_webgl_glsl_validation_) {
8478 extensions = feature_info_->extensions();
8479 if (!derivatives_explicitly_enabled_) {
8480 size_t offset = extensions.find(kOESDerivativeExtension);
8481 if (std::string::npos != offset) {
8482 extensions.replace(offset, arraysize(kOESDerivativeExtension),
8483 std::string());
8486 if (!frag_depth_explicitly_enabled_) {
8487 size_t offset = extensions.find(kEXTFragDepthExtension);
8488 if (std::string::npos != offset) {
8489 extensions.replace(offset, arraysize(kEXTFragDepthExtension),
8490 std::string());
8493 if (!draw_buffers_explicitly_enabled_) {
8494 size_t offset = extensions.find(kEXTDrawBuffersExtension);
8495 if (std::string::npos != offset) {
8496 extensions.replace(offset, arraysize(kEXTDrawBuffersExtension),
8497 std::string());
8500 if (!shader_texture_lod_explicitly_enabled_) {
8501 size_t offset = extensions.find(kEXTShaderTextureLodExtension);
8502 if (std::string::npos != offset) {
8503 extensions.replace(offset,
8504 arraysize(kEXTShaderTextureLodExtension),
8505 std::string());
8508 } else {
8509 extensions = feature_info_->extensions().c_str();
8511 if (supports_post_sub_buffer_)
8512 extensions += " GL_CHROMIUM_post_sub_buffer";
8513 str = extensions.c_str();
8515 break;
8516 default:
8517 str = reinterpret_cast<const char*>(glGetString(name));
8518 break;
8520 Bucket* bucket = CreateBucket(c.bucket_id);
8521 bucket->SetFromString(str);
8522 return error::kNoError;
8525 error::Error GLES2DecoderImpl::HandleBufferData(uint32 immediate_data_size,
8526 const void* cmd_data) {
8527 const gles2::cmds::BufferData& c =
8528 *static_cast<const gles2::cmds::BufferData*>(cmd_data);
8529 GLenum target = static_cast<GLenum>(c.target);
8530 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
8531 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
8532 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
8533 GLenum usage = static_cast<GLenum>(c.usage);
8534 const void* data = NULL;
8535 if (data_shm_id != 0 || data_shm_offset != 0) {
8536 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
8537 if (!data) {
8538 return error::kOutOfBounds;
8541 buffer_manager()->ValidateAndDoBufferData(&state_, target, size, data, usage);
8542 return error::kNoError;
8545 void GLES2DecoderImpl::DoBufferSubData(
8546 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
8547 // Just delegate it. Some validation is actually done before this.
8548 buffer_manager()->ValidateAndDoBufferSubData(
8549 &state_, target, offset, size, data);
8552 bool GLES2DecoderImpl::ClearLevel(
8553 Texture* texture,
8554 unsigned target,
8555 int level,
8556 unsigned internal_format,
8557 unsigned format,
8558 unsigned type,
8559 int width,
8560 int height,
8561 bool is_texture_immutable) {
8562 uint32 channels = GLES2Util::GetChannelsForFormat(format);
8563 if (feature_info_->feature_flags().angle_depth_texture &&
8564 (channels & GLES2Util::kDepth) != 0) {
8565 // It's a depth format and ANGLE doesn't allow texImage2D or texSubImage2D
8566 // on depth formats.
8567 GLuint fb = 0;
8568 glGenFramebuffersEXT(1, &fb);
8569 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb);
8571 bool have_stencil = (channels & GLES2Util::kStencil) != 0;
8572 GLenum attachment = have_stencil ? GL_DEPTH_STENCIL_ATTACHMENT :
8573 GL_DEPTH_ATTACHMENT;
8575 glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, attachment, target,
8576 texture->service_id(), level);
8577 // ANGLE promises a depth only attachment ok.
8578 if (glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT) !=
8579 GL_FRAMEBUFFER_COMPLETE) {
8580 return false;
8582 glClearStencil(0);
8583 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
8584 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
8585 glClearDepth(1.0f);
8586 state_.SetDeviceDepthMask(GL_TRUE);
8587 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
8588 glClear(GL_DEPTH_BUFFER_BIT | (have_stencil ? GL_STENCIL_BUFFER_BIT : 0));
8590 RestoreClearState();
8592 glDeleteFramebuffersEXT(1, &fb);
8593 Framebuffer* framebuffer =
8594 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
8595 GLuint fb_service_id =
8596 framebuffer ? framebuffer->service_id() : GetBackbufferServiceId();
8597 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb_service_id);
8598 return true;
8601 static const uint32 kMaxZeroSize = 1024 * 1024 * 4;
8603 uint32 size;
8604 uint32 padded_row_size;
8605 if (!GLES2Util::ComputeImageDataSizes(
8606 width, height, 1, format, type, state_.unpack_alignment, &size,
8607 NULL, &padded_row_size)) {
8608 return false;
8611 TRACE_EVENT1("gpu", "GLES2DecoderImpl::ClearLevel", "size", size);
8613 int tile_height;
8615 if (size > kMaxZeroSize) {
8616 if (kMaxZeroSize < padded_row_size) {
8617 // That'd be an awfully large texture.
8618 return false;
8620 // We should never have a large total size with a zero row size.
8621 DCHECK_GT(padded_row_size, 0U);
8622 tile_height = kMaxZeroSize / padded_row_size;
8623 if (!GLES2Util::ComputeImageDataSizes(
8624 width, tile_height, 1, format, type, state_.unpack_alignment, &size,
8625 NULL, NULL)) {
8626 return false;
8628 } else {
8629 tile_height = height;
8632 // Assumes the size has already been checked.
8633 scoped_ptr<char[]> zero(new char[size]);
8634 memset(zero.get(), 0, size);
8635 glBindTexture(texture->target(), texture->service_id());
8637 bool has_images = texture->HasImages();
8638 GLint y = 0;
8639 while (y < height) {
8640 GLint h = y + tile_height > height ? height - y : tile_height;
8641 if (is_texture_immutable || h != height || has_images) {
8642 glTexSubImage2D(target, level, 0, y, width, h, format, type, zero.get());
8643 } else {
8644 glTexImage2D(
8645 target, level, internal_format, width, h, 0, format, type,
8646 zero.get());
8648 y += tile_height;
8650 TextureRef* bound_texture =
8651 texture_manager()->GetTextureInfoForTarget(&state_, texture->target());
8652 glBindTexture(texture->target(),
8653 bound_texture ? bound_texture->service_id() : 0);
8654 return true;
8657 namespace {
8659 const int kS3TCBlockWidth = 4;
8660 const int kS3TCBlockHeight = 4;
8661 const int kS3TCDXT1BlockSize = 8;
8662 const int kS3TCDXT3AndDXT5BlockSize = 16;
8664 bool IsValidDXTSize(GLint level, GLsizei size) {
8665 return (size == 1) ||
8666 (size == 2) || !(size % kS3TCBlockWidth);
8669 bool IsValidPVRTCSize(GLint level, GLsizei size) {
8670 return GLES2Util::IsPOT(size);
8673 } // anonymous namespace.
8675 bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
8676 const char* function_name,
8677 GLsizei width, GLsizei height, GLenum format, size_t size) {
8678 unsigned int bytes_required = 0;
8680 switch (format) {
8681 case GL_ATC_RGB_AMD:
8682 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
8683 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
8684 case GL_ETC1_RGB8_OES: {
8685 int num_blocks_across =
8686 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
8687 int num_blocks_down =
8688 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
8689 int num_blocks = num_blocks_across * num_blocks_down;
8690 bytes_required = num_blocks * kS3TCDXT1BlockSize;
8691 break;
8693 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
8694 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
8695 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
8696 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
8697 int num_blocks_across =
8698 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
8699 int num_blocks_down =
8700 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
8701 int num_blocks = num_blocks_across * num_blocks_down;
8702 bytes_required = num_blocks * kS3TCDXT3AndDXT5BlockSize;
8703 break;
8705 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
8706 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG: {
8707 bytes_required = (std::max(width, 8) * std::max(height, 8) * 4 + 7)/8;
8708 break;
8710 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
8711 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
8712 bytes_required = (std::max(width, 16) * std::max(height, 8) * 2 + 7)/8;
8713 break;
8715 default:
8716 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, format, "format");
8717 return false;
8720 if (size != bytes_required) {
8721 LOCAL_SET_GL_ERROR(
8722 GL_INVALID_VALUE, function_name, "size is not correct for dimensions");
8723 return false;
8726 return true;
8729 bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
8730 const char* function_name,
8731 GLint level, GLsizei width, GLsizei height, GLenum format) {
8732 switch (format) {
8733 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
8734 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
8735 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
8736 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
8737 if (!IsValidDXTSize(level, width) || !IsValidDXTSize(level, height)) {
8738 LOCAL_SET_GL_ERROR(
8739 GL_INVALID_OPERATION, function_name,
8740 "width or height invalid for level");
8741 return false;
8743 return true;
8745 case GL_ATC_RGB_AMD:
8746 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
8747 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
8748 case GL_ETC1_RGB8_OES: {
8749 if (width <= 0 || height <= 0) {
8750 LOCAL_SET_GL_ERROR(
8751 GL_INVALID_OPERATION, function_name,
8752 "width or height invalid for level");
8753 return false;
8755 return true;
8757 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
8758 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
8759 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
8760 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
8761 if (!IsValidPVRTCSize(level, width) ||
8762 !IsValidPVRTCSize(level, height)) {
8763 LOCAL_SET_GL_ERROR(
8764 GL_INVALID_OPERATION, function_name,
8765 "width or height invalid for level");
8766 return false;
8768 return true;
8770 default:
8771 return false;
8775 bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
8776 const char* function_name,
8777 GLenum target, GLint level, GLint xoffset, GLint yoffset,
8778 GLsizei width, GLsizei height, GLenum format,
8779 Texture* texture) {
8780 if (xoffset < 0 || yoffset < 0) {
8781 LOCAL_SET_GL_ERROR(
8782 GL_INVALID_VALUE, function_name, "xoffset or yoffset < 0");
8783 return false;
8786 switch (format) {
8787 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
8788 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
8789 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
8790 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
8791 const int kBlockWidth = 4;
8792 const int kBlockHeight = 4;
8793 if ((xoffset % kBlockWidth) || (yoffset % kBlockHeight)) {
8794 LOCAL_SET_GL_ERROR(
8795 GL_INVALID_OPERATION, function_name,
8796 "xoffset or yoffset not multiple of 4");
8797 return false;
8799 GLsizei tex_width = 0;
8800 GLsizei tex_height = 0;
8801 if (!texture->GetLevelSize(target, level, &tex_width, &tex_height) ||
8802 width - xoffset > tex_width ||
8803 height - yoffset > tex_height) {
8804 LOCAL_SET_GL_ERROR(
8805 GL_INVALID_OPERATION, function_name, "dimensions out of range");
8806 return false;
8808 return ValidateCompressedTexDimensions(
8809 function_name, level, width, height, format);
8811 case GL_ATC_RGB_AMD:
8812 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
8813 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD: {
8814 LOCAL_SET_GL_ERROR(
8815 GL_INVALID_OPERATION, function_name,
8816 "not supported for ATC textures");
8817 return false;
8819 case GL_ETC1_RGB8_OES: {
8820 LOCAL_SET_GL_ERROR(
8821 GL_INVALID_OPERATION, function_name,
8822 "not supported for ECT1_RGB8_OES textures");
8823 return false;
8825 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
8826 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
8827 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
8828 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
8829 if ((xoffset != 0) || (yoffset != 0)) {
8830 LOCAL_SET_GL_ERROR(
8831 GL_INVALID_OPERATION, function_name,
8832 "xoffset and yoffset must be zero");
8833 return false;
8835 GLsizei tex_width = 0;
8836 GLsizei tex_height = 0;
8837 if (!texture->GetLevelSize(target, level, &tex_width, &tex_height) ||
8838 width != tex_width ||
8839 height != tex_height) {
8840 LOCAL_SET_GL_ERROR(
8841 GL_INVALID_OPERATION, function_name,
8842 "dimensions must match existing texture level dimensions");
8843 return false;
8845 return ValidateCompressedTexDimensions(
8846 function_name, level, width, height, format);
8848 default:
8849 return false;
8853 error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
8854 GLenum target,
8855 GLint level,
8856 GLenum internal_format,
8857 GLsizei width,
8858 GLsizei height,
8859 GLint border,
8860 GLsizei image_size,
8861 const void* data) {
8862 // TODO(gman): Validate image_size is correct for width, height and format.
8863 if (!validators_->texture_target.IsValid(target)) {
8864 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8865 "glCompressedTexImage2D", target, "target");
8866 return error::kNoError;
8868 if (!validators_->compressed_texture_format.IsValid(
8869 internal_format)) {
8870 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8871 "glCompressedTexImage2D", internal_format, "internal_format");
8872 return error::kNoError;
8874 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
8875 border != 0) {
8876 LOCAL_SET_GL_ERROR(
8877 GL_INVALID_VALUE,
8878 "glCompressedTexImage2D", "dimensions out of range");
8879 return error::kNoError;
8881 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8882 &state_, target);
8883 if (!texture_ref) {
8884 LOCAL_SET_GL_ERROR(
8885 GL_INVALID_VALUE,
8886 "glCompressedTexImage2D", "unknown texture target");
8887 return error::kNoError;
8889 Texture* texture = texture_ref->texture();
8890 if (texture->IsImmutable()) {
8891 LOCAL_SET_GL_ERROR(
8892 GL_INVALID_OPERATION,
8893 "glCompressedTexImage2D", "texture is immutable");
8894 return error::kNoError;
8897 if (!ValidateCompressedTexDimensions(
8898 "glCompressedTexImage2D", level, width, height, internal_format) ||
8899 !ValidateCompressedTexFuncData(
8900 "glCompressedTexImage2D", width, height, internal_format, image_size)) {
8901 return error::kNoError;
8904 if (!EnsureGPUMemoryAvailable(image_size)) {
8905 LOCAL_SET_GL_ERROR(
8906 GL_OUT_OF_MEMORY, "glCompressedTexImage2D", "out of memory");
8907 return error::kNoError;
8910 if (texture->IsAttachedToFramebuffer()) {
8911 framebuffer_state_.clear_state_dirty = true;
8914 scoped_ptr<int8[]> zero;
8915 if (!data) {
8916 zero.reset(new int8[image_size]);
8917 memset(zero.get(), 0, image_size);
8918 data = zero.get();
8920 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage2D");
8921 glCompressedTexImage2D(
8922 target, level, internal_format, width, height, border, image_size, data);
8923 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedTexImage2D");
8924 if (error == GL_NO_ERROR) {
8925 texture_manager()->SetLevelInfo(
8926 texture_ref, target, level, internal_format,
8927 width, height, 1, border, 0, 0, true);
8930 // This may be a slow command. Exit command processing to allow for
8931 // context preemption and GPU watchdog checks.
8932 ExitCommandProcessingEarly();
8933 return error::kNoError;
8936 error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
8937 uint32 immediate_data_size,
8938 const void* cmd_data) {
8939 const gles2::cmds::CompressedTexImage2D& c =
8940 *static_cast<const gles2::cmds::CompressedTexImage2D*>(cmd_data);
8941 GLenum target = static_cast<GLenum>(c.target);
8942 GLint level = static_cast<GLint>(c.level);
8943 GLenum internal_format = static_cast<GLenum>(c.internalformat);
8944 GLsizei width = static_cast<GLsizei>(c.width);
8945 GLsizei height = static_cast<GLsizei>(c.height);
8946 GLint border = static_cast<GLint>(c.border);
8947 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
8948 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
8949 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
8950 const void* data = NULL;
8951 if (data_shm_id != 0 || data_shm_offset != 0) {
8952 data = GetSharedMemoryAs<const void*>(
8953 data_shm_id, data_shm_offset, image_size);
8954 if (!data) {
8955 return error::kOutOfBounds;
8958 return DoCompressedTexImage2D(
8959 target, level, internal_format, width, height, border, image_size, data);
8962 error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
8963 uint32 immediate_data_size,
8964 const void* cmd_data) {
8965 const gles2::cmds::CompressedTexImage2DBucket& c =
8966 *static_cast<const gles2::cmds::CompressedTexImage2DBucket*>(cmd_data);
8967 GLenum target = static_cast<GLenum>(c.target);
8968 GLint level = static_cast<GLint>(c.level);
8969 GLenum internal_format = static_cast<GLenum>(c.internalformat);
8970 GLsizei width = static_cast<GLsizei>(c.width);
8971 GLsizei height = static_cast<GLsizei>(c.height);
8972 GLint border = static_cast<GLint>(c.border);
8973 Bucket* bucket = GetBucket(c.bucket_id);
8974 if (!bucket) {
8975 return error::kInvalidArguments;
8977 uint32 data_size = bucket->size();
8978 GLsizei imageSize = data_size;
8979 const void* data = bucket->GetData(0, data_size);
8980 if (!data) {
8981 return error::kInvalidArguments;
8983 return DoCompressedTexImage2D(
8984 target, level, internal_format, width, height, border,
8985 imageSize, data);
8988 error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
8989 uint32 immediate_data_size,
8990 const void* cmd_data) {
8991 const gles2::cmds::CompressedTexSubImage2DBucket& c =
8992 *static_cast<const gles2::cmds::CompressedTexSubImage2DBucket*>(cmd_data);
8993 GLenum target = static_cast<GLenum>(c.target);
8994 GLint level = static_cast<GLint>(c.level);
8995 GLint xoffset = static_cast<GLint>(c.xoffset);
8996 GLint yoffset = static_cast<GLint>(c.yoffset);
8997 GLsizei width = static_cast<GLsizei>(c.width);
8998 GLsizei height = static_cast<GLsizei>(c.height);
8999 GLenum format = static_cast<GLenum>(c.format);
9000 Bucket* bucket = GetBucket(c.bucket_id);
9001 if (!bucket) {
9002 return error::kInvalidArguments;
9004 uint32 data_size = bucket->size();
9005 GLsizei imageSize = data_size;
9006 const void* data = bucket->GetData(0, data_size);
9007 if (!data) {
9008 return error::kInvalidArguments;
9010 if (!validators_->texture_target.IsValid(target)) {
9011 LOCAL_SET_GL_ERROR(
9012 GL_INVALID_ENUM, "glCompressedTexSubImage2D", "target");
9013 return error::kNoError;
9015 if (!validators_->compressed_texture_format.IsValid(format)) {
9016 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9017 "glCompressedTexSubImage2D", format, "format");
9018 return error::kNoError;
9020 if (width < 0) {
9021 LOCAL_SET_GL_ERROR(
9022 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "width < 0");
9023 return error::kNoError;
9025 if (height < 0) {
9026 LOCAL_SET_GL_ERROR(
9027 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "height < 0");
9028 return error::kNoError;
9030 if (imageSize < 0) {
9031 LOCAL_SET_GL_ERROR(
9032 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "imageSize < 0");
9033 return error::kNoError;
9035 DoCompressedTexSubImage2D(
9036 target, level, xoffset, yoffset, width, height, format, imageSize, data);
9037 return error::kNoError;
9040 error::Error GLES2DecoderImpl::HandleTexImage2D(uint32 immediate_data_size,
9041 const void* cmd_data) {
9042 const gles2::cmds::TexImage2D& c =
9043 *static_cast<const gles2::cmds::TexImage2D*>(cmd_data);
9044 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage2D",
9045 "width", c.width, "height", c.height);
9046 // Set as failed for now, but if it successed, this will be set to not failed.
9047 texture_state_.tex_image_2d_failed = true;
9048 GLenum target = static_cast<GLenum>(c.target);
9049 GLint level = static_cast<GLint>(c.level);
9050 // TODO(kloveless): Change TexImage2D command to use unsigned integer
9051 // for internalformat.
9052 GLenum internal_format = static_cast<GLenum>(c.internalformat);
9053 GLsizei width = static_cast<GLsizei>(c.width);
9054 GLsizei height = static_cast<GLsizei>(c.height);
9055 GLint border = static_cast<GLint>(c.border);
9056 GLenum format = static_cast<GLenum>(c.format);
9057 GLenum type = static_cast<GLenum>(c.type);
9058 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
9059 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
9060 uint32 pixels_size;
9061 if (!GLES2Util::ComputeImageDataSizes(
9062 width, height, 1, format, type, state_.unpack_alignment, &pixels_size,
9063 NULL, NULL)) {
9064 return error::kOutOfBounds;
9066 const void* pixels = NULL;
9067 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
9068 pixels = GetSharedMemoryAs<const void*>(
9069 pixels_shm_id, pixels_shm_offset, pixels_size);
9070 if (!pixels) {
9071 return error::kOutOfBounds;
9075 // For testing only. Allows us to stress the ability to respond to OOM errors.
9076 if (workarounds().simulate_out_of_memory_on_large_textures &&
9077 (width * height >= 4096 * 4096)) {
9078 LOCAL_SET_GL_ERROR(
9079 GL_OUT_OF_MEMORY,
9080 "glTexImage2D", "synthetic out of memory");
9081 return error::kNoError;
9084 TextureManager::DoTextImage2DArguments args = {
9085 target, level, internal_format, width, height, border, format, type,
9086 pixels, pixels_size};
9087 texture_manager()->ValidateAndDoTexImage2D(
9088 &texture_state_, &state_, &framebuffer_state_, args);
9090 // This may be a slow command. Exit command processing to allow for
9091 // context preemption and GPU watchdog checks.
9092 ExitCommandProcessingEarly();
9093 return error::kNoError;
9096 error::Error GLES2DecoderImpl::HandleTexImage3D(uint32 immediate_data_size,
9097 const void* cmd_data) {
9098 // TODO(zmo): Unsafe ES3 API.
9099 if (!unsafe_es3_apis_enabled())
9100 return error::kUnknownCommand;
9102 const gles2::cmds::TexImage3D& c =
9103 *static_cast<const gles2::cmds::TexImage3D*>(cmd_data);
9104 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage3D",
9105 "widthXheight", c.width * c.height, "depth", c.depth);
9106 GLenum target = static_cast<GLenum>(c.target);
9107 GLint level = static_cast<GLint>(c.level);
9108 GLenum internal_format = static_cast<GLenum>(c.internalformat);
9109 GLsizei width = static_cast<GLsizei>(c.width);
9110 GLsizei height = static_cast<GLsizei>(c.height);
9111 GLsizei depth = static_cast<GLsizei>(c.depth);
9112 GLint border = static_cast<GLint>(c.border);
9113 GLenum format = static_cast<GLenum>(c.format);
9114 GLenum type = static_cast<GLenum>(c.type);
9115 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
9116 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
9117 uint32 pixels_size;
9118 if (!GLES2Util::ComputeImageDataSizes(
9119 width, height, depth, format, type, state_.unpack_alignment, &pixels_size,
9120 NULL, NULL)) {
9121 return error::kOutOfBounds;
9123 const void* pixels = NULL;
9124 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
9125 pixels = GetSharedMemoryAs<const void*>(
9126 pixels_shm_id, pixels_shm_offset, pixels_size);
9127 if (!pixels) {
9128 return error::kOutOfBounds;
9132 glTexImage3D(target, level, internal_format, width, height, depth, border,
9133 format, type, pixels);
9135 // This may be a slow command. Exit command processing to allow for
9136 // context preemption and GPU watchdog checks.
9137 ExitCommandProcessingEarly();
9138 return error::kNoError;
9141 void GLES2DecoderImpl::DoCompressedTexSubImage2D(
9142 GLenum target,
9143 GLint level,
9144 GLint xoffset,
9145 GLint yoffset,
9146 GLsizei width,
9147 GLsizei height,
9148 GLenum format,
9149 GLsizei image_size,
9150 const void * data) {
9151 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9152 &state_, target);
9153 if (!texture_ref) {
9154 LOCAL_SET_GL_ERROR(
9155 GL_INVALID_OPERATION,
9156 "glCompressedTexSubImage2D", "unknown texture for target");
9157 return;
9159 Texture* texture = texture_ref->texture();
9160 GLenum type = 0;
9161 GLenum internal_format = 0;
9162 if (!texture->GetLevelType(target, level, &type, &internal_format)) {
9163 LOCAL_SET_GL_ERROR(
9164 GL_INVALID_OPERATION,
9165 "glCompressedTexSubImage2D", "level does not exist.");
9166 return;
9168 if (internal_format != format) {
9169 LOCAL_SET_GL_ERROR(
9170 GL_INVALID_OPERATION,
9171 "glCompressedTexSubImage2D", "format does not match internal format.");
9172 return;
9174 if (!texture->ValidForTexture(
9175 target, level, xoffset, yoffset, width, height, type)) {
9176 LOCAL_SET_GL_ERROR(
9177 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "bad dimensions.");
9178 return;
9181 if (!ValidateCompressedTexFuncData(
9182 "glCompressedTexSubImage2D", width, height, format, image_size) ||
9183 !ValidateCompressedTexSubDimensions(
9184 "glCompressedTexSubImage2D",
9185 target, level, xoffset, yoffset, width, height, format, texture)) {
9186 return;
9190 // Note: There is no need to deal with texture cleared tracking here
9191 // because the validation above means you can only get here if the level
9192 // is already a matching compressed format and in that case
9193 // CompressedTexImage2D already cleared the texture.
9194 glCompressedTexSubImage2D(
9195 target, level, xoffset, yoffset, width, height, format, image_size, data);
9197 // This may be a slow command. Exit command processing to allow for
9198 // context preemption and GPU watchdog checks.
9199 ExitCommandProcessingEarly();
9202 static void Clip(
9203 GLint start, GLint range, GLint sourceRange,
9204 GLint* out_start, GLint* out_range) {
9205 DCHECK(out_start);
9206 DCHECK(out_range);
9207 if (start < 0) {
9208 range += start;
9209 start = 0;
9211 GLint end = start + range;
9212 if (end > sourceRange) {
9213 range -= end - sourceRange;
9215 *out_start = start;
9216 *out_range = range;
9219 void GLES2DecoderImpl::DoCopyTexImage2D(
9220 GLenum target,
9221 GLint level,
9222 GLenum internal_format,
9223 GLint x,
9224 GLint y,
9225 GLsizei width,
9226 GLsizei height,
9227 GLint border) {
9228 DCHECK(!ShouldDeferReads());
9229 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9230 &state_, target);
9231 if (!texture_ref) {
9232 LOCAL_SET_GL_ERROR(
9233 GL_INVALID_OPERATION,
9234 "glCopyTexImage2D", "unknown texture for target");
9235 return;
9237 Texture* texture = texture_ref->texture();
9238 if (texture->IsImmutable()) {
9239 LOCAL_SET_GL_ERROR(
9240 GL_INVALID_OPERATION, "glCopyTexImage2D", "texture is immutable");
9241 return;
9243 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
9244 border != 0) {
9245 LOCAL_SET_GL_ERROR(
9246 GL_INVALID_VALUE, "glCopyTexImage2D", "dimensions out of range");
9247 return;
9249 if (!texture_manager()->ValidateFormatAndTypeCombination(
9250 state_.GetErrorState(), "glCopyTexImage2D", internal_format,
9251 GL_UNSIGNED_BYTE)) {
9252 return;
9255 // Check we have compatible formats.
9256 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
9257 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
9258 uint32 channels_needed = GLES2Util::GetChannelsForFormat(internal_format);
9260 if ((channels_needed & channels_exist) != channels_needed) {
9261 LOCAL_SET_GL_ERROR(
9262 GL_INVALID_OPERATION, "glCopyTexImage2D", "incompatible format");
9263 return;
9266 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
9267 LOCAL_SET_GL_ERROR(
9268 GL_INVALID_OPERATION,
9269 "glCopyTexImage2D", "can not be used with depth or stencil textures");
9270 return;
9273 uint32 estimated_size = 0;
9274 if (!GLES2Util::ComputeImageDataSizes(
9275 width, height, 1, internal_format, GL_UNSIGNED_BYTE,
9276 state_.unpack_alignment, &estimated_size, NULL, NULL)) {
9277 LOCAL_SET_GL_ERROR(
9278 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too large");
9279 return;
9282 if (!EnsureGPUMemoryAvailable(estimated_size)) {
9283 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexImage2D", "out of memory");
9284 return;
9287 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexImage2D")) {
9288 return;
9291 if (FormsTextureCopyingFeedbackLoop(texture_ref, level)) {
9292 LOCAL_SET_GL_ERROR(
9293 GL_INVALID_OPERATION,
9294 "glCopyTexImage2D", "source and destination textures are the same");
9295 return;
9298 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
9299 return;
9302 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTexImage2D");
9303 ScopedResolvedFrameBufferBinder binder(this, false, true);
9304 gfx::Size size = GetBoundReadFrameBufferSize();
9306 if (texture->IsAttachedToFramebuffer()) {
9307 framebuffer_state_.clear_state_dirty = true;
9310 // Clip to size to source dimensions
9311 GLint copyX = 0;
9312 GLint copyY = 0;
9313 GLint copyWidth = 0;
9314 GLint copyHeight = 0;
9315 Clip(x, width, size.width(), &copyX, &copyWidth);
9316 Clip(y, height, size.height(), &copyY, &copyHeight);
9318 if (copyX != x ||
9319 copyY != y ||
9320 copyWidth != width ||
9321 copyHeight != height) {
9322 // some part was clipped so clear the texture.
9323 if (!ClearLevel(texture, target, level, internal_format, internal_format,
9324 GL_UNSIGNED_BYTE, width, height, texture->IsImmutable())) {
9325 LOCAL_SET_GL_ERROR(
9326 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too big");
9327 return;
9329 if (copyHeight > 0 && copyWidth > 0) {
9330 GLint dx = copyX - x;
9331 GLint dy = copyY - y;
9332 GLint destX = dx;
9333 GLint destY = dy;
9334 ScopedModifyPixels modify(texture_ref);
9335 glCopyTexSubImage2D(target, level,
9336 destX, destY, copyX, copyY,
9337 copyWidth, copyHeight);
9339 } else {
9340 ScopedModifyPixels modify(texture_ref);
9341 glCopyTexImage2D(target, level, internal_format,
9342 copyX, copyY, copyWidth, copyHeight, border);
9344 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTexImage2D");
9345 if (error == GL_NO_ERROR) {
9346 texture_manager()->SetLevelInfo(
9347 texture_ref, target, level, internal_format, width, height, 1,
9348 border, internal_format, GL_UNSIGNED_BYTE, true);
9351 // This may be a slow command. Exit command processing to allow for
9352 // context preemption and GPU watchdog checks.
9353 ExitCommandProcessingEarly();
9356 void GLES2DecoderImpl::DoCopyTexSubImage2D(
9357 GLenum target,
9358 GLint level,
9359 GLint xoffset,
9360 GLint yoffset,
9361 GLint x,
9362 GLint y,
9363 GLsizei width,
9364 GLsizei height) {
9365 DCHECK(!ShouldDeferReads());
9366 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9367 &state_, target);
9368 if (!texture_ref) {
9369 LOCAL_SET_GL_ERROR(
9370 GL_INVALID_OPERATION,
9371 "glCopyTexSubImage2D", "unknown texture for target");
9372 return;
9374 Texture* texture = texture_ref->texture();
9375 GLenum type = 0;
9376 GLenum format = 0;
9377 if (!texture->GetLevelType(target, level, &type, &format) ||
9378 !texture->ValidForTexture(
9379 target, level, xoffset, yoffset, width, height, type)) {
9380 LOCAL_SET_GL_ERROR(
9381 GL_INVALID_VALUE, "glCopyTexSubImage2D", "bad dimensions.");
9382 return;
9384 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
9385 LOCAL_SET_GL_ERROR(
9386 GL_INVALID_OPERATION,
9387 "glCopyTexSubImage2D", "async upload pending for texture");
9388 return;
9391 // Check we have compatible formats.
9392 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
9393 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
9394 uint32 channels_needed = GLES2Util::GetChannelsForFormat(format);
9396 if (!channels_needed ||
9397 (channels_needed & channels_exist) != channels_needed) {
9398 LOCAL_SET_GL_ERROR(
9399 GL_INVALID_OPERATION, "glCopyTexSubImage2D", "incompatible format");
9400 return;
9403 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
9404 LOCAL_SET_GL_ERROR(
9405 GL_INVALID_OPERATION,
9406 "glCopySubImage2D", "can not be used with depth or stencil textures");
9407 return;
9410 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexSubImage2D")) {
9411 return;
9414 if (FormsTextureCopyingFeedbackLoop(texture_ref, level)) {
9415 LOCAL_SET_GL_ERROR(
9416 GL_INVALID_OPERATION,
9417 "glCopyTexSubImage2D", "source and destination textures are the same");
9418 return;
9421 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
9422 return;
9425 ScopedResolvedFrameBufferBinder binder(this, false, true);
9426 gfx::Size size = GetBoundReadFrameBufferSize();
9427 GLint copyX = 0;
9428 GLint copyY = 0;
9429 GLint copyWidth = 0;
9430 GLint copyHeight = 0;
9431 Clip(x, width, size.width(), &copyX, &copyWidth);
9432 Clip(y, height, size.height(), &copyY, &copyHeight);
9434 if (xoffset != 0 || yoffset != 0 || width != size.width() ||
9435 height != size.height()) {
9436 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target,
9437 level)) {
9438 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexSubImage2D",
9439 "dimensions too big");
9440 return;
9442 } else {
9443 // Write all pixels in below.
9444 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
9447 if (copyX != x ||
9448 copyY != y ||
9449 copyWidth != width ||
9450 copyHeight != height) {
9451 // some part was clipped so clear the sub rect.
9452 uint32 pixels_size = 0;
9453 if (!GLES2Util::ComputeImageDataSizes(
9454 width, height, 1, format, type, state_.unpack_alignment, &pixels_size,
9455 NULL, NULL)) {
9456 LOCAL_SET_GL_ERROR(
9457 GL_INVALID_VALUE, "glCopyTexSubImage2D", "dimensions too large");
9458 return;
9460 scoped_ptr<char[]> zero(new char[pixels_size]);
9461 memset(zero.get(), 0, pixels_size);
9462 ScopedModifyPixels modify(texture_ref);
9463 glTexSubImage2D(
9464 target, level, xoffset, yoffset, width, height,
9465 format, type, zero.get());
9468 if (copyHeight > 0 && copyWidth > 0) {
9469 GLint dx = copyX - x;
9470 GLint dy = copyY - y;
9471 GLint destX = xoffset + dx;
9472 GLint destY = yoffset + dy;
9473 ScopedModifyPixels modify(texture_ref);
9474 glCopyTexSubImage2D(target, level,
9475 destX, destY, copyX, copyY,
9476 copyWidth, copyHeight);
9479 // This may be a slow command. Exit command processing to allow for
9480 // context preemption and GPU watchdog checks.
9481 ExitCommandProcessingEarly();
9484 bool GLES2DecoderImpl::ValidateTexSubImage2D(
9485 error::Error* error,
9486 const char* function_name,
9487 GLenum target,
9488 GLint level,
9489 GLint xoffset,
9490 GLint yoffset,
9491 GLsizei width,
9492 GLsizei height,
9493 GLenum format,
9494 GLenum type,
9495 const void * data) {
9496 (*error) = error::kNoError;
9497 if (!validators_->texture_target.IsValid(target)) {
9498 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
9499 return false;
9501 if (width < 0) {
9502 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "width < 0");
9503 return false;
9505 if (height < 0) {
9506 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "height < 0");
9507 return false;
9509 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9510 &state_, target);
9511 if (!texture_ref) {
9512 LOCAL_SET_GL_ERROR(
9513 GL_INVALID_OPERATION,
9514 function_name, "unknown texture for target");
9515 return false;
9517 Texture* texture = texture_ref->texture();
9518 GLenum current_type = 0;
9519 GLenum internal_format = 0;
9520 if (!texture->GetLevelType(target, level, &current_type, &internal_format)) {
9521 LOCAL_SET_GL_ERROR(
9522 GL_INVALID_OPERATION, function_name, "level does not exist.");
9523 return false;
9525 if (!texture_manager()->ValidateTextureParameters(state_.GetErrorState(),
9526 function_name, format, type, internal_format, level)) {
9527 return false;
9529 if (type != current_type) {
9530 LOCAL_SET_GL_ERROR(
9531 GL_INVALID_OPERATION,
9532 function_name, "type does not match type of texture.");
9533 return false;
9535 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
9536 LOCAL_SET_GL_ERROR(
9537 GL_INVALID_OPERATION,
9538 function_name, "async upload pending for texture");
9539 return false;
9541 if (!texture->ValidForTexture(
9542 target, level, xoffset, yoffset, width, height, type)) {
9543 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "bad dimensions.");
9544 return false;
9546 if ((GLES2Util::GetChannelsForFormat(format) &
9547 (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
9548 LOCAL_SET_GL_ERROR(
9549 GL_INVALID_OPERATION,
9550 function_name, "can not supply data for depth or stencil textures");
9551 return false;
9553 if (data == NULL) {
9554 (*error) = error::kOutOfBounds;
9555 return false;
9557 return true;
9560 error::Error GLES2DecoderImpl::DoTexSubImage2D(
9561 GLenum target,
9562 GLint level,
9563 GLint xoffset,
9564 GLint yoffset,
9565 GLsizei width,
9566 GLsizei height,
9567 GLenum format,
9568 GLenum type,
9569 const void * data) {
9570 error::Error error = error::kNoError;
9571 if (!ValidateTexSubImage2D(&error, "glTexSubImage2D", target, level,
9572 xoffset, yoffset, width, height, format, type, data)) {
9573 return error;
9575 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9576 &state_, target);
9577 Texture* texture = texture_ref->texture();
9578 GLsizei tex_width = 0;
9579 GLsizei tex_height = 0;
9580 bool ok = texture->GetLevelSize(target, level, &tex_width, &tex_height);
9581 DCHECK(ok);
9582 if (xoffset != 0 || yoffset != 0 ||
9583 width != tex_width || height != tex_height) {
9584 if (!texture_manager()->ClearTextureLevel(this, texture_ref,
9585 target, level)) {
9586 LOCAL_SET_GL_ERROR(
9587 GL_OUT_OF_MEMORY, "glTexSubImage2D", "dimensions too big");
9588 return error::kNoError;
9590 ScopedTextureUploadTimer timer(&texture_state_);
9591 glTexSubImage2D(
9592 target, level, xoffset, yoffset, width, height, format, type, data);
9593 return error::kNoError;
9596 if (!texture_state_.texsubimage2d_faster_than_teximage2d &&
9597 !texture->IsImmutable() &&
9598 !texture->HasImages()) {
9599 ScopedTextureUploadTimer timer(&texture_state_);
9600 GLenum internal_format;
9601 GLenum tex_type;
9602 texture->GetLevelType(target, level, &tex_type, &internal_format);
9603 // NOTE: In OpenGL ES 2.0 border is always zero. If that changes we'll need
9604 // to look it up.
9605 glTexImage2D(
9606 target, level, internal_format, width, height, 0, format, type, data);
9607 } else {
9608 ScopedTextureUploadTimer timer(&texture_state_);
9609 glTexSubImage2D(
9610 target, level, xoffset, yoffset, width, height, format, type, data);
9612 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
9614 // This may be a slow command. Exit command processing to allow for
9615 // context preemption and GPU watchdog checks.
9616 ExitCommandProcessingEarly();
9617 return error::kNoError;
9620 error::Error GLES2DecoderImpl::HandleTexSubImage2D(uint32 immediate_data_size,
9621 const void* cmd_data) {
9622 const gles2::cmds::TexSubImage2D& c =
9623 *static_cast<const gles2::cmds::TexSubImage2D*>(cmd_data);
9624 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage2D",
9625 "width", c.width, "height", c.height);
9626 GLboolean internal = static_cast<GLboolean>(c.internal);
9627 if (internal == GL_TRUE && texture_state_.tex_image_2d_failed)
9628 return error::kNoError;
9630 GLenum target = static_cast<GLenum>(c.target);
9631 GLint level = static_cast<GLint>(c.level);
9632 GLint xoffset = static_cast<GLint>(c.xoffset);
9633 GLint yoffset = static_cast<GLint>(c.yoffset);
9634 GLsizei width = static_cast<GLsizei>(c.width);
9635 GLsizei height = static_cast<GLsizei>(c.height);
9636 GLenum format = static_cast<GLenum>(c.format);
9637 GLenum type = static_cast<GLenum>(c.type);
9638 uint32 data_size;
9639 if (!GLES2Util::ComputeImageDataSizes(
9640 width, height, 1, format, type, state_.unpack_alignment, &data_size,
9641 NULL, NULL)) {
9642 return error::kOutOfBounds;
9644 const void* pixels = GetSharedMemoryAs<const void*>(
9645 c.pixels_shm_id, c.pixels_shm_offset, data_size);
9646 return DoTexSubImage2D(
9647 target, level, xoffset, yoffset, width, height, format, type, pixels);
9650 // TODO(zmo): Remove the below stub once we add the real function binding.
9651 // Currently it's missing due to a gmock limitation.
9652 static void glTexSubImage3D(
9653 GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
9654 GLsizei height, GLsizei width, GLsizei depth, GLenum format, GLenum type,
9655 const void* pixels) {
9656 NOTIMPLEMENTED();
9659 error::Error GLES2DecoderImpl::HandleTexSubImage3D(uint32 immediate_data_size,
9660 const void* cmd_data) {
9661 // TODO(zmo): Unsafe ES3 API.
9662 if (!unsafe_es3_apis_enabled())
9663 return error::kUnknownCommand;
9665 const gles2::cmds::TexSubImage3D& c =
9666 *static_cast<const gles2::cmds::TexSubImage3D*>(cmd_data);
9667 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage3D",
9668 "widthXheight", c.width * c.height, "depth", c.depth);
9669 GLenum target = static_cast<GLenum>(c.target);
9670 GLint level = static_cast<GLint>(c.level);
9671 GLint xoffset = static_cast<GLint>(c.xoffset);
9672 GLint yoffset = static_cast<GLint>(c.yoffset);
9673 GLint zoffset = static_cast<GLint>(c.zoffset);
9674 GLsizei width = static_cast<GLsizei>(c.width);
9675 GLsizei height = static_cast<GLsizei>(c.height);
9676 GLsizei depth = static_cast<GLsizei>(c.depth);
9677 GLenum format = static_cast<GLenum>(c.format);
9678 GLenum type = static_cast<GLenum>(c.type);
9679 uint32 data_size;
9680 if (!GLES2Util::ComputeImageDataSizes(
9681 width, height, depth, format, type, state_.unpack_alignment, &data_size,
9682 NULL, NULL)) {
9683 return error::kOutOfBounds;
9685 const void* pixels = GetSharedMemoryAs<const void*>(
9686 c.pixels_shm_id, c.pixels_shm_offset, data_size);
9687 glTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height,
9688 depth, format, type, pixels);
9689 return error::kNoError;
9692 error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
9693 uint32 immediate_data_size,
9694 const void* cmd_data) {
9695 const gles2::cmds::GetVertexAttribPointerv& c =
9696 *static_cast<const gles2::cmds::GetVertexAttribPointerv*>(cmd_data);
9697 GLuint index = static_cast<GLuint>(c.index);
9698 GLenum pname = static_cast<GLenum>(c.pname);
9699 typedef cmds::GetVertexAttribPointerv::Result Result;
9700 Result* result = GetSharedMemoryAs<Result*>(
9701 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
9702 if (!result) {
9703 return error::kOutOfBounds;
9705 // Check that the client initialized the result.
9706 if (result->size != 0) {
9707 return error::kInvalidArguments;
9709 if (!validators_->vertex_pointer.IsValid(pname)) {
9710 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9711 "glGetVertexAttribPointerv", pname, "pname");
9712 return error::kNoError;
9714 if (index >= group_->max_vertex_attribs()) {
9715 LOCAL_SET_GL_ERROR(
9716 GL_INVALID_VALUE, "glGetVertexAttribPointerv", "index out of range.");
9717 return error::kNoError;
9719 result->SetNumResults(1);
9720 *result->GetData() =
9721 state_.vertex_attrib_manager->GetVertexAttrib(index)->offset();
9722 return error::kNoError;
9725 bool GLES2DecoderImpl::GetUniformSetup(GLuint program_id,
9726 GLint fake_location,
9727 uint32 shm_id,
9728 uint32 shm_offset,
9729 error::Error* error,
9730 GLint* real_location,
9731 GLuint* service_id,
9732 void** result_pointer,
9733 GLenum* result_type,
9734 GLsizei* result_size) {
9735 DCHECK(error);
9736 DCHECK(service_id);
9737 DCHECK(result_pointer);
9738 DCHECK(result_type);
9739 DCHECK(real_location);
9740 *error = error::kNoError;
9741 // Make sure we have enough room for the result on failure.
9742 SizedResult<GLint>* result;
9743 result = GetSharedMemoryAs<SizedResult<GLint>*>(
9744 shm_id, shm_offset, SizedResult<GLint>::ComputeSize(0));
9745 if (!result) {
9746 *error = error::kOutOfBounds;
9747 return false;
9749 *result_pointer = result;
9750 // Set the result size to 0 so the client does not have to check for success.
9751 result->SetNumResults(0);
9752 Program* program = GetProgramInfoNotShader(program_id, "glGetUniform");
9753 if (!program) {
9754 return false;
9756 if (!program->IsValid()) {
9757 // Program was not linked successfully. (ie, glLinkProgram)
9758 LOCAL_SET_GL_ERROR(
9759 GL_INVALID_OPERATION, "glGetUniform", "program not linked");
9760 return false;
9762 *service_id = program->service_id();
9763 GLint array_index = -1;
9764 const Program::UniformInfo* uniform_info =
9765 program->GetUniformInfoByFakeLocation(
9766 fake_location, real_location, &array_index);
9767 if (!uniform_info) {
9768 // No such location.
9769 LOCAL_SET_GL_ERROR(
9770 GL_INVALID_OPERATION, "glGetUniform", "unknown location");
9771 return false;
9773 GLenum type = uniform_info->type;
9774 GLsizei size = GLES2Util::GetGLDataTypeSizeForUniforms(type);
9775 if (size == 0) {
9776 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glGetUniform", "unknown type");
9777 return false;
9779 result = GetSharedMemoryAs<SizedResult<GLint>*>(
9780 shm_id, shm_offset, SizedResult<GLint>::ComputeSizeFromBytes(size));
9781 if (!result) {
9782 *error = error::kOutOfBounds;
9783 return false;
9785 result->size = size;
9786 *result_size = size;
9787 *result_type = type;
9788 return true;
9791 error::Error GLES2DecoderImpl::HandleGetUniformiv(uint32 immediate_data_size,
9792 const void* cmd_data) {
9793 const gles2::cmds::GetUniformiv& c =
9794 *static_cast<const gles2::cmds::GetUniformiv*>(cmd_data);
9795 GLuint program = c.program;
9796 GLint fake_location = c.location;
9797 GLuint service_id;
9798 GLenum result_type;
9799 GLsizei result_size;
9800 GLint real_location = -1;
9801 Error error;
9802 void* result;
9803 if (GetUniformSetup(program, fake_location, c.params_shm_id,
9804 c.params_shm_offset, &error, &real_location, &service_id,
9805 &result, &result_type, &result_size)) {
9806 glGetUniformiv(
9807 service_id, real_location,
9808 static_cast<cmds::GetUniformiv::Result*>(result)->GetData());
9810 return error;
9813 error::Error GLES2DecoderImpl::HandleGetUniformfv(uint32 immediate_data_size,
9814 const void* cmd_data) {
9815 const gles2::cmds::GetUniformfv& c =
9816 *static_cast<const gles2::cmds::GetUniformfv*>(cmd_data);
9817 GLuint program = c.program;
9818 GLint fake_location = c.location;
9819 GLuint service_id;
9820 GLint real_location = -1;
9821 Error error;
9822 typedef cmds::GetUniformfv::Result Result;
9823 Result* result;
9824 GLenum result_type;
9825 GLsizei result_size;
9826 if (GetUniformSetup(program, fake_location, c.params_shm_id,
9827 c.params_shm_offset, &error, &real_location, &service_id,
9828 reinterpret_cast<void**>(&result), &result_type,
9829 &result_size)) {
9830 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
9831 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
9832 GLsizei num_values = result_size / sizeof(Result::Type);
9833 scoped_ptr<GLint[]> temp(new GLint[num_values]);
9834 glGetUniformiv(service_id, real_location, temp.get());
9835 GLfloat* dst = result->GetData();
9836 for (GLsizei ii = 0; ii < num_values; ++ii) {
9837 dst[ii] = (temp[ii] != 0);
9839 } else {
9840 glGetUniformfv(service_id, real_location, result->GetData());
9843 return error;
9846 error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
9847 uint32 immediate_data_size,
9848 const void* cmd_data) {
9849 const gles2::cmds::GetShaderPrecisionFormat& c =
9850 *static_cast<const gles2::cmds::GetShaderPrecisionFormat*>(cmd_data);
9851 GLenum shader_type = static_cast<GLenum>(c.shadertype);
9852 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
9853 typedef cmds::GetShaderPrecisionFormat::Result Result;
9854 Result* result = GetSharedMemoryAs<Result*>(
9855 c.result_shm_id, c.result_shm_offset, sizeof(*result));
9856 if (!result) {
9857 return error::kOutOfBounds;
9859 // Check that the client initialized the result.
9860 if (result->success != 0) {
9861 return error::kInvalidArguments;
9863 if (!validators_->shader_type.IsValid(shader_type)) {
9864 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9865 "glGetShaderPrecisionFormat", shader_type, "shader_type");
9866 return error::kNoError;
9868 if (!validators_->shader_precision.IsValid(precision_type)) {
9869 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9870 "glGetShaderPrecisionFormat", precision_type, "precision_type");
9871 return error::kNoError;
9874 result->success = 1; // true
9876 GLint range[2] = { 0, 0 };
9877 GLint precision = 0;
9878 GetShaderPrecisionFormatImpl(shader_type, precision_type, range, &precision);
9880 result->min_range = range[0];
9881 result->max_range = range[1];
9882 result->precision = precision;
9884 return error::kNoError;
9887 error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
9888 uint32 immediate_data_size,
9889 const void* cmd_data) {
9890 const gles2::cmds::GetAttachedShaders& c =
9891 *static_cast<const gles2::cmds::GetAttachedShaders*>(cmd_data);
9892 uint32 result_size = c.result_size;
9893 GLuint program_id = static_cast<GLuint>(c.program);
9894 Program* program = GetProgramInfoNotShader(
9895 program_id, "glGetAttachedShaders");
9896 if (!program) {
9897 return error::kNoError;
9899 typedef cmds::GetAttachedShaders::Result Result;
9900 uint32 max_count = Result::ComputeMaxResults(result_size);
9901 Result* result = GetSharedMemoryAs<Result*>(
9902 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
9903 if (!result) {
9904 return error::kOutOfBounds;
9906 // Check that the client initialized the result.
9907 if (result->size != 0) {
9908 return error::kInvalidArguments;
9910 GLsizei count = 0;
9911 glGetAttachedShaders(
9912 program->service_id(), max_count, &count, result->GetData());
9913 for (GLsizei ii = 0; ii < count; ++ii) {
9914 if (!shader_manager()->GetClientId(result->GetData()[ii],
9915 &result->GetData()[ii])) {
9916 NOTREACHED();
9917 return error::kGenericError;
9920 result->SetNumResults(count);
9921 return error::kNoError;
9924 error::Error GLES2DecoderImpl::HandleGetActiveUniform(
9925 uint32 immediate_data_size,
9926 const void* cmd_data) {
9927 const gles2::cmds::GetActiveUniform& c =
9928 *static_cast<const gles2::cmds::GetActiveUniform*>(cmd_data);
9929 GLuint program_id = c.program;
9930 GLuint index = c.index;
9931 uint32 name_bucket_id = c.name_bucket_id;
9932 typedef cmds::GetActiveUniform::Result Result;
9933 Result* result = GetSharedMemoryAs<Result*>(
9934 c.result_shm_id, c.result_shm_offset, sizeof(*result));
9935 if (!result) {
9936 return error::kOutOfBounds;
9938 // Check that the client initialized the result.
9939 if (result->success != 0) {
9940 return error::kInvalidArguments;
9942 Program* program = GetProgramInfoNotShader(
9943 program_id, "glGetActiveUniform");
9944 if (!program) {
9945 return error::kNoError;
9947 const Program::UniformInfo* uniform_info =
9948 program->GetUniformInfo(index);
9949 if (!uniform_info) {
9950 LOCAL_SET_GL_ERROR(
9951 GL_INVALID_VALUE, "glGetActiveUniform", "index out of range");
9952 return error::kNoError;
9954 result->success = 1; // true.
9955 result->size = uniform_info->size;
9956 result->type = uniform_info->type;
9957 Bucket* bucket = CreateBucket(name_bucket_id);
9958 bucket->SetFromString(uniform_info->name.c_str());
9959 return error::kNoError;
9962 error::Error GLES2DecoderImpl::HandleGetActiveUniformBlockiv(
9963 uint32 immediate_data_size, const void* cmd_data) {
9964 if (!unsafe_es3_apis_enabled())
9965 return error::kUnknownCommand;
9966 const gles2::cmds::GetActiveUniformBlockiv& c =
9967 *static_cast<const gles2::cmds::GetActiveUniformBlockiv*>(cmd_data);
9968 GLuint program_id = c.program;
9969 GLuint index = static_cast<GLuint>(c.index);
9970 GLenum pname = static_cast<GLenum>(c.pname);
9971 Program* program = GetProgramInfoNotShader(
9972 program_id, "glGetActiveUniformBlockiv");
9973 if (!program) {
9974 return error::kNoError;
9976 GLuint service_id = program->service_id();
9977 GLint link_status = GL_FALSE;
9978 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
9979 if (link_status != GL_TRUE) {
9980 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
9981 "glGetActiveActiveUniformBlockiv", "program not linked");
9982 return error::kNoError;
9984 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetActiveUniformBlockiv");
9985 GLsizei num_values = 1;
9986 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES) {
9987 GLint num = 0;
9988 glGetActiveUniformBlockiv(
9989 service_id, index, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &num);
9990 GLenum error = glGetError();
9991 if (error != GL_NO_ERROR) {
9992 // Assume this will the same error if calling with pname.
9993 LOCAL_SET_GL_ERROR(error, "GetActiveUniformBlockiv", "");
9994 return error::kNoError;
9996 num_values = static_cast<GLsizei>(num);
9998 typedef cmds::GetActiveUniformBlockiv::Result Result;
9999 Result* result = GetSharedMemoryAs<Result*>(
10000 c.params_shm_id, c.params_shm_offset, Result::ComputeSize(num_values));
10001 GLint* params = result ? result->GetData() : NULL;
10002 if (params == NULL) {
10003 return error::kOutOfBounds;
10005 // Check that the client initialized the result.
10006 if (result->size != 0) {
10007 return error::kInvalidArguments;
10009 glGetActiveUniformBlockiv(service_id, index, pname, params);
10010 GLenum error = glGetError();
10011 if (error == GL_NO_ERROR) {
10012 result->SetNumResults(num_values);
10013 } else {
10014 LOCAL_SET_GL_ERROR(error, "GetActiveUniformBlockiv", "");
10016 return error::kNoError;
10019 error::Error GLES2DecoderImpl::HandleGetActiveUniformBlockName(
10020 uint32 immediate_data_size, const void* cmd_data) {
10021 if (!unsafe_es3_apis_enabled())
10022 return error::kUnknownCommand;
10023 const gles2::cmds::GetActiveUniformBlockName& c =
10024 *static_cast<const gles2::cmds::GetActiveUniformBlockName*>(cmd_data);
10025 GLuint program_id = c.program;
10026 GLuint index = c.index;
10027 uint32 name_bucket_id = c.name_bucket_id;
10028 typedef cmds::GetActiveUniformBlockName::Result Result;
10029 Result* result = GetSharedMemoryAs<Result*>(
10030 c.result_shm_id, c.result_shm_offset, sizeof(*result));
10031 if (!result) {
10032 return error::kOutOfBounds;
10034 // Check that the client initialized the result.
10035 if (*result != 0) {
10036 return error::kInvalidArguments;
10038 Program* program = GetProgramInfoNotShader(
10039 program_id, "glGetActiveUniformBlockName");
10040 if (!program) {
10041 return error::kNoError;
10043 GLuint service_id = program->service_id();
10044 GLint link_status = GL_FALSE;
10045 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
10046 if (link_status != GL_TRUE) {
10047 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10048 "glGetActiveActiveUniformBlockName", "program not linked");
10049 return error::kNoError;
10051 GLint max_length = 0;
10052 glGetProgramiv(
10053 service_id, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &max_length);
10054 // Increase one so &buffer[0] is always valid.
10055 GLsizei buf_size = static_cast<GLsizei>(max_length) + 1;
10056 std::vector<char> buffer(buf_size);
10057 GLsizei length = 0;
10058 glGetActiveUniformBlockName(
10059 service_id, index, buf_size, &length, &buffer[0]);
10060 if (length == 0) {
10061 *result = 0;
10062 return error::kNoError;
10064 *result = 1;
10065 Bucket* bucket = CreateBucket(name_bucket_id);
10066 DCHECK_GT(buf_size, length);
10067 DCHECK_EQ(0, buffer[length]);
10068 bucket->SetFromString(&buffer[0]);
10069 return error::kNoError;
10072 error::Error GLES2DecoderImpl::HandleGetActiveUniformsiv(
10073 uint32 immediate_data_size, const void* cmd_data) {
10074 if (!unsafe_es3_apis_enabled())
10075 return error::kUnknownCommand;
10076 const gles2::cmds::GetActiveUniformsiv& c =
10077 *static_cast<const gles2::cmds::GetActiveUniformsiv*>(cmd_data);
10078 GLuint program_id = c.program;
10079 GLenum pname = static_cast<GLenum>(c.pname);
10080 Bucket* bucket = GetBucket(c.indices_bucket_id);
10081 if (!bucket) {
10082 return error::kInvalidArguments;
10084 GLsizei count = static_cast<GLsizei>(bucket->size() / sizeof(GLuint));
10085 const GLuint* indices = bucket->GetDataAs<const GLuint*>(0, bucket->size());
10086 typedef cmds::GetActiveUniformsiv::Result Result;
10087 Result* result = GetSharedMemoryAs<Result*>(
10088 c.params_shm_id, c.params_shm_offset, Result::ComputeSize(count));
10089 GLint* params = result ? result->GetData() : NULL;
10090 if (params == NULL) {
10091 return error::kOutOfBounds;
10093 // Check that the client initialized the result.
10094 if (result->size != 0) {
10095 return error::kInvalidArguments;
10097 Program* program = GetProgramInfoNotShader(
10098 program_id, "glGetActiveUniformsiv");
10099 if (!program) {
10100 return error::kNoError;
10102 GLuint service_id = program->service_id();
10103 GLint link_status = GL_FALSE;
10104 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
10105 if (link_status != GL_TRUE) {
10106 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10107 "glGetActiveUniformsiv", "program not linked");
10108 return error::kNoError;
10110 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetActiveUniformsiv");
10111 glGetActiveUniformsiv(service_id, count, indices, pname, params);
10112 GLenum error = glGetError();
10113 if (error == GL_NO_ERROR) {
10114 result->SetNumResults(count);
10115 } else {
10116 LOCAL_SET_GL_ERROR(error, "GetActiveUniformsiv", "");
10118 return error::kNoError;
10121 error::Error GLES2DecoderImpl::HandleGetActiveAttrib(uint32 immediate_data_size,
10122 const void* cmd_data) {
10123 const gles2::cmds::GetActiveAttrib& c =
10124 *static_cast<const gles2::cmds::GetActiveAttrib*>(cmd_data);
10125 GLuint program_id = c.program;
10126 GLuint index = c.index;
10127 uint32 name_bucket_id = c.name_bucket_id;
10128 typedef cmds::GetActiveAttrib::Result Result;
10129 Result* result = GetSharedMemoryAs<Result*>(
10130 c.result_shm_id, c.result_shm_offset, sizeof(*result));
10131 if (!result) {
10132 return error::kOutOfBounds;
10134 // Check that the client initialized the result.
10135 if (result->success != 0) {
10136 return error::kInvalidArguments;
10138 Program* program = GetProgramInfoNotShader(
10139 program_id, "glGetActiveAttrib");
10140 if (!program) {
10141 return error::kNoError;
10143 const Program::VertexAttrib* attrib_info =
10144 program->GetAttribInfo(index);
10145 if (!attrib_info) {
10146 LOCAL_SET_GL_ERROR(
10147 GL_INVALID_VALUE, "glGetActiveAttrib", "index out of range");
10148 return error::kNoError;
10150 result->success = 1; // true.
10151 result->size = attrib_info->size;
10152 result->type = attrib_info->type;
10153 Bucket* bucket = CreateBucket(name_bucket_id);
10154 bucket->SetFromString(attrib_info->name.c_str());
10155 return error::kNoError;
10158 error::Error GLES2DecoderImpl::HandleShaderBinary(uint32 immediate_data_size,
10159 const void* cmd_data) {
10160 #if 1 // No binary shader support.
10161 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glShaderBinary", "not supported");
10162 return error::kNoError;
10163 #else
10164 GLsizei n = static_cast<GLsizei>(c.n);
10165 if (n < 0) {
10166 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "n < 0");
10167 return error::kNoError;
10169 GLsizei length = static_cast<GLsizei>(c.length);
10170 if (length < 0) {
10171 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "length < 0");
10172 return error::kNoError;
10174 uint32 data_size;
10175 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
10176 return error::kOutOfBounds;
10178 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
10179 c.shaders_shm_id, c.shaders_shm_offset, data_size);
10180 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
10181 const void* binary = GetSharedMemoryAs<const void*>(
10182 c.binary_shm_id, c.binary_shm_offset, length);
10183 if (shaders == NULL || binary == NULL) {
10184 return error::kOutOfBounds;
10186 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
10187 for (GLsizei ii = 0; ii < n; ++ii) {
10188 Shader* shader = GetShader(shaders[ii]);
10189 if (!shader) {
10190 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "unknown shader");
10191 return error::kNoError;
10193 service_ids[ii] = shader->service_id();
10195 // TODO(gman): call glShaderBinary
10196 return error::kNoError;
10197 #endif
10200 void GLES2DecoderImpl::DoSwapBuffers() {
10201 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
10203 int this_frame_number = frame_number_++;
10204 // TRACE_EVENT for gpu tests:
10205 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffersLatency",
10206 TRACE_EVENT_SCOPE_THREAD,
10207 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
10208 "width", (is_offscreen ? offscreen_size_.width() :
10209 surface_->GetSize().width()));
10210 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoSwapBuffers",
10211 "offscreen", is_offscreen,
10212 "frame", this_frame_number);
10214 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
10217 ScopedGPUTrace scoped_gpu_trace(gpu_tracer_.get(), kTraceDecoder,
10218 "gpu_toplevel", "SwapBuffer");
10220 bool is_tracing;
10221 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
10222 &is_tracing);
10223 if (is_tracing) {
10224 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
10225 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
10226 is_offscreen ? offscreen_size_ : surface_->GetSize());
10229 // If offscreen then don't actually SwapBuffers to the display. Just copy
10230 // the rendered frame to another frame buffer.
10231 if (is_offscreen) {
10232 TRACE_EVENT2("gpu", "Offscreen",
10233 "width", offscreen_size_.width(), "height", offscreen_size_.height());
10234 if (offscreen_size_ != offscreen_saved_color_texture_->size()) {
10235 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
10236 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
10237 // fix this.
10238 if (workarounds().needs_offscreen_buffer_workaround) {
10239 offscreen_saved_frame_buffer_->Create();
10240 glFinish();
10243 // Allocate the offscreen saved color texture.
10244 DCHECK(offscreen_saved_color_format_);
10245 offscreen_saved_color_texture_->AllocateStorage(
10246 offscreen_size_, offscreen_saved_color_format_, false);
10248 offscreen_saved_frame_buffer_->AttachRenderTexture(
10249 offscreen_saved_color_texture_.get());
10250 if (offscreen_size_.width() != 0 && offscreen_size_.height() != 0) {
10251 if (offscreen_saved_frame_buffer_->CheckStatus() !=
10252 GL_FRAMEBUFFER_COMPLETE) {
10253 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
10254 << "because offscreen saved FBO was incomplete.";
10255 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB);
10256 return;
10259 // Clear the offscreen color texture.
10260 // TODO(piman): Is this still necessary?
10262 ScopedFrameBufferBinder binder(this,
10263 offscreen_saved_frame_buffer_->id());
10264 glClearColor(0, 0, 0, 0);
10265 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
10266 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
10267 glClear(GL_COLOR_BUFFER_BIT);
10268 RestoreClearState();
10272 UpdateParentTextureInfo();
10275 if (offscreen_size_.width() == 0 || offscreen_size_.height() == 0)
10276 return;
10277 ScopedGLErrorSuppressor suppressor(
10278 "GLES2DecoderImpl::DoSwapBuffers", GetErrorState());
10280 if (IsOffscreenBufferMultisampled()) {
10281 // For multisampled buffers, resolve the frame buffer.
10282 ScopedResolvedFrameBufferBinder binder(this, true, false);
10283 } else {
10284 ScopedFrameBufferBinder binder(this,
10285 offscreen_target_frame_buffer_->id());
10287 if (offscreen_target_buffer_preserved_) {
10288 // Copy the target frame buffer to the saved offscreen texture.
10289 offscreen_saved_color_texture_->Copy(
10290 offscreen_saved_color_texture_->size(),
10291 offscreen_saved_color_format_);
10292 } else {
10293 // Flip the textures in the parent context via the texture manager.
10294 if (!!offscreen_saved_color_texture_info_.get())
10295 offscreen_saved_color_texture_info_->texture()->
10296 SetServiceId(offscreen_target_color_texture_->id());
10298 offscreen_saved_color_texture_.swap(offscreen_target_color_texture_);
10299 offscreen_target_frame_buffer_->AttachRenderTexture(
10300 offscreen_target_color_texture_.get());
10303 // Ensure the side effects of the copy are visible to the parent
10304 // context. There is no need to do this for ANGLE because it uses a
10305 // single D3D device for all contexts.
10306 if (!feature_info_->gl_version_info().is_angle)
10307 glFlush();
10309 } else {
10310 if (!surface_->SwapBuffers()) {
10311 LOG(ERROR) << "Context lost because SwapBuffers failed.";
10312 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB);
10316 // This may be a slow command. Exit command processing to allow for
10317 // context preemption and GPU watchdog checks.
10318 ExitCommandProcessingEarly();
10321 void GLES2DecoderImpl::DoSwapInterval(int interval) {
10322 context_->SetSwapInterval(interval);
10325 error::Error GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
10326 uint32 immediate_data_size,
10327 const void* cmd_data) {
10328 const gles2::cmds::EnableFeatureCHROMIUM& c =
10329 *static_cast<const gles2::cmds::EnableFeatureCHROMIUM*>(cmd_data);
10330 Bucket* bucket = GetBucket(c.bucket_id);
10331 if (!bucket || bucket->size() == 0) {
10332 return error::kInvalidArguments;
10334 typedef cmds::EnableFeatureCHROMIUM::Result Result;
10335 Result* result = GetSharedMemoryAs<Result*>(
10336 c.result_shm_id, c.result_shm_offset, sizeof(*result));
10337 if (!result) {
10338 return error::kOutOfBounds;
10340 // Check that the client initialized the result.
10341 if (*result != 0) {
10342 return error::kInvalidArguments;
10344 std::string feature_str;
10345 if (!bucket->GetAsString(&feature_str)) {
10346 return error::kInvalidArguments;
10349 // TODO(gman): make this some kind of table to function pointer thingy.
10350 if (feature_str.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
10351 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
10352 } else if (feature_str.compare("pepper3d_support_fixed_attribs") == 0) {
10353 buffer_manager()->set_allow_fixed_attribs(true);
10354 // TODO(gman): decide how to remove the need for this const_cast.
10355 // I could make validators_ non const but that seems bad as this is the only
10356 // place it is needed. I could make some special friend class of validators
10357 // just to allow this to set them. That seems silly. I could refactor this
10358 // code to use the extension mechanism or the initialization attributes to
10359 // turn this feature on. Given that the only real point of this is to make
10360 // the conformance tests pass and given that there is lots of real work that
10361 // needs to be done it seems like refactoring for one to one of those
10362 // methods is a very low priority.
10363 const_cast<Validators*>(validators_)->vertex_attrib_type.AddValue(GL_FIXED);
10364 } else if (feature_str.compare("webgl_enable_glsl_webgl_validation") == 0) {
10365 force_webgl_glsl_validation_ = true;
10366 InitializeShaderTranslator();
10367 } else {
10368 return error::kNoError;
10371 *result = 1; // true.
10372 return error::kNoError;
10375 error::Error GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
10376 uint32 immediate_data_size,
10377 const void* cmd_data) {
10378 const gles2::cmds::GetRequestableExtensionsCHROMIUM& c =
10379 *static_cast<const gles2::cmds::GetRequestableExtensionsCHROMIUM*>(
10380 cmd_data);
10381 Bucket* bucket = CreateBucket(c.bucket_id);
10382 scoped_refptr<FeatureInfo> info(new FeatureInfo());
10383 info->Initialize(disallowed_features_);
10384 bucket->SetFromString(info->extensions().c_str());
10385 return error::kNoError;
10388 error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
10389 uint32 immediate_data_size,
10390 const void* cmd_data) {
10391 const gles2::cmds::RequestExtensionCHROMIUM& c =
10392 *static_cast<const gles2::cmds::RequestExtensionCHROMIUM*>(cmd_data);
10393 Bucket* bucket = GetBucket(c.bucket_id);
10394 if (!bucket || bucket->size() == 0) {
10395 return error::kInvalidArguments;
10397 std::string feature_str;
10398 if (!bucket->GetAsString(&feature_str)) {
10399 return error::kInvalidArguments;
10402 bool desire_webgl_glsl_validation =
10403 feature_str.find("GL_CHROMIUM_webglsl") != std::string::npos;
10404 bool desire_standard_derivatives = false;
10405 bool desire_frag_depth = false;
10406 bool desire_draw_buffers = false;
10407 bool desire_shader_texture_lod = false;
10408 if (force_webgl_glsl_validation_) {
10409 desire_standard_derivatives =
10410 feature_str.find("GL_OES_standard_derivatives") != std::string::npos;
10411 desire_frag_depth =
10412 feature_str.find("GL_EXT_frag_depth") != std::string::npos;
10413 desire_draw_buffers =
10414 feature_str.find("GL_EXT_draw_buffers") != std::string::npos;
10415 desire_shader_texture_lod =
10416 feature_str.find("GL_EXT_shader_texture_lod") != std::string::npos;
10419 if (desire_webgl_glsl_validation != force_webgl_glsl_validation_ ||
10420 desire_standard_derivatives != derivatives_explicitly_enabled_ ||
10421 desire_frag_depth != frag_depth_explicitly_enabled_ ||
10422 desire_draw_buffers != draw_buffers_explicitly_enabled_) {
10423 force_webgl_glsl_validation_ |= desire_webgl_glsl_validation;
10424 derivatives_explicitly_enabled_ |= desire_standard_derivatives;
10425 frag_depth_explicitly_enabled_ |= desire_frag_depth;
10426 draw_buffers_explicitly_enabled_ |= desire_draw_buffers;
10427 shader_texture_lod_explicitly_enabled_ |= desire_shader_texture_lod;
10428 InitializeShaderTranslator();
10431 UpdateCapabilities();
10433 return error::kNoError;
10436 error::Error GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
10437 uint32 immediate_data_size,
10438 const void* cmd_data) {
10439 const gles2::cmds::GetProgramInfoCHROMIUM& c =
10440 *static_cast<const gles2::cmds::GetProgramInfoCHROMIUM*>(cmd_data);
10441 GLuint program_id = static_cast<GLuint>(c.program);
10442 uint32 bucket_id = c.bucket_id;
10443 Bucket* bucket = CreateBucket(bucket_id);
10444 bucket->SetSize(sizeof(ProgramInfoHeader)); // in case we fail.
10445 Program* program = NULL;
10446 program = GetProgram(program_id);
10447 if (!program || !program->IsValid()) {
10448 return error::kNoError;
10450 program->GetProgramInfo(program_manager(), bucket);
10451 return error::kNoError;
10454 error::Error GLES2DecoderImpl::HandleGetUniformBlocksCHROMIUM(
10455 uint32 immediate_data_size, const void* cmd_data) {
10456 if (!unsafe_es3_apis_enabled())
10457 return error::kUnknownCommand;
10458 const gles2::cmds::GetUniformBlocksCHROMIUM& c =
10459 *static_cast<const gles2::cmds::GetUniformBlocksCHROMIUM*>(cmd_data);
10460 GLuint program_id = static_cast<GLuint>(c.program);
10461 uint32 bucket_id = c.bucket_id;
10462 Bucket* bucket = CreateBucket(bucket_id);
10463 bucket->SetSize(sizeof(UniformBlocksHeader)); // in case we fail.
10464 Program* program = NULL;
10465 program = GetProgram(program_id);
10466 if (!program || !program->IsValid()) {
10467 return error::kNoError;
10469 program->GetUniformBlocks(bucket);
10470 return error::kNoError;
10473 error::Error GLES2DecoderImpl::HandleGetUniformsES3CHROMIUM(
10474 uint32 immediate_data_size, const void* cmd_data) {
10475 if (!unsafe_es3_apis_enabled())
10476 return error::kUnknownCommand;
10477 const gles2::cmds::GetUniformsES3CHROMIUM& c =
10478 *static_cast<const gles2::cmds::GetUniformsES3CHROMIUM*>(cmd_data);
10479 GLuint program_id = static_cast<GLuint>(c.program);
10480 uint32 bucket_id = c.bucket_id;
10481 Bucket* bucket = CreateBucket(bucket_id);
10482 bucket->SetSize(sizeof(UniformsES3Header)); // in case we fail.
10483 Program* program = NULL;
10484 program = GetProgram(program_id);
10485 if (!program || !program->IsValid()) {
10486 return error::kNoError;
10488 program->GetUniformsES3(bucket);
10489 return error::kNoError;
10492 error::Error GLES2DecoderImpl::HandleGetTransformFeedbackVarying(
10493 uint32 immediate_data_size,
10494 const void* cmd_data) {
10495 if (!unsafe_es3_apis_enabled())
10496 return error::kUnknownCommand;
10497 const gles2::cmds::GetTransformFeedbackVarying& c =
10498 *static_cast<const gles2::cmds::GetTransformFeedbackVarying*>(cmd_data);
10499 GLuint program_id = c.program;
10500 GLuint index = c.index;
10501 uint32 name_bucket_id = c.name_bucket_id;
10502 typedef cmds::GetTransformFeedbackVarying::Result Result;
10503 Result* result = GetSharedMemoryAs<Result*>(
10504 c.result_shm_id, c.result_shm_offset, sizeof(*result));
10505 if (!result) {
10506 return error::kOutOfBounds;
10508 // Check that the client initialized the result.
10509 if (result->success != 0) {
10510 return error::kInvalidArguments;
10512 Program* program = GetProgramInfoNotShader(
10513 program_id, "glGetTransformFeedbackVarying");
10514 if (!program) {
10515 return error::kNoError;
10517 GLuint service_id = program->service_id();
10518 GLint link_status = GL_FALSE;
10519 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
10520 if (link_status != GL_TRUE) {
10521 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10522 "glGetTransformFeedbackVarying", "program not linked");
10523 return error::kNoError;
10525 GLint max_length = 0;
10526 glGetProgramiv(
10527 service_id, GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH, &max_length);
10528 max_length = std::max(1, max_length);
10529 std::vector<char> buffer(max_length);
10530 GLsizei length = 0;
10531 GLsizei size = 0;
10532 GLenum type = 0;
10533 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetTransformFeedbackVarying");
10534 glGetTransformFeedbackVarying(
10535 service_id, index, max_length, &length, &size, &type, &buffer[0]);
10536 GLenum error = glGetError();
10537 if (error != GL_NO_ERROR) {
10538 LOCAL_SET_GL_ERROR(error, "glGetTransformFeedbackVarying", "");
10539 return error::kNoError;
10541 result->success = 1; // true.
10542 result->size = static_cast<int32_t>(size);
10543 result->type = static_cast<uint32_t>(type);
10544 Bucket* bucket = CreateBucket(name_bucket_id);
10545 DCHECK(length >= 0 && length < max_length);
10546 buffer[length] = '\0'; // Just to be safe.
10547 bucket->SetFromString(&buffer[0]);
10548 return error::kNoError;
10551 error::Error GLES2DecoderImpl::HandleGetTransformFeedbackVaryingsCHROMIUM(
10552 uint32 immediate_data_size, const void* cmd_data) {
10553 if (!unsafe_es3_apis_enabled())
10554 return error::kUnknownCommand;
10555 const gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM& c =
10556 *static_cast<const gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM*>(
10557 cmd_data);
10558 GLuint program_id = static_cast<GLuint>(c.program);
10559 uint32 bucket_id = c.bucket_id;
10560 Bucket* bucket = CreateBucket(bucket_id);
10561 bucket->SetSize(sizeof(TransformFeedbackVaryingsHeader)); // in case we fail.
10562 Program* program = NULL;
10563 program = GetProgram(program_id);
10564 if (!program || !program->IsValid()) {
10565 return error::kNoError;
10567 program->GetTransformFeedbackVaryings(bucket);
10568 return error::kNoError;
10571 error::ContextLostReason GLES2DecoderImpl::GetContextLostReason() {
10572 switch (reset_status_) {
10573 case GL_NO_ERROR:
10574 // TODO(kbr): improve the precision of the error code in this case.
10575 // Consider delegating to context for error code if MakeCurrent fails.
10576 return error::kUnknown;
10577 case GL_GUILTY_CONTEXT_RESET_ARB:
10578 return error::kGuilty;
10579 case GL_INNOCENT_CONTEXT_RESET_ARB:
10580 return error::kInnocent;
10581 case GL_UNKNOWN_CONTEXT_RESET_ARB:
10582 return error::kUnknown;
10585 NOTREACHED();
10586 return error::kUnknown;
10589 void GLES2DecoderImpl::MaybeExitOnContextLost() {
10590 // Some D3D drivers cannot recover from device lost in the GPU process
10591 // sandbox. Allow a new GPU process to launch.
10592 if (workarounds().exit_on_context_lost) {
10593 LOG(ERROR) << "Exiting GPU process because some drivers cannot reset"
10594 << " a D3D device in the Chrome GPU process sandbox.";
10595 #if defined(OS_WIN)
10596 base::win::SetShouldCrashOnProcessDetach(false);
10597 #endif
10598 exit(0);
10602 bool GLES2DecoderImpl::WasContextLost() {
10603 if (reset_status_ != GL_NO_ERROR) {
10604 MaybeExitOnContextLost();
10605 return true;
10607 if (IsRobustnessSupported()) {
10608 GLenum status = glGetGraphicsResetStatusARB();
10609 if (status != GL_NO_ERROR) {
10610 // The graphics card was reset. Signal a lost context to the application.
10611 reset_status_ = status;
10612 reset_by_robustness_extension_ = true;
10613 LOG(ERROR) << (surface_->IsOffscreen() ? "Offscreen" : "Onscreen")
10614 << " context lost via ARB/EXT_robustness. Reset status = "
10615 << GLES2Util::GetStringEnum(status);
10616 MaybeExitOnContextLost();
10617 return true;
10620 return false;
10623 bool GLES2DecoderImpl::WasContextLostByRobustnessExtension() {
10624 return WasContextLost() && reset_by_robustness_extension_;
10627 void GLES2DecoderImpl::LoseContext(uint32 reset_status) {
10628 // Only loses the context once.
10629 if (reset_status_ != GL_NO_ERROR) {
10630 return;
10633 if (workarounds().use_virtualized_gl_contexts) {
10634 // If the context is virtual, the real context being guilty does not ensure
10635 // that the virtual context is guilty.
10636 if (reset_status == GL_GUILTY_CONTEXT_RESET_ARB) {
10637 reset_status = GL_UNKNOWN_CONTEXT_RESET_ARB;
10639 } else if (reset_status == GL_UNKNOWN_CONTEXT_RESET_ARB &&
10640 IsRobustnessSupported()) {
10641 // If the reason for the call was a GL error, we can try to determine the
10642 // reset status more accurately.
10643 GLenum driver_status = glGetGraphicsResetStatusARB();
10644 if (driver_status == GL_GUILTY_CONTEXT_RESET_ARB ||
10645 driver_status == GL_INNOCENT_CONTEXT_RESET_ARB) {
10646 reset_status = driver_status;
10650 // Marks this context as lost.
10651 reset_status_ = reset_status;
10652 current_decoder_error_ = error::kLostContext;
10655 error::Error GLES2DecoderImpl::HandleInsertSyncPointCHROMIUM(
10656 uint32 immediate_data_size,
10657 const void* cmd_data) {
10658 return error::kUnknownCommand;
10661 error::Error GLES2DecoderImpl::HandleWaitSyncPointCHROMIUM(
10662 uint32 immediate_data_size,
10663 const void* cmd_data) {
10664 const gles2::cmds::WaitSyncPointCHROMIUM& c =
10665 *static_cast<const gles2::cmds::WaitSyncPointCHROMIUM*>(cmd_data);
10666 uint32 sync_point = c.sync_point;
10667 if (wait_sync_point_callback_.is_null())
10668 return error::kNoError;
10670 return wait_sync_point_callback_.Run(sync_point) ?
10671 error::kNoError : error::kDeferCommandUntilLater;
10674 error::Error GLES2DecoderImpl::HandleDiscardBackbufferCHROMIUM(
10675 uint32 immediate_data_size,
10676 const void* cmd_data) {
10677 if (surface_->DeferDraws())
10678 return error::kDeferCommandUntilLater;
10679 if (!surface_->SetBackbufferAllocation(false))
10680 return error::kLostContext;
10681 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
10682 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
10683 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
10684 return error::kNoError;
10687 bool GLES2DecoderImpl::GenQueriesEXTHelper(
10688 GLsizei n, const GLuint* client_ids) {
10689 for (GLsizei ii = 0; ii < n; ++ii) {
10690 if (query_manager_->GetQuery(client_ids[ii])) {
10691 return false;
10694 query_manager_->GenQueries(n, client_ids);
10695 return true;
10698 void GLES2DecoderImpl::DeleteQueriesEXTHelper(
10699 GLsizei n, const GLuint* client_ids) {
10700 for (GLsizei ii = 0; ii < n; ++ii) {
10701 QueryManager::Query* query = query_manager_->GetQuery(client_ids[ii]);
10702 if (query && !query->IsDeleted()) {
10703 ContextState::QueryMap::iterator it =
10704 state_.current_queries.find(query->target());
10705 if (it != state_.current_queries.end())
10706 state_.current_queries.erase(it);
10708 query->Destroy(true);
10710 query_manager_->RemoveQuery(client_ids[ii]);
10714 bool GLES2DecoderImpl::ProcessPendingQueries(bool did_finish) {
10715 if (query_manager_.get() == NULL) {
10716 return false;
10718 if (!query_manager_->ProcessPendingQueries(did_finish)) {
10719 current_decoder_error_ = error::kOutOfBounds;
10721 return query_manager_->HavePendingQueries();
10724 // Note that if there are no pending readpixels right now,
10725 // this function will call the callback immediately.
10726 void GLES2DecoderImpl::WaitForReadPixels(base::Closure callback) {
10727 if (features().use_async_readpixels && !pending_readpixel_fences_.empty()) {
10728 pending_readpixel_fences_.back()->callbacks.push_back(callback);
10729 } else {
10730 callback.Run();
10734 void GLES2DecoderImpl::ProcessPendingReadPixels() {
10735 while (!pending_readpixel_fences_.empty() &&
10736 pending_readpixel_fences_.front()->fence->HasCompleted()) {
10737 std::vector<base::Closure> callbacks =
10738 pending_readpixel_fences_.front()->callbacks;
10739 pending_readpixel_fences_.pop();
10740 for (size_t i = 0; i < callbacks.size(); i++) {
10741 callbacks[i].Run();
10746 bool GLES2DecoderImpl::HasMoreIdleWork() {
10747 return !pending_readpixel_fences_.empty() ||
10748 async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers();
10751 void GLES2DecoderImpl::PerformIdleWork() {
10752 ProcessPendingReadPixels();
10753 if (!async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers())
10754 return;
10755 async_pixel_transfer_manager_->ProcessMorePendingTransfers();
10756 ProcessFinishedAsyncTransfers();
10759 error::Error GLES2DecoderImpl::HandleBeginQueryEXT(uint32 immediate_data_size,
10760 const void* cmd_data) {
10761 const gles2::cmds::BeginQueryEXT& c =
10762 *static_cast<const gles2::cmds::BeginQueryEXT*>(cmd_data);
10763 GLenum target = static_cast<GLenum>(c.target);
10764 GLuint client_id = static_cast<GLuint>(c.id);
10765 int32 sync_shm_id = static_cast<int32>(c.sync_data_shm_id);
10766 uint32 sync_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
10768 switch (target) {
10769 case GL_COMMANDS_ISSUED_CHROMIUM:
10770 case GL_LATENCY_QUERY_CHROMIUM:
10771 case GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM:
10772 case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM:
10773 case GL_GET_ERROR_QUERY_CHROMIUM:
10774 break;
10775 case GL_COMMANDS_COMPLETED_CHROMIUM:
10776 if (!features().chromium_sync_query) {
10777 LOCAL_SET_GL_ERROR(
10778 GL_INVALID_OPERATION, "glBeginQueryEXT",
10779 "not enabled for commands completed queries");
10780 return error::kNoError;
10782 break;
10783 default:
10784 if (!features().occlusion_query_boolean) {
10785 LOCAL_SET_GL_ERROR(
10786 GL_INVALID_OPERATION, "glBeginQueryEXT",
10787 "not enabled for occlusion queries");
10788 return error::kNoError;
10790 break;
10793 if (state_.current_queries.find(target) != state_.current_queries.end()) {
10794 LOCAL_SET_GL_ERROR(
10795 GL_INVALID_OPERATION, "glBeginQueryEXT", "query already in progress");
10796 return error::kNoError;
10799 if (client_id == 0) {
10800 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glBeginQueryEXT", "id is 0");
10801 return error::kNoError;
10804 QueryManager::Query* query = query_manager_->GetQuery(client_id);
10805 if (!query) {
10806 if (!query_manager_->IsValidQuery(client_id)) {
10807 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10808 "glBeginQueryEXT",
10809 "id not made by glGenQueriesEXT");
10810 return error::kNoError;
10812 query = query_manager_->CreateQuery(
10813 target, client_id, sync_shm_id, sync_shm_offset);
10816 if (query->target() != target) {
10817 LOCAL_SET_GL_ERROR(
10818 GL_INVALID_OPERATION, "glBeginQueryEXT", "target does not match");
10819 return error::kNoError;
10820 } else if (query->shm_id() != sync_shm_id ||
10821 query->shm_offset() != sync_shm_offset) {
10822 DLOG(ERROR) << "Shared memory used by query not the same as before";
10823 return error::kInvalidArguments;
10826 if (!query_manager_->BeginQuery(query)) {
10827 return error::kOutOfBounds;
10830 state_.current_queries[target] = query;
10831 return error::kNoError;
10834 error::Error GLES2DecoderImpl::HandleEndQueryEXT(uint32 immediate_data_size,
10835 const void* cmd_data) {
10836 const gles2::cmds::EndQueryEXT& c =
10837 *static_cast<const gles2::cmds::EndQueryEXT*>(cmd_data);
10838 GLenum target = static_cast<GLenum>(c.target);
10839 uint32 submit_count = static_cast<GLuint>(c.submit_count);
10840 ContextState::QueryMap::iterator it = state_.current_queries.find(target);
10842 if (it == state_.current_queries.end()) {
10843 LOCAL_SET_GL_ERROR(
10844 GL_INVALID_OPERATION, "glEndQueryEXT", "No active query");
10845 return error::kNoError;
10848 QueryManager::Query* query = it->second.get();
10849 if (!query_manager_->EndQuery(query, submit_count)) {
10850 return error::kOutOfBounds;
10853 query_manager_->ProcessPendingTransferQueries();
10855 state_.current_queries.erase(it);
10856 return error::kNoError;
10859 bool GLES2DecoderImpl::GenVertexArraysOESHelper(
10860 GLsizei n, const GLuint* client_ids) {
10861 for (GLsizei ii = 0; ii < n; ++ii) {
10862 if (GetVertexAttribManager(client_ids[ii])) {
10863 return false;
10867 if (!features().native_vertex_array_object) {
10868 // Emulated VAO
10869 for (GLsizei ii = 0; ii < n; ++ii) {
10870 CreateVertexAttribManager(client_ids[ii], 0, true);
10872 } else {
10873 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
10875 glGenVertexArraysOES(n, service_ids.get());
10876 for (GLsizei ii = 0; ii < n; ++ii) {
10877 CreateVertexAttribManager(client_ids[ii], service_ids[ii], true);
10881 return true;
10884 void GLES2DecoderImpl::DeleteVertexArraysOESHelper(
10885 GLsizei n, const GLuint* client_ids) {
10886 for (GLsizei ii = 0; ii < n; ++ii) {
10887 VertexAttribManager* vao =
10888 GetVertexAttribManager(client_ids[ii]);
10889 if (vao && !vao->IsDeleted()) {
10890 if (state_.vertex_attrib_manager.get() == vao) {
10891 DoBindVertexArrayOES(0);
10893 RemoveVertexAttribManager(client_ids[ii]);
10898 void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id) {
10899 VertexAttribManager* vao = NULL;
10900 if (client_id != 0) {
10901 vao = GetVertexAttribManager(client_id);
10902 if (!vao) {
10903 // Unlike most Bind* methods, the spec explicitly states that VertexArray
10904 // only allows names that have been previously generated. As such, we do
10905 // not generate new names here.
10906 LOCAL_SET_GL_ERROR(
10907 GL_INVALID_OPERATION,
10908 "glBindVertexArrayOES", "bad vertex array id.");
10909 current_decoder_error_ = error::kNoError;
10910 return;
10912 } else {
10913 vao = state_.default_vertex_attrib_manager.get();
10916 // Only set the VAO state if it's changed
10917 if (state_.vertex_attrib_manager.get() != vao) {
10918 state_.vertex_attrib_manager = vao;
10919 if (!features().native_vertex_array_object) {
10920 EmulateVertexArrayState();
10921 } else {
10922 GLuint service_id = vao->service_id();
10923 glBindVertexArrayOES(service_id);
10928 // Used when OES_vertex_array_object isn't natively supported
10929 void GLES2DecoderImpl::EmulateVertexArrayState() {
10930 // Setup the Vertex attribute state
10931 for (uint32 vv = 0; vv < group_->max_vertex_attribs(); ++vv) {
10932 RestoreStateForAttrib(vv, true);
10935 // Setup the element buffer
10936 Buffer* element_array_buffer =
10937 state_.vertex_attrib_manager->element_array_buffer();
10938 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
10939 element_array_buffer ? element_array_buffer->service_id() : 0);
10942 bool GLES2DecoderImpl::DoIsVertexArrayOES(GLuint client_id) {
10943 const VertexAttribManager* vao =
10944 GetVertexAttribManager(client_id);
10945 return vao && vao->IsValid() && !vao->IsDeleted();
10948 #if defined(OS_MACOSX)
10949 void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id) {
10950 TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.find(
10951 texture_id);
10952 if (it != texture_to_io_surface_map_.end()) {
10953 // Found a previous IOSurface bound to this texture; release it.
10954 IOSurfaceRef surface = it->second;
10955 CFRelease(surface);
10956 texture_to_io_surface_map_.erase(it);
10959 #endif
10961 void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
10962 GLenum target, GLsizei width, GLsizei height,
10963 GLuint io_surface_id, GLuint plane) {
10964 #if defined(OS_MACOSX)
10965 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) {
10966 LOCAL_SET_GL_ERROR(
10967 GL_INVALID_OPERATION,
10968 "glTexImageIOSurface2DCHROMIUM", "only supported on desktop GL.");
10969 return;
10972 if (target != GL_TEXTURE_RECTANGLE_ARB) {
10973 // This might be supported in the future, and if we could require
10974 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
10975 // could delete a lot of code. For now, perform strict validation so we
10976 // know what's going on.
10977 LOCAL_SET_GL_ERROR(
10978 GL_INVALID_OPERATION,
10979 "glTexImageIOSurface2DCHROMIUM",
10980 "requires TEXTURE_RECTANGLE_ARB target");
10981 return;
10984 // Default target might be conceptually valid, but disallow it to avoid
10985 // accidents.
10986 TextureRef* texture_ref =
10987 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
10988 if (!texture_ref) {
10989 LOCAL_SET_GL_ERROR(
10990 GL_INVALID_OPERATION,
10991 "glTexImageIOSurface2DCHROMIUM", "no rectangle texture bound");
10992 return;
10995 // Look up the new IOSurface. Note that because of asynchrony
10996 // between processes this might fail; during live resizing the
10997 // plugin process might allocate and release an IOSurface before
10998 // this process gets a chance to look it up. Hold on to any old
10999 // IOSurface in this case.
11000 IOSurfaceRef surface = IOSurfaceLookup(io_surface_id);
11001 if (!surface) {
11002 LOCAL_SET_GL_ERROR(
11003 GL_INVALID_OPERATION,
11004 "glTexImageIOSurface2DCHROMIUM", "no IOSurface with the given ID");
11005 return;
11008 // Release any IOSurface previously bound to this texture.
11009 ReleaseIOSurfaceForTexture(texture_ref->service_id());
11011 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
11012 texture_to_io_surface_map_.insert(
11013 std::make_pair(texture_ref->service_id(), surface));
11015 CGLContextObj context =
11016 static_cast<CGLContextObj>(context_->GetHandle());
11018 CGLError err = CGLTexImageIOSurface2D(
11019 context,
11020 target,
11021 GL_RGBA,
11022 width,
11023 height,
11024 GL_BGRA,
11025 GL_UNSIGNED_INT_8_8_8_8_REV,
11026 surface,
11027 plane);
11029 if (err != kCGLNoError) {
11030 LOCAL_SET_GL_ERROR(
11031 GL_INVALID_OPERATION,
11032 "glTexImageIOSurface2DCHROMIUM", "error in CGLTexImageIOSurface2D");
11033 return;
11036 texture_manager()->SetLevelInfo(
11037 texture_ref, target, 0, GL_RGBA, width, height, 1, 0,
11038 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, true);
11040 #else
11041 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
11042 "glTexImageIOSurface2DCHROMIUM", "not supported.");
11043 #endif
11046 static GLenum ExtractFormatFromStorageFormat(GLenum internalformat) {
11047 switch (internalformat) {
11048 case GL_RGB565:
11049 return GL_RGB;
11050 case GL_RGBA4:
11051 return GL_RGBA;
11052 case GL_RGB5_A1:
11053 return GL_RGBA;
11054 case GL_RGB8_OES:
11055 return GL_RGB;
11056 case GL_RGBA8_OES:
11057 return GL_RGBA;
11058 case GL_LUMINANCE8_ALPHA8_EXT:
11059 return GL_LUMINANCE_ALPHA;
11060 case GL_LUMINANCE8_EXT:
11061 return GL_LUMINANCE;
11062 case GL_ALPHA8_EXT:
11063 return GL_ALPHA;
11064 case GL_RGBA32F_EXT:
11065 return GL_RGBA;
11066 case GL_RGB32F_EXT:
11067 return GL_RGB;
11068 case GL_ALPHA32F_EXT:
11069 return GL_ALPHA;
11070 case GL_LUMINANCE32F_EXT:
11071 return GL_LUMINANCE;
11072 case GL_LUMINANCE_ALPHA32F_EXT:
11073 return GL_LUMINANCE_ALPHA;
11074 case GL_RGBA16F_EXT:
11075 return GL_RGBA;
11076 case GL_RGB16F_EXT:
11077 return GL_RGB;
11078 case GL_ALPHA16F_EXT:
11079 return GL_ALPHA;
11080 case GL_LUMINANCE16F_EXT:
11081 return GL_LUMINANCE;
11082 case GL_LUMINANCE_ALPHA16F_EXT:
11083 return GL_LUMINANCE_ALPHA;
11084 case GL_BGRA8_EXT:
11085 return GL_BGRA_EXT;
11086 case GL_SRGB8_ALPHA8_EXT:
11087 return GL_SRGB_ALPHA_EXT;
11088 default:
11089 return GL_NONE;
11093 bool GLES2DecoderImpl::ValidateCopyTextureCHROMIUM(
11094 const char* function_name,
11095 GLenum target,
11096 TextureRef* source_texture_ref,
11097 TextureRef* dest_texture_ref,
11098 GLenum dest_internal_format) {
11099 if (!source_texture_ref || !dest_texture_ref) {
11100 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "unknown texture id");
11101 return false;
11104 if (GL_TEXTURE_2D != target) {
11105 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name,
11106 "invalid texture target");
11107 return false;
11110 Texture* source_texture = source_texture_ref->texture();
11111 Texture* dest_texture = dest_texture_ref->texture();
11112 if (source_texture == dest_texture) {
11113 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
11114 "source and destination textures are the same");
11115 return false;
11118 if (dest_texture->target() != GL_TEXTURE_2D ||
11119 (source_texture->target() != GL_TEXTURE_2D &&
11120 source_texture->target() != GL_TEXTURE_RECTANGLE_ARB &&
11121 source_texture->target() != GL_TEXTURE_EXTERNAL_OES)) {
11122 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name,
11123 "invalid texture target binding");
11124 return false;
11127 GLenum source_type = 0;
11128 GLenum source_internal_format = 0;
11129 source_texture->GetLevelType(source_texture->target(), 0, &source_type,
11130 &source_internal_format);
11132 // The destination format should be GL_RGB, or GL_RGBA. GL_ALPHA,
11133 // GL_LUMINANCE, and GL_LUMINANCE_ALPHA are not supported because they are not
11134 // renderable on some platforms.
11135 bool valid_dest_format = dest_internal_format == GL_RGB ||
11136 dest_internal_format == GL_RGBA ||
11137 dest_internal_format == GL_BGRA_EXT;
11138 bool valid_source_format = source_internal_format == GL_ALPHA ||
11139 source_internal_format == GL_RGB ||
11140 source_internal_format == GL_RGBA ||
11141 source_internal_format == GL_LUMINANCE ||
11142 source_internal_format == GL_LUMINANCE_ALPHA ||
11143 source_internal_format == GL_BGRA_EXT;
11144 if (!valid_source_format || !valid_dest_format) {
11145 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
11146 "invalid internal format");
11147 return false;
11149 return true;
11152 void GLES2DecoderImpl::DoCopyTextureCHROMIUM(GLenum target,
11153 GLuint source_id,
11154 GLuint dest_id,
11155 GLenum internal_format,
11156 GLenum dest_type) {
11157 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopyTextureCHROMIUM");
11159 TextureRef* source_texture_ref = GetTexture(source_id);
11160 TextureRef* dest_texture_ref = GetTexture(dest_id);
11161 Texture* source_texture = source_texture_ref->texture();
11162 Texture* dest_texture = dest_texture_ref->texture();
11163 int source_width = 0;
11164 int source_height = 0;
11165 gfx::GLImage* image =
11166 source_texture->GetLevelImage(source_texture->target(), 0);
11167 if (image) {
11168 gfx::Size size = image->GetSize();
11169 source_width = size.width();
11170 source_height = size.height();
11171 if (source_width <= 0 || source_height <= 0) {
11172 LOCAL_SET_GL_ERROR(
11173 GL_INVALID_VALUE,
11174 "glCopyTextureChromium", "invalid image size");
11175 return;
11177 } else {
11178 if (!source_texture->GetLevelSize(
11179 source_texture->target(), 0, &source_width, &source_height)) {
11180 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
11181 "glCopyTextureChromium",
11182 "source texture has no level 0");
11183 return;
11186 // Check that this type of texture is allowed.
11187 if (!texture_manager()->ValidForTarget(source_texture->target(), 0,
11188 source_width, source_height, 1)) {
11189 LOCAL_SET_GL_ERROR(
11190 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "Bad dimensions");
11191 return;
11195 GLenum source_type = 0;
11196 GLenum source_internal_format = 0;
11197 source_texture->GetLevelType(
11198 source_texture->target(), 0, &source_type, &source_internal_format);
11200 if (dest_texture->IsImmutable()) {
11201 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCopyTextureCHROMIUM",
11202 "texture is immutable");
11203 return;
11206 if (!ValidateCopyTextureCHROMIUM("glCopyTextureCHROMIUM", target,
11207 source_texture_ref, dest_texture_ref,
11208 internal_format)) {
11209 return;
11212 // Clear the source texture if necessary.
11213 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref,
11214 source_texture->target(), 0)) {
11215 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTextureCHROMIUM",
11216 "dimensions too big");
11217 return;
11220 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
11221 // needed because it takes 10s of milliseconds to initialize.
11222 if (!copy_texture_CHROMIUM_.get()) {
11223 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
11224 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
11225 copy_texture_CHROMIUM_->Initialize(this);
11226 RestoreCurrentFramebufferBindings();
11227 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR)
11228 return;
11231 GLenum dest_type_previous = dest_type;
11232 GLenum dest_internal_format = internal_format;
11233 int dest_width = 0;
11234 int dest_height = 0;
11235 bool dest_level_defined =
11236 dest_texture->GetLevelSize(GL_TEXTURE_2D, 0, &dest_width, &dest_height);
11238 if (dest_level_defined) {
11239 dest_texture->GetLevelType(GL_TEXTURE_2D, 0, &dest_type_previous,
11240 &dest_internal_format);
11243 // Resize the destination texture to the dimensions of the source texture.
11244 if (!dest_level_defined || dest_width != source_width ||
11245 dest_height != source_height ||
11246 dest_internal_format != internal_format ||
11247 dest_type_previous != dest_type) {
11248 // Ensure that the glTexImage2D succeeds.
11249 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
11250 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
11251 glTexImage2D(GL_TEXTURE_2D, 0, internal_format, source_width, source_height,
11252 0, internal_format, dest_type, NULL);
11253 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM");
11254 if (error != GL_NO_ERROR) {
11255 RestoreCurrentTextureBindings(&state_, GL_TEXTURE_2D);
11256 return;
11259 texture_manager()->SetLevelInfo(
11260 dest_texture_ref, GL_TEXTURE_2D, 0, internal_format, source_width,
11261 source_height, 1, 0, internal_format, dest_type, true);
11262 } else {
11263 texture_manager()->SetLevelCleared(dest_texture_ref, GL_TEXTURE_2D, 0,
11264 true);
11267 ScopedModifyPixels modify(dest_texture_ref);
11269 // Try using GLImage::CopyTexImage when possible.
11270 bool unpack_premultiply_alpha_change =
11271 unpack_premultiply_alpha_ ^ unpack_unpremultiply_alpha_;
11272 if (image && !unpack_flip_y_ && !unpack_premultiply_alpha_change) {
11273 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
11274 if (image->CopyTexImage(GL_TEXTURE_2D))
11275 return;
11278 DoWillUseTexImageIfNeeded(source_texture, source_texture->target());
11280 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
11281 // before presenting.
11282 if (source_texture->target() == GL_TEXTURE_EXTERNAL_OES) {
11283 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
11284 // instead of using kIdentityMatrix crbug.com/226218.
11285 copy_texture_CHROMIUM_->DoCopyTextureWithTransform(
11286 this, source_texture->target(), source_texture->service_id(),
11287 dest_texture->service_id(), source_width, source_height, unpack_flip_y_,
11288 unpack_premultiply_alpha_, unpack_unpremultiply_alpha_,
11289 kIdentityMatrix);
11290 } else {
11291 copy_texture_CHROMIUM_->DoCopyTexture(
11292 this, source_texture->target(), source_texture->service_id(),
11293 source_internal_format, dest_texture->service_id(), internal_format,
11294 source_width, source_height, unpack_flip_y_, unpack_premultiply_alpha_,
11295 unpack_unpremultiply_alpha_);
11298 DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
11301 void GLES2DecoderImpl::DoCopySubTextureCHROMIUM(GLenum target,
11302 GLuint source_id,
11303 GLuint dest_id,
11304 GLint xoffset,
11305 GLint yoffset) {
11306 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopySubTextureCHROMIUM");
11308 TextureRef* source_texture_ref = GetTexture(source_id);
11309 TextureRef* dest_texture_ref = GetTexture(dest_id);
11310 Texture* source_texture = source_texture_ref->texture();
11311 Texture* dest_texture = dest_texture_ref->texture();
11312 int source_width = 0;
11313 int source_height = 0;
11314 gfx::GLImage* image =
11315 source_texture->GetLevelImage(source_texture->target(), 0);
11316 if (image) {
11317 gfx::Size size = image->GetSize();
11318 source_width = size.width();
11319 source_height = size.height();
11320 if (source_width <= 0 || source_height <= 0) {
11321 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
11322 "invalid image size");
11323 return;
11325 } else {
11326 if (!source_texture->GetLevelSize(source_texture->target(), 0,
11327 &source_width, &source_height)) {
11328 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
11329 "source texture has no level 0");
11330 return;
11333 // Check that this type of texture is allowed.
11334 if (!texture_manager()->ValidForTarget(source_texture->target(), 0,
11335 source_width, source_height, 1)) {
11336 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
11337 "source texture bad dimensions");
11338 return;
11342 GLenum source_type = 0;
11343 GLenum source_internal_format = 0;
11344 source_texture->GetLevelType(source_texture->target(), 0, &source_type,
11345 &source_internal_format);
11346 GLenum dest_type = 0;
11347 GLenum dest_internal_format = 0;
11348 bool dest_level_defined = dest_texture->GetLevelType(
11349 dest_texture->target(), 0, &dest_type, &dest_internal_format);
11350 if (!dest_level_defined) {
11351 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCopySubTextureCHROMIUM",
11352 "destination texture is not defined");
11353 return;
11355 if (!dest_texture->ValidForTexture(dest_texture->target(), 0, xoffset,
11356 yoffset, source_width, source_height,
11357 dest_type)) {
11358 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
11359 "destination texture bad dimensions.");
11360 return;
11363 if (!ValidateCopyTextureCHROMIUM("glCopySubTextureCHROMIUM", target,
11364 source_texture_ref, dest_texture_ref,
11365 dest_internal_format)) {
11366 return;
11369 // Clear the source texture if necessary.
11370 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref,
11371 source_texture->target(), 0)) {
11372 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopySubTextureCHROMIUM",
11373 "source texture dimensions too big");
11374 return;
11377 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
11378 // needed because it takes 10s of milliseconds to initialize.
11379 if (!copy_texture_CHROMIUM_.get()) {
11380 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopySubTextureCHROMIUM");
11381 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
11382 copy_texture_CHROMIUM_->Initialize(this);
11383 RestoreCurrentFramebufferBindings();
11384 if (LOCAL_PEEK_GL_ERROR("glCopySubTextureCHROMIUM") != GL_NO_ERROR)
11385 return;
11388 int dest_width = 0;
11389 int dest_height = 0;
11390 bool ok =
11391 dest_texture->GetLevelSize(GL_TEXTURE_2D, 0, &dest_width, &dest_height);
11392 DCHECK(ok);
11393 if (xoffset != 0 || yoffset != 0 || source_width != dest_width ||
11394 source_height != dest_height) {
11395 if (!texture_manager()->ClearTextureLevel(this, dest_texture_ref, target,
11396 0)) {
11397 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopySubTextureCHROMIUM",
11398 "destination texture dimensions too big");
11399 return;
11401 } else {
11402 texture_manager()->SetLevelCleared(dest_texture_ref, GL_TEXTURE_2D, 0,
11403 true);
11406 ScopedModifyPixels modify(dest_texture_ref);
11408 // Try using GLImage::CopyTexSubImage when possible.
11409 bool unpack_premultiply_alpha_change =
11410 unpack_premultiply_alpha_ ^ unpack_unpremultiply_alpha_;
11411 if (image && !unpack_flip_y_ && !unpack_premultiply_alpha_change &&
11412 !xoffset && !yoffset) {
11413 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
11414 if (image->CopyTexImage(GL_TEXTURE_2D))
11415 return;
11418 DoWillUseTexImageIfNeeded(source_texture, source_texture->target());
11420 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
11421 // before presenting.
11422 if (source_texture->target() == GL_TEXTURE_EXTERNAL_OES) {
11423 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
11424 // instead of using kIdentityMatrix crbug.com/226218.
11425 copy_texture_CHROMIUM_->DoCopySubTextureWithTransform(
11426 this, source_texture->target(), source_texture->service_id(),
11427 dest_texture->service_id(), xoffset, yoffset, dest_width, dest_height,
11428 source_width, source_height, unpack_flip_y_, unpack_premultiply_alpha_,
11429 unpack_unpremultiply_alpha_, kIdentityMatrix);
11430 } else {
11431 copy_texture_CHROMIUM_->DoCopySubTexture(
11432 this, source_texture->target(), source_texture->service_id(),
11433 source_internal_format, dest_texture->service_id(),
11434 dest_internal_format, xoffset, yoffset, dest_width, dest_height,
11435 source_width, source_height, unpack_flip_y_, unpack_premultiply_alpha_,
11436 unpack_unpremultiply_alpha_);
11439 DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
11442 static GLenum ExtractTypeFromStorageFormat(GLenum internalformat) {
11443 switch (internalformat) {
11444 case GL_RGB565:
11445 return GL_UNSIGNED_SHORT_5_6_5;
11446 case GL_RGBA4:
11447 return GL_UNSIGNED_SHORT_4_4_4_4;
11448 case GL_RGB5_A1:
11449 return GL_UNSIGNED_SHORT_5_5_5_1;
11450 case GL_RGB8_OES:
11451 return GL_UNSIGNED_BYTE;
11452 case GL_RGBA8_OES:
11453 return GL_UNSIGNED_BYTE;
11454 case GL_LUMINANCE8_ALPHA8_EXT:
11455 return GL_UNSIGNED_BYTE;
11456 case GL_LUMINANCE8_EXT:
11457 return GL_UNSIGNED_BYTE;
11458 case GL_ALPHA8_EXT:
11459 return GL_UNSIGNED_BYTE;
11460 case GL_RGBA32F_EXT:
11461 return GL_FLOAT;
11462 case GL_RGB32F_EXT:
11463 return GL_FLOAT;
11464 case GL_ALPHA32F_EXT:
11465 return GL_FLOAT;
11466 case GL_LUMINANCE32F_EXT:
11467 return GL_FLOAT;
11468 case GL_LUMINANCE_ALPHA32F_EXT:
11469 return GL_FLOAT;
11470 case GL_RGBA16F_EXT:
11471 return GL_HALF_FLOAT_OES;
11472 case GL_RGB16F_EXT:
11473 return GL_HALF_FLOAT_OES;
11474 case GL_ALPHA16F_EXT:
11475 return GL_HALF_FLOAT_OES;
11476 case GL_LUMINANCE16F_EXT:
11477 return GL_HALF_FLOAT_OES;
11478 case GL_LUMINANCE_ALPHA16F_EXT:
11479 return GL_HALF_FLOAT_OES;
11480 case GL_BGRA8_EXT:
11481 return GL_UNSIGNED_BYTE;
11482 default:
11483 return GL_NONE;
11487 void GLES2DecoderImpl::DoTexStorage2DEXT(
11488 GLenum target,
11489 GLint levels,
11490 GLenum internal_format,
11491 GLsizei width,
11492 GLsizei height) {
11493 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT",
11494 "width", width, "height", height);
11495 if (!texture_manager()->ValidForTarget(target, 0, width, height, 1) ||
11496 TextureManager::ComputeMipMapCount(target, width, height, 1) < levels) {
11497 LOCAL_SET_GL_ERROR(
11498 GL_INVALID_VALUE, "glTexStorage2DEXT", "dimensions out of range");
11499 return;
11501 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
11502 &state_, target);
11503 if (!texture_ref) {
11504 LOCAL_SET_GL_ERROR(
11505 GL_INVALID_OPERATION,
11506 "glTexStorage2DEXT", "unknown texture for target");
11507 return;
11509 Texture* texture = texture_ref->texture();
11510 if (texture->IsAttachedToFramebuffer()) {
11511 framebuffer_state_.clear_state_dirty = true;
11513 if (texture->IsImmutable()) {
11514 LOCAL_SET_GL_ERROR(
11515 GL_INVALID_OPERATION,
11516 "glTexStorage2DEXT", "texture is immutable");
11517 return;
11520 GLenum format = ExtractFormatFromStorageFormat(internal_format);
11521 GLenum type = ExtractTypeFromStorageFormat(internal_format);
11524 GLsizei level_width = width;
11525 GLsizei level_height = height;
11526 uint32 estimated_size = 0;
11527 for (int ii = 0; ii < levels; ++ii) {
11528 uint32 level_size = 0;
11529 if (!GLES2Util::ComputeImageDataSizes(
11530 level_width, level_height, 1, format, type, state_.unpack_alignment,
11531 &estimated_size, NULL, NULL) ||
11532 !SafeAddUint32(estimated_size, level_size, &estimated_size)) {
11533 LOCAL_SET_GL_ERROR(
11534 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "dimensions too large");
11535 return;
11537 level_width = std::max(1, level_width >> 1);
11538 level_height = std::max(1, level_height >> 1);
11540 if (!EnsureGPUMemoryAvailable(estimated_size)) {
11541 LOCAL_SET_GL_ERROR(
11542 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "out of memory");
11543 return;
11547 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexStorage2DEXT");
11548 glTexStorage2DEXT(target, levels, internal_format, width, height);
11549 GLenum error = LOCAL_PEEK_GL_ERROR("glTexStorage2DEXT");
11550 if (error == GL_NO_ERROR) {
11551 GLsizei level_width = width;
11552 GLsizei level_height = height;
11553 for (int ii = 0; ii < levels; ++ii) {
11554 texture_manager()->SetLevelInfo(
11555 texture_ref, target, ii, format,
11556 level_width, level_height, 1, 0, format, type, false);
11557 level_width = std::max(1, level_width >> 1);
11558 level_height = std::max(1, level_height >> 1);
11560 texture->SetImmutable(true);
11564 error::Error GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
11565 uint32 immediate_data_size,
11566 const void* cmd_data) {
11567 return error::kUnknownCommand;
11570 void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target,
11571 const GLbyte* data) {
11572 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureCHROMIUM",
11573 "context", logger_.GetLogPrefix(),
11574 "mailbox[0]", static_cast<unsigned char>(data[0]));
11576 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
11577 &state_, target);
11578 ProduceTextureRef("glProduceTextureCHROMIUM", texture_ref, target, data);
11581 void GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM(GLuint client_id,
11582 GLenum target, const GLbyte* data) {
11583 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM",
11584 "context", logger_.GetLogPrefix(),
11585 "mailbox[0]", static_cast<unsigned char>(data[0]));
11587 ProduceTextureRef("glProduceTextureDirectCHROMIUM", GetTexture(client_id),
11588 target, data);
11591 void GLES2DecoderImpl::ProduceTextureRef(std::string func_name,
11592 TextureRef* texture_ref, GLenum target, const GLbyte* data) {
11593 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
11594 DLOG_IF(ERROR, !mailbox.Verify()) << func_name << " was passed a "
11595 "mailbox that was not generated by "
11596 "GenMailboxCHROMIUM.";
11598 if (!texture_ref) {
11599 LOCAL_SET_GL_ERROR(
11600 GL_INVALID_OPERATION, func_name.c_str(), "unknown texture for target");
11601 return;
11604 Texture* produced = texture_manager()->Produce(texture_ref);
11605 if (!produced) {
11606 LOCAL_SET_GL_ERROR(
11607 GL_INVALID_OPERATION, func_name.c_str(), "invalid texture");
11608 return;
11611 if (produced->target() != target) {
11612 LOCAL_SET_GL_ERROR(
11613 GL_INVALID_OPERATION, func_name.c_str(), "invalid target");
11614 return;
11617 group_->mailbox_manager()->ProduceTexture(mailbox, produced);
11620 void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target,
11621 const GLbyte* data) {
11622 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoConsumeTextureCHROMIUM",
11623 "context", logger_.GetLogPrefix(),
11624 "mailbox[0]", static_cast<unsigned char>(data[0]));
11625 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
11626 DLOG_IF(ERROR, !mailbox.Verify()) << "ConsumeTextureCHROMIUM was passed a "
11627 "mailbox that was not generated by "
11628 "GenMailboxCHROMIUM.";
11630 scoped_refptr<TextureRef> texture_ref =
11631 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
11632 if (!texture_ref.get()) {
11633 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
11634 "glConsumeTextureCHROMIUM",
11635 "unknown texture for target");
11636 return;
11638 GLuint client_id = texture_ref->client_id();
11639 if (!client_id) {
11640 LOCAL_SET_GL_ERROR(
11641 GL_INVALID_OPERATION,
11642 "glConsumeTextureCHROMIUM", "unknown texture for target");
11643 return;
11645 Texture* texture = group_->mailbox_manager()->ConsumeTexture(mailbox);
11646 if (!texture) {
11647 LOCAL_SET_GL_ERROR(
11648 GL_INVALID_OPERATION,
11649 "glConsumeTextureCHROMIUM", "invalid mailbox name");
11650 return;
11652 if (texture->target() != target) {
11653 LOCAL_SET_GL_ERROR(
11654 GL_INVALID_OPERATION,
11655 "glConsumeTextureCHROMIUM", "invalid target");
11656 return;
11659 DeleteTexturesHelper(1, &client_id);
11660 texture_ref = texture_manager()->Consume(client_id, texture);
11661 glBindTexture(target, texture_ref->service_id());
11663 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
11664 unit.bind_target = target;
11665 switch (target) {
11666 case GL_TEXTURE_2D:
11667 unit.bound_texture_2d = texture_ref;
11668 break;
11669 case GL_TEXTURE_CUBE_MAP:
11670 unit.bound_texture_cube_map = texture_ref;
11671 break;
11672 case GL_TEXTURE_EXTERNAL_OES:
11673 unit.bound_texture_external_oes = texture_ref;
11674 break;
11675 case GL_TEXTURE_RECTANGLE_ARB:
11676 unit.bound_texture_rectangle_arb = texture_ref;
11677 break;
11678 default:
11679 NOTREACHED(); // Validation should prevent us getting here.
11680 break;
11684 void GLES2DecoderImpl::EnsureTextureForClientId(
11685 GLenum target,
11686 GLuint client_id) {
11687 TextureRef* texture_ref = GetTexture(client_id);
11688 if (!texture_ref) {
11689 GLuint service_id;
11690 glGenTextures(1, &service_id);
11691 DCHECK_NE(0u, service_id);
11692 texture_ref = CreateTexture(client_id, service_id);
11693 texture_manager()->SetTarget(texture_ref, target);
11694 glBindTexture(target, service_id);
11695 RestoreCurrentTextureBindings(&state_, target);
11699 // If CreateAndConsumeTexture fails we still need to ensure that the client_id
11700 // provided is associated with a service_id/TextureRef for consistency, even if
11701 // the resulting texture is incomplete.
11702 error::Error GLES2DecoderImpl::HandleCreateAndConsumeTextureCHROMIUMImmediate(
11703 uint32_t immediate_data_size,
11704 const void* cmd_data) {
11705 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate& c =
11706 *static_cast<
11707 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate*>(
11708 cmd_data);
11709 GLenum target = static_cast<GLenum>(c.target);
11710 uint32_t data_size;
11711 if (!ComputeDataSize(1, sizeof(GLbyte), 64, &data_size)) {
11712 return error::kOutOfBounds;
11714 if (data_size > immediate_data_size) {
11715 return error::kOutOfBounds;
11717 const GLbyte* mailbox =
11718 GetImmediateDataAs<const GLbyte*>(c, data_size, immediate_data_size);
11719 if (!validators_->texture_bind_target.IsValid(target)) {
11720 LOCAL_SET_GL_ERROR_INVALID_ENUM(
11721 "glCreateAndConsumeTextureCHROMIUM", target, "target");
11722 return error::kNoError;
11724 if (mailbox == NULL) {
11725 return error::kOutOfBounds;
11727 uint32_t client_id = c.client_id;
11728 DoCreateAndConsumeTextureCHROMIUM(target, mailbox, client_id);
11729 return error::kNoError;
11732 void GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM(GLenum target,
11733 const GLbyte* data, GLuint client_id) {
11734 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM",
11735 "context", logger_.GetLogPrefix(),
11736 "mailbox[0]", static_cast<unsigned char>(data[0]));
11737 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
11738 DLOG_IF(ERROR, !mailbox.Verify()) << "CreateAndConsumeTextureCHROMIUM was "
11739 "passed a mailbox that was not "
11740 "generated by GenMailboxCHROMIUM.";
11742 TextureRef* texture_ref = GetTexture(client_id);
11743 if (texture_ref) {
11744 // No need to call EnsureTextureForClientId here, the client_id already has
11745 // an associated texture.
11746 LOCAL_SET_GL_ERROR(
11747 GL_INVALID_OPERATION,
11748 "glCreateAndConsumeTextureCHROMIUM", "client id already in use");
11749 return;
11751 Texture* texture = group_->mailbox_manager()->ConsumeTexture(mailbox);
11752 if (!texture) {
11753 EnsureTextureForClientId(target, client_id);
11754 LOCAL_SET_GL_ERROR(
11755 GL_INVALID_OPERATION,
11756 "glCreateAndConsumeTextureCHROMIUM", "invalid mailbox name");
11757 return;
11760 if (texture->target() != target) {
11761 EnsureTextureForClientId(target, client_id);
11762 LOCAL_SET_GL_ERROR(
11763 GL_INVALID_OPERATION,
11764 "glCreateAndConsumeTextureCHROMIUM", "invalid target");
11765 return;
11768 texture_ref = texture_manager()->Consume(client_id, texture);
11771 bool GLES2DecoderImpl::DoIsValuebufferCHROMIUM(GLuint client_id) {
11772 const Valuebuffer* valuebuffer = GetValuebuffer(client_id);
11773 return valuebuffer && valuebuffer->IsValid();
11776 void GLES2DecoderImpl::DoBindValueBufferCHROMIUM(GLenum target,
11777 GLuint client_id) {
11778 Valuebuffer* valuebuffer = NULL;
11779 if (client_id != 0) {
11780 valuebuffer = GetValuebuffer(client_id);
11781 if (!valuebuffer) {
11782 if (!group_->bind_generates_resource()) {
11783 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glBindValuebufferCHROMIUM",
11784 "id not generated by glBindValuebufferCHROMIUM");
11785 return;
11788 // It's a new id so make a valuebuffer for it.
11789 CreateValuebuffer(client_id);
11790 valuebuffer = GetValuebuffer(client_id);
11792 valuebuffer->MarkAsValid();
11794 state_.bound_valuebuffer = valuebuffer;
11797 void GLES2DecoderImpl::DoSubscribeValueCHROMIUM(GLenum target,
11798 GLenum subscription) {
11799 if (!CheckCurrentValuebuffer("glSubscribeValueCHROMIUM")) {
11800 return;
11802 state_.bound_valuebuffer.get()->AddSubscription(subscription);
11805 void GLES2DecoderImpl::DoPopulateSubscribedValuesCHROMIUM(GLenum target) {
11806 if (!CheckCurrentValuebuffer("glPopulateSubscribedValuesCHROMIUM")) {
11807 return;
11809 valuebuffer_manager()->UpdateValuebufferState(state_.bound_valuebuffer.get());
11812 void GLES2DecoderImpl::DoUniformValueBufferCHROMIUM(GLint location,
11813 GLenum target,
11814 GLenum subscription) {
11815 if (!CheckCurrentValuebufferForSubscription(
11816 subscription, "glPopulateSubscribedValuesCHROMIUM")) {
11817 return;
11819 if (!CheckSubscriptionTarget(location, subscription,
11820 "glPopulateSubscribedValuesCHROMIUM")) {
11821 return;
11823 const ValueState* state =
11824 state_.bound_valuebuffer.get()->GetState(subscription);
11825 if (state) {
11826 switch (subscription) {
11827 case GL_MOUSE_POSITION_CHROMIUM:
11828 DoUniform2iv(location, 1, state->int_value);
11829 break;
11830 default:
11831 NOTREACHED() << "Unhandled uniform subscription target "
11832 << subscription;
11833 break;
11838 void GLES2DecoderImpl::DoInsertEventMarkerEXT(
11839 GLsizei length, const GLchar* marker) {
11840 if (!marker) {
11841 marker = "";
11843 debug_marker_manager_.SetMarker(
11844 length ? std::string(marker, length) : std::string(marker));
11847 void GLES2DecoderImpl::DoPushGroupMarkerEXT(
11848 GLsizei length, const GLchar* marker) {
11849 if (!marker) {
11850 marker = "";
11852 std::string name = length ? std::string(marker, length) : std::string(marker);
11853 debug_marker_manager_.PushGroup(name);
11854 gpu_tracer_->Begin(TRACE_DISABLED_BY_DEFAULT("gpu_group_marker"), name,
11855 kTraceGroupMarker);
11858 void GLES2DecoderImpl::DoPopGroupMarkerEXT(void) {
11859 debug_marker_manager_.PopGroup();
11860 gpu_tracer_->End(kTraceGroupMarker);
11863 void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(
11864 GLenum target, GLint image_id) {
11865 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM");
11867 if (target == GL_TEXTURE_CUBE_MAP) {
11868 LOCAL_SET_GL_ERROR(
11869 GL_INVALID_ENUM,
11870 "glBindTexImage2DCHROMIUM", "invalid target");
11871 return;
11874 // Default target might be conceptually valid, but disallow it to avoid
11875 // accidents.
11876 TextureRef* texture_ref =
11877 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
11878 if (!texture_ref) {
11879 LOCAL_SET_GL_ERROR(
11880 GL_INVALID_OPERATION,
11881 "glBindTexImage2DCHROMIUM", "no texture bound");
11882 return;
11885 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
11886 if (!gl_image) {
11887 LOCAL_SET_GL_ERROR(
11888 GL_INVALID_OPERATION,
11889 "glBindTexImage2DCHROMIUM", "no image found with the given ID");
11890 return;
11894 ScopedGLErrorSuppressor suppressor(
11895 "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", GetErrorState());
11896 if (!gl_image->BindTexImage(target)) {
11897 LOCAL_SET_GL_ERROR(
11898 GL_INVALID_OPERATION,
11899 "glBindTexImage2DCHROMIUM", "fail to bind image with the given ID");
11900 return;
11904 gfx::Size size = gl_image->GetSize();
11905 texture_manager()->SetLevelInfo(
11906 texture_ref, target, 0, GL_RGBA, size.width(), size.height(), 1, 0,
11907 GL_RGBA, GL_UNSIGNED_BYTE, true);
11908 texture_manager()->SetLevelImage(texture_ref, target, 0, gl_image);
11911 void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(
11912 GLenum target, GLint image_id) {
11913 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM");
11915 // Default target might be conceptually valid, but disallow it to avoid
11916 // accidents.
11917 TextureRef* texture_ref =
11918 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
11919 if (!texture_ref) {
11920 LOCAL_SET_GL_ERROR(
11921 GL_INVALID_OPERATION,
11922 "glReleaseTexImage2DCHROMIUM", "no texture bound");
11923 return;
11926 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
11927 if (!gl_image) {
11928 LOCAL_SET_GL_ERROR(
11929 GL_INVALID_OPERATION,
11930 "glReleaseTexImage2DCHROMIUM", "no image found with the given ID");
11931 return;
11934 // Do nothing when image is not currently bound.
11935 if (texture_ref->texture()->GetLevelImage(target, 0) != gl_image)
11936 return;
11939 ScopedGLErrorSuppressor suppressor(
11940 "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", GetErrorState());
11941 gl_image->ReleaseTexImage(target);
11944 texture_manager()->SetLevelInfo(
11945 texture_ref, target, 0, GL_RGBA, 0, 0, 1, 0,
11946 GL_RGBA, GL_UNSIGNED_BYTE, false);
11949 error::Error GLES2DecoderImpl::HandleTraceBeginCHROMIUM(
11950 uint32 immediate_data_size,
11951 const void* cmd_data) {
11952 const gles2::cmds::TraceBeginCHROMIUM& c =
11953 *static_cast<const gles2::cmds::TraceBeginCHROMIUM*>(cmd_data);
11954 Bucket* category_bucket = GetBucket(c.category_bucket_id);
11955 Bucket* name_bucket = GetBucket(c.name_bucket_id);
11956 if (!category_bucket || category_bucket->size() == 0 ||
11957 !name_bucket || name_bucket->size() == 0) {
11958 return error::kInvalidArguments;
11961 std::string category_name;
11962 std::string trace_name;
11963 if (!category_bucket->GetAsString(&category_name) ||
11964 !name_bucket->GetAsString(&trace_name)) {
11965 return error::kInvalidArguments;
11968 if (!gpu_tracer_->Begin(category_name, trace_name, kTraceCHROMIUM)) {
11969 LOCAL_SET_GL_ERROR(
11970 GL_INVALID_OPERATION,
11971 "glTraceBeginCHROMIUM", "unable to create begin trace");
11972 return error::kNoError;
11974 return error::kNoError;
11977 void GLES2DecoderImpl::DoTraceEndCHROMIUM() {
11978 if (!gpu_tracer_->End(kTraceCHROMIUM)) {
11979 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
11980 "glTraceEndCHROMIUM", "no trace begin found");
11981 return;
11985 void GLES2DecoderImpl::DoDrawBuffersEXT(
11986 GLsizei count, const GLenum* bufs) {
11987 if (count > static_cast<GLsizei>(group_->max_draw_buffers())) {
11988 LOCAL_SET_GL_ERROR(
11989 GL_INVALID_VALUE,
11990 "glDrawBuffersEXT", "greater than GL_MAX_DRAW_BUFFERS_EXT");
11991 return;
11994 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
11995 if (framebuffer) {
11996 for (GLsizei i = 0; i < count; ++i) {
11997 if (bufs[i] != static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i) &&
11998 bufs[i] != GL_NONE) {
11999 LOCAL_SET_GL_ERROR(
12000 GL_INVALID_OPERATION,
12001 "glDrawBuffersEXT",
12002 "bufs[i] not GL_NONE or GL_COLOR_ATTACHMENTi_EXT");
12003 return;
12006 glDrawBuffersARB(count, bufs);
12007 framebuffer->SetDrawBuffers(count, bufs);
12008 } else { // backbuffer
12009 if (count > 1 ||
12010 (bufs[0] != GL_BACK && bufs[0] != GL_NONE)) {
12011 LOCAL_SET_GL_ERROR(
12012 GL_INVALID_OPERATION,
12013 "glDrawBuffersEXT",
12014 "more than one buffer or bufs not GL_NONE or GL_BACK");
12015 return;
12017 GLenum mapped_buf = bufs[0];
12018 if (GetBackbufferServiceId() != 0 && // emulated backbuffer
12019 bufs[0] == GL_BACK) {
12020 mapped_buf = GL_COLOR_ATTACHMENT0;
12022 glDrawBuffersARB(count, &mapped_buf);
12023 group_->set_draw_buffer(bufs[0]);
12027 void GLES2DecoderImpl::DoLoseContextCHROMIUM(GLenum current, GLenum other) {
12028 group_->LoseContexts(other);
12029 reset_status_ = current;
12030 current_decoder_error_ = error::kLostContext;
12033 void GLES2DecoderImpl::DoMatrixLoadfCHROMIUM(GLenum matrix_mode,
12034 const GLfloat* matrix) {
12035 DCHECK(matrix_mode == GL_PATH_PROJECTION_CHROMIUM ||
12036 matrix_mode == GL_PATH_MODELVIEW_CHROMIUM);
12037 if (!features().chromium_path_rendering) {
12038 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
12039 "glMatrixLoadfCHROMIUM",
12040 "function not available");
12041 return;
12044 GLfloat* target_matrix = matrix_mode == GL_PATH_PROJECTION_CHROMIUM
12045 ? state_.projection_matrix
12046 : state_.modelview_matrix;
12047 memcpy(target_matrix, matrix, sizeof(GLfloat) * 16);
12048 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
12049 // since the values of the _NV and _CHROMIUM tokens match.
12050 glMatrixLoadfEXT(matrix_mode, matrix);
12053 void GLES2DecoderImpl::DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode) {
12054 DCHECK(matrix_mode == GL_PATH_PROJECTION_CHROMIUM ||
12055 matrix_mode == GL_PATH_MODELVIEW_CHROMIUM);
12057 if (!features().chromium_path_rendering) {
12058 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
12059 "glMatrixLoadIdentityCHROMIUM",
12060 "function not available");
12061 return;
12064 GLfloat* target_matrix = matrix_mode == GL_PATH_PROJECTION_CHROMIUM
12065 ? state_.projection_matrix
12066 : state_.modelview_matrix;
12067 memcpy(target_matrix, kIdentityMatrix, sizeof(kIdentityMatrix));
12068 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
12069 // since the values of the _NV and _CHROMIUM tokens match.
12070 glMatrixLoadIdentityEXT(matrix_mode);
12073 bool GLES2DecoderImpl::ValidateAsyncTransfer(
12074 const char* function_name,
12075 TextureRef* texture_ref,
12076 GLenum target,
12077 GLint level,
12078 const void * data) {
12079 // We only support async uploads to 2D textures for now.
12080 if (GL_TEXTURE_2D != target) {
12081 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
12082 return false;
12084 // We only support uploads to level zero for now.
12085 if (level != 0) {
12086 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "level != 0");
12087 return false;
12089 // A transfer buffer must be bound, even for asyncTexImage2D.
12090 if (data == NULL) {
12091 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, "buffer == 0");
12092 return false;
12094 // We only support one async transfer in progress.
12095 if (!texture_ref ||
12096 async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
12097 LOCAL_SET_GL_ERROR(
12098 GL_INVALID_OPERATION,
12099 function_name, "transfer already in progress");
12100 return false;
12102 return true;
12105 base::Closure GLES2DecoderImpl::AsyncUploadTokenCompletionClosure(
12106 uint32 async_upload_token,
12107 uint32 sync_data_shm_id,
12108 uint32 sync_data_shm_offset) {
12109 scoped_refptr<gpu::Buffer> buffer = GetSharedMemoryBuffer(sync_data_shm_id);
12110 if (!buffer.get() ||
12111 !buffer->GetDataAddress(sync_data_shm_offset, sizeof(AsyncUploadSync)))
12112 return base::Closure();
12114 AsyncMemoryParams mem_params(buffer,
12115 sync_data_shm_offset,
12116 sizeof(AsyncUploadSync));
12118 scoped_refptr<AsyncUploadTokenCompletionObserver> observer(
12119 new AsyncUploadTokenCompletionObserver(async_upload_token));
12121 return base::Bind(
12122 &AsyncPixelTransferManager::AsyncNotifyCompletion,
12123 base::Unretained(GetAsyncPixelTransferManager()),
12124 mem_params,
12125 observer);
12128 error::Error GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM(
12129 uint32 immediate_data_size,
12130 const void* cmd_data) {
12131 const gles2::cmds::AsyncTexImage2DCHROMIUM& c =
12132 *static_cast<const gles2::cmds::AsyncTexImage2DCHROMIUM*>(cmd_data);
12133 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM");
12134 GLenum target = static_cast<GLenum>(c.target);
12135 GLint level = static_cast<GLint>(c.level);
12136 GLenum internal_format = static_cast<GLenum>(c.internalformat);
12137 GLsizei width = static_cast<GLsizei>(c.width);
12138 GLsizei height = static_cast<GLsizei>(c.height);
12139 GLint border = static_cast<GLint>(c.border);
12140 GLenum format = static_cast<GLenum>(c.format);
12141 GLenum type = static_cast<GLenum>(c.type);
12142 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
12143 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
12144 uint32 pixels_size;
12145 uint32 async_upload_token = static_cast<uint32>(c.async_upload_token);
12146 uint32 sync_data_shm_id = static_cast<uint32>(c.sync_data_shm_id);
12147 uint32 sync_data_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
12149 base::ScopedClosureRunner scoped_completion_callback;
12150 if (async_upload_token) {
12151 base::Closure completion_closure =
12152 AsyncUploadTokenCompletionClosure(async_upload_token,
12153 sync_data_shm_id,
12154 sync_data_shm_offset);
12155 if (completion_closure.is_null())
12156 return error::kInvalidArguments;
12158 scoped_completion_callback.Reset(completion_closure);
12161 // TODO(epenner): Move this and copies of this memory validation
12162 // into ValidateTexImage2D step.
12163 if (!GLES2Util::ComputeImageDataSizes(
12164 width, height, 1, format, type, state_.unpack_alignment, &pixels_size,
12165 NULL, NULL)) {
12166 return error::kOutOfBounds;
12168 const void* pixels = NULL;
12169 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
12170 pixels = GetSharedMemoryAs<const void*>(
12171 pixels_shm_id, pixels_shm_offset, pixels_size);
12172 if (!pixels) {
12173 return error::kOutOfBounds;
12177 TextureManager::DoTextImage2DArguments args = {
12178 target, level, internal_format, width, height, border, format, type,
12179 pixels, pixels_size};
12180 TextureRef* texture_ref;
12181 // All the normal glTexSubImage2D validation.
12182 if (!texture_manager()->ValidateTexImage2D(
12183 &state_, "glAsyncTexImage2DCHROMIUM", args, &texture_ref)) {
12184 return error::kNoError;
12187 // Extra async validation.
12188 Texture* texture = texture_ref->texture();
12189 if (!ValidateAsyncTransfer(
12190 "glAsyncTexImage2DCHROMIUM", texture_ref, target, level, pixels))
12191 return error::kNoError;
12193 // Don't allow async redefinition of a textures.
12194 if (texture->IsDefined()) {
12195 LOCAL_SET_GL_ERROR(
12196 GL_INVALID_OPERATION,
12197 "glAsyncTexImage2DCHROMIUM", "already defined");
12198 return error::kNoError;
12201 if (!EnsureGPUMemoryAvailable(pixels_size)) {
12202 LOCAL_SET_GL_ERROR(
12203 GL_OUT_OF_MEMORY, "glAsyncTexImage2DCHROMIUM", "out of memory");
12204 return error::kNoError;
12207 // Setup the parameters.
12208 AsyncTexImage2DParams tex_params = {
12209 target, level, static_cast<GLenum>(internal_format),
12210 width, height, border, format, type};
12211 AsyncMemoryParams mem_params(
12212 GetSharedMemoryBuffer(c.pixels_shm_id), c.pixels_shm_offset, pixels_size);
12214 // Set up the async state if needed, and make the texture
12215 // immutable so the async state stays valid. The level info
12216 // is set up lazily when the transfer completes.
12217 AsyncPixelTransferDelegate* delegate =
12218 async_pixel_transfer_manager_->CreatePixelTransferDelegate(texture_ref,
12219 tex_params);
12220 texture->SetImmutable(true);
12222 delegate->AsyncTexImage2D(
12223 tex_params,
12224 mem_params,
12225 base::Bind(&TextureManager::SetLevelInfoFromParams,
12226 // The callback is only invoked if the transfer delegate still
12227 // exists, which implies through manager->texture_ref->state
12228 // ownership that both of these pointers are valid.
12229 base::Unretained(texture_manager()),
12230 base::Unretained(texture_ref),
12231 tex_params));
12232 return error::kNoError;
12235 error::Error GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM(
12236 uint32 immediate_data_size,
12237 const void* cmd_data) {
12238 const gles2::cmds::AsyncTexSubImage2DCHROMIUM& c =
12239 *static_cast<const gles2::cmds::AsyncTexSubImage2DCHROMIUM*>(cmd_data);
12240 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM");
12241 GLenum target = static_cast<GLenum>(c.target);
12242 GLint level = static_cast<GLint>(c.level);
12243 GLint xoffset = static_cast<GLint>(c.xoffset);
12244 GLint yoffset = static_cast<GLint>(c.yoffset);
12245 GLsizei width = static_cast<GLsizei>(c.width);
12246 GLsizei height = static_cast<GLsizei>(c.height);
12247 GLenum format = static_cast<GLenum>(c.format);
12248 GLenum type = static_cast<GLenum>(c.type);
12249 uint32 async_upload_token = static_cast<uint32>(c.async_upload_token);
12250 uint32 sync_data_shm_id = static_cast<uint32>(c.sync_data_shm_id);
12251 uint32 sync_data_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
12253 base::ScopedClosureRunner scoped_completion_callback;
12254 if (async_upload_token) {
12255 base::Closure completion_closure =
12256 AsyncUploadTokenCompletionClosure(async_upload_token,
12257 sync_data_shm_id,
12258 sync_data_shm_offset);
12259 if (completion_closure.is_null())
12260 return error::kInvalidArguments;
12262 scoped_completion_callback.Reset(completion_closure);
12265 // TODO(epenner): Move this and copies of this memory validation
12266 // into ValidateTexSubImage2D step.
12267 uint32 data_size;
12268 if (!GLES2Util::ComputeImageDataSizes(
12269 width, height, 1, format, type, state_.unpack_alignment, &data_size,
12270 NULL, NULL)) {
12271 return error::kOutOfBounds;
12273 const void* pixels = GetSharedMemoryAs<const void*>(
12274 c.data_shm_id, c.data_shm_offset, data_size);
12276 // All the normal glTexSubImage2D validation.
12277 error::Error error = error::kNoError;
12278 if (!ValidateTexSubImage2D(&error, "glAsyncTexSubImage2DCHROMIUM",
12279 target, level, xoffset, yoffset, width, height, format, type, pixels)) {
12280 return error;
12283 // Extra async validation.
12284 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
12285 &state_, target);
12286 Texture* texture = texture_ref->texture();
12287 if (!ValidateAsyncTransfer(
12288 "glAsyncTexSubImage2DCHROMIUM", texture_ref, target, level, pixels))
12289 return error::kNoError;
12291 // Guarantee async textures are always 'cleared' as follows:
12292 // - AsyncTexImage2D can not redefine an existing texture
12293 // - AsyncTexImage2D must initialize the entire image via non-null buffer.
12294 // - AsyncTexSubImage2D clears synchronously if not already cleared.
12295 // - Textures become immutable after an async call.
12296 // This way we know in all cases that an async texture is always clear.
12297 if (!texture->SafeToRenderFrom()) {
12298 if (!texture_manager()->ClearTextureLevel(this, texture_ref,
12299 target, level)) {
12300 LOCAL_SET_GL_ERROR(
12301 GL_OUT_OF_MEMORY,
12302 "glAsyncTexSubImage2DCHROMIUM", "dimensions too big");
12303 return error::kNoError;
12307 // Setup the parameters.
12308 AsyncTexSubImage2DParams tex_params = {target, level, xoffset, yoffset,
12309 width, height, format, type};
12310 AsyncMemoryParams mem_params(
12311 GetSharedMemoryBuffer(c.data_shm_id), c.data_shm_offset, data_size);
12312 AsyncPixelTransferDelegate* delegate =
12313 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
12314 if (!delegate) {
12315 // TODO(epenner): We may want to enforce exclusive use
12316 // of async APIs in which case this should become an error,
12317 // (the texture should have been async defined).
12318 AsyncTexImage2DParams define_params = {target, level,
12319 0, 0, 0, 0, 0, 0};
12320 texture->GetLevelSize(target, level, &define_params.width,
12321 &define_params.height);
12322 texture->GetLevelType(target, level, &define_params.type,
12323 &define_params.internal_format);
12324 // Set up the async state if needed, and make the texture
12325 // immutable so the async state stays valid.
12326 delegate = async_pixel_transfer_manager_->CreatePixelTransferDelegate(
12327 texture_ref, define_params);
12328 texture->SetImmutable(true);
12331 delegate->AsyncTexSubImage2D(tex_params, mem_params);
12332 return error::kNoError;
12335 error::Error GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM(
12336 uint32 immediate_data_size,
12337 const void* cmd_data) {
12338 const gles2::cmds::WaitAsyncTexImage2DCHROMIUM& c =
12339 *static_cast<const gles2::cmds::WaitAsyncTexImage2DCHROMIUM*>(cmd_data);
12340 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
12341 GLenum target = static_cast<GLenum>(c.target);
12343 if (GL_TEXTURE_2D != target) {
12344 LOCAL_SET_GL_ERROR(
12345 GL_INVALID_ENUM, "glWaitAsyncTexImage2DCHROMIUM", "target");
12346 return error::kNoError;
12348 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
12349 &state_, target);
12350 if (!texture_ref) {
12351 LOCAL_SET_GL_ERROR(
12352 GL_INVALID_OPERATION,
12353 "glWaitAsyncTexImage2DCHROMIUM", "unknown texture");
12354 return error::kNoError;
12356 AsyncPixelTransferDelegate* delegate =
12357 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
12358 if (!delegate) {
12359 LOCAL_SET_GL_ERROR(
12360 GL_INVALID_OPERATION,
12361 "glWaitAsyncTexImage2DCHROMIUM", "No async transfer started");
12362 return error::kNoError;
12364 delegate->WaitForTransferCompletion();
12365 ProcessFinishedAsyncTransfers();
12366 return error::kNoError;
12369 error::Error GLES2DecoderImpl::HandleWaitAllAsyncTexImage2DCHROMIUM(
12370 uint32 immediate_data_size,
12371 const void* data) {
12372 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
12374 GetAsyncPixelTransferManager()->WaitAllAsyncTexImage2D();
12375 ProcessFinishedAsyncTransfers();
12376 return error::kNoError;
12379 error::Error GLES2DecoderImpl::HandleUniformBlockBinding(
12380 uint32_t immediate_data_size, const void* cmd_data) {
12381 if (!unsafe_es3_apis_enabled())
12382 return error::kUnknownCommand;
12383 const gles2::cmds::UniformBlockBinding& c =
12384 *static_cast<const gles2::cmds::UniformBlockBinding*>(cmd_data);
12385 GLuint client_id = c.program;
12386 GLuint index = static_cast<GLuint>(c.index);
12387 GLuint binding = static_cast<GLuint>(c.binding);
12388 Program* program = GetProgramInfoNotShader(
12389 client_id, "glUniformBlockBinding");
12390 if (!program) {
12391 return error::kNoError;
12393 GLuint service_id = program->service_id();
12394 glUniformBlockBinding(service_id, index, binding);
12395 return error::kNoError;
12398 error::Error GLES2DecoderImpl::HandleClientWaitSync(
12399 uint32_t immediate_data_size, const void* cmd_data) {
12400 if (!unsafe_es3_apis_enabled())
12401 return error::kUnknownCommand;
12402 const gles2::cmds::ClientWaitSync& c =
12403 *static_cast<const gles2::cmds::ClientWaitSync*>(cmd_data);
12404 GLuint sync = static_cast<GLuint>(c.sync);
12405 GLbitfield flags = static_cast<GLbitfield>(c.flags);
12406 GLuint64 timeout = GLES2Util::MapTwoUint32ToUint64(c.timeout_0, c.timeout_1);
12407 typedef cmds::ClientWaitSync::Result Result;
12408 Result* result_dst = GetSharedMemoryAs<Result*>(
12409 c.result_shm_id, c.result_shm_offset, sizeof(*result_dst));
12410 if (!result_dst) {
12411 return error::kOutOfBounds;
12413 if (*result_dst != GL_WAIT_FAILED) {
12414 return error::kInvalidArguments;
12416 GLsync service_sync = 0;
12417 if (!group_->GetSyncServiceId(sync, &service_sync)) {
12418 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "ClientWaitSync", "invalid sync");
12419 return error::kNoError;
12421 *result_dst = glClientWaitSync(service_sync, flags, timeout);
12422 return error::kNoError;
12425 error::Error GLES2DecoderImpl::HandleWaitSync(
12426 uint32_t immediate_data_size, const void* cmd_data) {
12427 if (!unsafe_es3_apis_enabled())
12428 return error::kUnknownCommand;
12429 const gles2::cmds::WaitSync& c =
12430 *static_cast<const gles2::cmds::WaitSync*>(cmd_data);
12431 GLuint sync = static_cast<GLuint>(c.sync);
12432 GLbitfield flags = static_cast<GLbitfield>(c.flags);
12433 GLuint64 timeout = GLES2Util::MapTwoUint32ToUint64(c.timeout_0, c.timeout_1);
12434 GLsync service_sync = 0;
12435 if (!group_->GetSyncServiceId(sync, &service_sync)) {
12436 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "WaitSync", "invalid sync");
12437 return error::kNoError;
12439 glWaitSync(service_sync, flags, timeout);
12440 return error::kNoError;
12443 error::Error GLES2DecoderImpl::HandleMapBufferRange(
12444 uint32_t immediate_data_size, const void* cmd_data) {
12445 if (!unsafe_es3_apis_enabled()) {
12446 return error::kUnknownCommand;
12448 const gles2::cmds::MapBufferRange& c =
12449 *static_cast<const gles2::cmds::MapBufferRange*>(cmd_data);
12450 GLenum target = static_cast<GLenum>(c.target);
12451 GLbitfield access = static_cast<GLbitfield>(c.access);
12452 GLintptr offset = static_cast<GLintptr>(c.offset);
12453 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
12455 typedef cmds::MapBufferRange::Result Result;
12456 Result* result = GetSharedMemoryAs<Result*>(
12457 c.result_shm_id, c.result_shm_offset, sizeof(*result));
12458 if (!result) {
12459 return error::kOutOfBounds;
12461 if (*result != 0) {
12462 *result = 0;
12463 return error::kInvalidArguments;
12465 int8_t* mem =
12466 GetSharedMemoryAs<int8_t*>(c.data_shm_id, c.data_shm_offset, size);
12467 if (!mem) {
12468 return error::kOutOfBounds;
12471 GLbitfield mask = GL_MAP_INVALIDATE_BUFFER_BIT;
12472 if ((access & mask) == mask) {
12473 // TODO(zmo): To be on the safe side, always map
12474 // GL_MAP_INVALIDATE_BUFFER_BIT to GL_MAP_INVALIDATE_RANGE_BIT.
12475 access = (access & ~GL_MAP_INVALIDATE_BUFFER_BIT);
12476 access = (access | GL_MAP_INVALIDATE_RANGE_BIT);
12478 // TODO(zmo): Always filter out GL_MAP_UNSYNCHRONIZED_BIT to get rid of
12479 // undefined behaviors.
12480 mask = GL_MAP_READ_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
12481 if ((access & mask) == mask) {
12482 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "MapBufferRange",
12483 "incompatible access bits");
12484 return error::kNoError;
12486 access = (access & ~GL_MAP_UNSYNCHRONIZED_BIT);
12487 if ((access & GL_MAP_WRITE_BIT) == GL_MAP_WRITE_BIT &&
12488 (access & GL_MAP_INVALIDATE_RANGE_BIT) == 0) {
12489 access = (access | GL_MAP_READ_BIT);
12491 void* ptr = glMapBufferRange(target, offset, size, access);
12492 if (ptr == nullptr) {
12493 return error::kNoError;
12495 Buffer* buffer = buffer_manager()->GetBufferInfoForTarget(&state_, target);
12496 DCHECK(buffer);
12497 buffer->SetMappedRange(offset, size, access, ptr,
12498 GetSharedMemoryBuffer(c.data_shm_id));
12499 if ((access & GL_MAP_INVALIDATE_RANGE_BIT) == 0) {
12500 memcpy(mem, ptr, size);
12502 *result = 1;
12503 return error::kNoError;
12506 error::Error GLES2DecoderImpl::HandleUnmapBuffer(
12507 uint32_t immediate_data_size, const void* cmd_data) {
12508 if (!unsafe_es3_apis_enabled()) {
12509 return error::kUnknownCommand;
12511 const gles2::cmds::UnmapBuffer& c =
12512 *static_cast<const gles2::cmds::UnmapBuffer*>(cmd_data);
12513 GLenum target = static_cast<GLenum>(c.target);
12515 Buffer* buffer = buffer_manager()->GetBufferInfoForTarget(&state_, target);
12516 if (!buffer) {
12517 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "UnmapBuffer", "no buffer bound");
12518 return error::kNoError;
12520 const Buffer::MappedRange* mapped_range = buffer->GetMappedRange();
12521 if (!mapped_range) {
12522 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "UnmapBuffer",
12523 "buffer is unmapped");
12524 return error::kNoError;
12526 if ((mapped_range->access & GL_MAP_WRITE_BIT) == 0 ||
12527 (mapped_range->access & GL_MAP_FLUSH_EXPLICIT_BIT) ==
12528 GL_MAP_FLUSH_EXPLICIT_BIT) {
12529 // If we don't need to write back, or explict flush is required, no copying
12530 // back is needed.
12531 } else {
12532 void* mem = mapped_range->GetShmPointer();
12533 if (!mem) {
12534 return error::kOutOfBounds;
12536 DCHECK(mapped_range->pointer);
12537 memcpy(mapped_range->pointer, mem, mapped_range->size);
12539 buffer->RemoveMappedRange();
12540 GLboolean rt = glUnmapBuffer(target);
12541 if (rt == GL_FALSE) {
12542 // At this point, we have already done the necessary validation, so
12543 // GL_FALSE indicates data corruption.
12544 // TODO(zmo): We could redo the map / copy data / unmap to recover, but
12545 // the second unmap could still return GL_FALSE. For now, we simply lose
12546 // the contexts in the share group.
12547 LOG(ERROR) << "glUnmapBuffer unexpectedly returned GL_FALSE";
12548 group_->LoseContexts(GL_INNOCENT_CONTEXT_RESET_ARB);
12549 reset_status_ = GL_GUILTY_CONTEXT_RESET_ARB;
12550 return error::kLostContext;
12552 return error::kNoError;
12555 void GLES2DecoderImpl::OnTextureRefDetachedFromFramebuffer(
12556 TextureRef* texture_ref) {
12557 Texture* texture = texture_ref->texture();
12558 DoDidUseTexImageIfNeeded(texture, texture->target());
12561 void GLES2DecoderImpl::OnContextLostError() {
12562 group_->LoseContexts(GL_UNKNOWN_CONTEXT_RESET_ARB);
12565 void GLES2DecoderImpl::OnOutOfMemoryError() {
12566 if (lose_context_when_out_of_memory_) {
12567 group_->LoseContexts(GL_UNKNOWN_CONTEXT_RESET_ARB);
12571 // Include the auto-generated part of this file. We split this because it means
12572 // we can easily edit the non-auto generated parts right here in this file
12573 // instead of having to edit some template or the code generator.
12574 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
12576 } // namespace gles2
12577 } // namespace gpu