Rewrite AndroidSyncSettings to be significantly simpler.
[chromium-blink-merge.git] / gpu / command_buffer / service / gles2_cmd_decoder.cc
blob8c24d3cd1df5f8e04a458d173ec5106f5d3971bd
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
7 #include <stdio.h>
9 #include <algorithm>
10 #include <list>
11 #include <map>
12 #include <stack>
13 #include <string>
14 #include <vector>
16 #include "base/at_exit.h"
17 #include "base/bind.h"
18 #include "base/callback_helpers.h"
19 #include "base/command_line.h"
20 #include "base/float_util.h"
21 #include "base/memory/scoped_ptr.h"
22 #include "base/numerics/safe_math.h"
23 #include "base/strings/string_number_conversions.h"
24 #include "base/strings/string_split.h"
25 #include "base/trace_event/trace_event.h"
26 #include "base/trace_event/trace_event_synthetic_delay.h"
27 #include "build/build_config.h"
28 #define GLES2_GPU_SERVICE 1
29 #include "gpu/command_buffer/common/debug_marker_manager.h"
30 #include "gpu/command_buffer/common/gles2_cmd_format.h"
31 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
32 #include "gpu/command_buffer/common/id_allocator.h"
33 #include "gpu/command_buffer/common/mailbox.h"
34 #include "gpu/command_buffer/service/async_pixel_transfer_delegate.h"
35 #include "gpu/command_buffer/service/async_pixel_transfer_manager.h"
36 #include "gpu/command_buffer/service/buffer_manager.h"
37 #include "gpu/command_buffer/service/cmd_buffer_engine.h"
38 #include "gpu/command_buffer/service/context_group.h"
39 #include "gpu/command_buffer/service/context_state.h"
40 #include "gpu/command_buffer/service/error_state.h"
41 #include "gpu/command_buffer/service/feature_info.h"
42 #include "gpu/command_buffer/service/framebuffer_manager.h"
43 #include "gpu/command_buffer/service/gl_utils.h"
44 #include "gpu/command_buffer/service/gles2_cmd_clear_framebuffer.h"
45 #include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h"
46 #include "gpu/command_buffer/service/gles2_cmd_validation.h"
47 #include "gpu/command_buffer/service/gpu_state_tracer.h"
48 #include "gpu/command_buffer/service/gpu_switches.h"
49 #include "gpu/command_buffer/service/gpu_tracer.h"
50 #include "gpu/command_buffer/service/image_manager.h"
51 #include "gpu/command_buffer/service/mailbox_manager.h"
52 #include "gpu/command_buffer/service/memory_tracking.h"
53 #include "gpu/command_buffer/service/program_manager.h"
54 #include "gpu/command_buffer/service/query_manager.h"
55 #include "gpu/command_buffer/service/renderbuffer_manager.h"
56 #include "gpu/command_buffer/service/shader_manager.h"
57 #include "gpu/command_buffer/service/shader_translator.h"
58 #include "gpu/command_buffer/service/shader_translator_cache.h"
59 #include "gpu/command_buffer/service/texture_manager.h"
60 #include "gpu/command_buffer/service/valuebuffer_manager.h"
61 #include "gpu/command_buffer/service/vertex_array_manager.h"
62 #include "gpu/command_buffer/service/vertex_attrib_manager.h"
63 #include "third_party/smhasher/src/City.h"
64 #include "ui/gl/gl_fence.h"
65 #include "ui/gl/gl_image.h"
66 #include "ui/gl/gl_implementation.h"
67 #include "ui/gl/gl_surface.h"
69 #if defined(OS_MACOSX)
70 #include <IOSurface/IOSurfaceAPI.h>
71 // Note that this must be included after gl_bindings.h to avoid conflicts.
72 #include <OpenGL/CGLIOSurface.h>
73 #endif
75 #if defined(OS_WIN)
76 #include "base/win/win_util.h"
77 #endif
79 namespace gpu {
80 namespace gles2 {
82 namespace {
84 static const char kOESDerivativeExtension[] = "GL_OES_standard_derivatives";
85 static const char kEXTFragDepthExtension[] = "GL_EXT_frag_depth";
86 static const char kEXTDrawBuffersExtension[] = "GL_EXT_draw_buffers";
87 static const char kEXTShaderTextureLodExtension[] = "GL_EXT_shader_texture_lod";
89 static bool PrecisionMeetsSpecForHighpFloat(GLint rangeMin,
90 GLint rangeMax,
91 GLint precision) {
92 return (rangeMin >= 62) && (rangeMax >= 62) && (precision >= 16);
95 static void GetShaderPrecisionFormatImpl(GLenum shader_type,
96 GLenum precision_type,
97 GLint *range, GLint *precision) {
98 switch (precision_type) {
99 case GL_LOW_INT:
100 case GL_MEDIUM_INT:
101 case GL_HIGH_INT:
102 // These values are for a 32-bit twos-complement integer format.
103 range[0] = 31;
104 range[1] = 30;
105 *precision = 0;
106 break;
107 case GL_LOW_FLOAT:
108 case GL_MEDIUM_FLOAT:
109 case GL_HIGH_FLOAT:
110 // These values are for an IEEE single-precision floating-point format.
111 range[0] = 127;
112 range[1] = 127;
113 *precision = 23;
114 break;
115 default:
116 NOTREACHED();
117 break;
120 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
121 gfx::g_driver_gl.fn.glGetShaderPrecisionFormatFn) {
122 // This function is sometimes defined even though it's really just
123 // a stub, so we need to set range and precision as if it weren't
124 // defined before calling it.
125 // On Mac OS with some GPUs, calling this generates a
126 // GL_INVALID_OPERATION error. Avoid calling it on non-GLES2
127 // platforms.
128 glGetShaderPrecisionFormat(shader_type, precision_type,
129 range, precision);
131 // TODO(brianderson): Make the following official workarounds.
133 // Some drivers have bugs where they report the ranges as a negative number.
134 // Taking the absolute value here shouldn't hurt because negative numbers
135 // aren't expected anyway.
136 range[0] = abs(range[0]);
137 range[1] = abs(range[1]);
139 // If the driver reports a precision for highp float that isn't actually
140 // highp, don't pretend like it's supported because shader compilation will
141 // fail anyway.
142 if (precision_type == GL_HIGH_FLOAT &&
143 !PrecisionMeetsSpecForHighpFloat(range[0], range[1], *precision)) {
144 range[0] = 0;
145 range[1] = 0;
146 *precision = 0;
151 static gfx::OverlayTransform GetGFXOverlayTransform(GLenum plane_transform) {
152 switch (plane_transform) {
153 case GL_OVERLAY_TRANSFORM_NONE_CHROMIUM:
154 return gfx::OVERLAY_TRANSFORM_NONE;
155 case GL_OVERLAY_TRANSFORM_FLIP_HORIZONTAL_CHROMIUM:
156 return gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL;
157 case GL_OVERLAY_TRANSFORM_FLIP_VERTICAL_CHROMIUM:
158 return gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL;
159 case GL_OVERLAY_TRANSFORM_ROTATE_90_CHROMIUM:
160 return gfx::OVERLAY_TRANSFORM_ROTATE_90;
161 case GL_OVERLAY_TRANSFORM_ROTATE_180_CHROMIUM:
162 return gfx::OVERLAY_TRANSFORM_ROTATE_180;
163 case GL_OVERLAY_TRANSFORM_ROTATE_270_CHROMIUM:
164 return gfx::OVERLAY_TRANSFORM_ROTATE_270;
165 default:
166 return gfx::OVERLAY_TRANSFORM_INVALID;
170 } // namespace
172 class GLES2DecoderImpl;
174 // Local versions of the SET_GL_ERROR macros
175 #define LOCAL_SET_GL_ERROR(error, function_name, msg) \
176 ERRORSTATE_SET_GL_ERROR(state_.GetErrorState(), error, function_name, msg)
177 #define LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, value, label) \
178 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(state_.GetErrorState(), \
179 function_name, value, label)
180 #define LOCAL_SET_GL_ERROR_INVALID_PARAM(error, function_name, pname) \
181 ERRORSTATE_SET_GL_ERROR_INVALID_PARAM(state_.GetErrorState(), error, \
182 function_name, pname)
183 #define LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name) \
184 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(state_.GetErrorState(), \
185 function_name)
186 #define LOCAL_PEEK_GL_ERROR(function_name) \
187 ERRORSTATE_PEEK_GL_ERROR(state_.GetErrorState(), function_name)
188 #define LOCAL_CLEAR_REAL_GL_ERRORS(function_name) \
189 ERRORSTATE_CLEAR_REAL_GL_ERRORS(state_.GetErrorState(), function_name)
190 #define LOCAL_PERFORMANCE_WARNING(msg) \
191 PerformanceWarning(__FILE__, __LINE__, msg)
192 #define LOCAL_RENDER_WARNING(msg) \
193 RenderWarning(__FILE__, __LINE__, msg)
195 // Check that certain assumptions the code makes are true. There are places in
196 // the code where shared memory is passed direclty to GL. Example, glUniformiv,
197 // glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
198 // a few others) are 32bits. If they are not 32bits the code will have to change
199 // to call those GL functions with service side memory and then copy the results
200 // to shared memory, converting the sizes.
201 static_assert(sizeof(GLint) == sizeof(uint32), // NOLINT
202 "GLint should be the same size as uint32");
203 static_assert(sizeof(GLsizei) == sizeof(uint32), // NOLINT
204 "GLsizei should be the same size as uint32");
205 static_assert(sizeof(GLfloat) == sizeof(float), // NOLINT
206 "GLfloat should be the same size as float");
208 // TODO(kbr): the use of this anonymous namespace core dumps the
209 // linker on Mac OS X 10.6 when the symbol ordering file is used
210 // namespace {
212 // Returns the address of the first byte after a struct.
213 template <typename T>
214 const void* AddressAfterStruct(const T& pod) {
215 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
218 // Returns the address of the frst byte after the struct or NULL if size >
219 // immediate_data_size.
220 template <typename RETURN_TYPE, typename COMMAND_TYPE>
221 RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod,
222 uint32 size,
223 uint32 immediate_data_size) {
224 return (size <= immediate_data_size) ?
225 static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))) :
226 NULL;
229 // Computes the data size for certain gl commands like glUniform.
230 bool ComputeDataSize(
231 GLuint count,
232 size_t size,
233 unsigned int elements_per_unit,
234 uint32* dst) {
235 uint32 value;
236 if (!SafeMultiplyUint32(count, size, &value)) {
237 return false;
239 if (!SafeMultiplyUint32(value, elements_per_unit, &value)) {
240 return false;
242 *dst = value;
243 return true;
246 // Return true if a character belongs to the ASCII subset as defined in
247 // GLSL ES 1.0 spec section 3.1.
248 static bool CharacterIsValidForGLES(unsigned char c) {
249 // Printing characters are valid except " $ ` @ \ ' DEL.
250 if (c >= 32 && c <= 126 &&
251 c != '"' &&
252 c != '$' &&
253 c != '`' &&
254 c != '@' &&
255 c != '\\' &&
256 c != '\'') {
257 return true;
259 // Horizontal tab, line feed, vertical tab, form feed, carriage return
260 // are also valid.
261 if (c >= 9 && c <= 13) {
262 return true;
265 return false;
268 static bool StringIsValidForGLES(const char* str) {
269 for (; *str; ++str) {
270 if (!CharacterIsValidForGLES(*str)) {
271 return false;
274 return true;
277 // This class prevents any GL errors that occur when it is in scope from
278 // being reported to the client.
279 class ScopedGLErrorSuppressor {
280 public:
281 explicit ScopedGLErrorSuppressor(
282 const char* function_name, ErrorState* error_state);
283 ~ScopedGLErrorSuppressor();
284 private:
285 const char* function_name_;
286 ErrorState* error_state_;
287 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor);
290 // Temporarily changes a decoder's bound texture and restore it when this
291 // object goes out of scope. Also temporarily switches to using active texture
292 // unit zero in case the client has changed that to something invalid.
293 class ScopedTextureBinder {
294 public:
295 explicit ScopedTextureBinder(ContextState* state, GLuint id, GLenum target);
296 ~ScopedTextureBinder();
298 private:
299 ContextState* state_;
300 GLenum target_;
301 DISALLOW_COPY_AND_ASSIGN(ScopedTextureBinder);
304 // Temporarily changes a decoder's bound render buffer and restore it when this
305 // object goes out of scope.
306 class ScopedRenderBufferBinder {
307 public:
308 explicit ScopedRenderBufferBinder(ContextState* state, GLuint id);
309 ~ScopedRenderBufferBinder();
311 private:
312 ContextState* state_;
313 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder);
316 // Temporarily changes a decoder's bound frame buffer and restore it when this
317 // object goes out of scope.
318 class ScopedFrameBufferBinder {
319 public:
320 explicit ScopedFrameBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
321 ~ScopedFrameBufferBinder();
323 private:
324 GLES2DecoderImpl* decoder_;
325 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder);
328 // Temporarily changes a decoder's bound frame buffer to a resolved version of
329 // the multisampled offscreen render buffer if that buffer is multisampled, and,
330 // if it is bound or enforce_internal_framebuffer is true. If internal is
331 // true, the resolved framebuffer is not visible to the parent.
332 class ScopedResolvedFrameBufferBinder {
333 public:
334 explicit ScopedResolvedFrameBufferBinder(GLES2DecoderImpl* decoder,
335 bool enforce_internal_framebuffer,
336 bool internal);
337 ~ScopedResolvedFrameBufferBinder();
339 private:
340 GLES2DecoderImpl* decoder_;
341 bool resolve_and_bind_;
342 DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder);
345 class ScopedModifyPixels {
346 public:
347 explicit ScopedModifyPixels(TextureRef* ref);
348 ~ScopedModifyPixels();
350 private:
351 TextureRef* ref_;
354 ScopedModifyPixels::ScopedModifyPixels(TextureRef* ref) : ref_(ref) {
355 if (ref_)
356 ref_->texture()->OnWillModifyPixels();
359 ScopedModifyPixels::~ScopedModifyPixels() {
360 if (ref_)
361 ref_->texture()->OnDidModifyPixels();
364 class ScopedRenderTo {
365 public:
366 explicit ScopedRenderTo(Framebuffer* framebuffer);
367 ~ScopedRenderTo();
369 private:
370 const Framebuffer* framebuffer_;
373 ScopedRenderTo::ScopedRenderTo(Framebuffer* framebuffer)
374 : framebuffer_(framebuffer) {
375 if (framebuffer)
376 framebuffer_->OnWillRenderTo();
379 ScopedRenderTo::~ScopedRenderTo() {
380 if (framebuffer_)
381 framebuffer_->OnDidRenderTo();
384 // Encapsulates an OpenGL texture.
385 class BackTexture {
386 public:
387 explicit BackTexture(MemoryTracker* memory_tracker, ContextState* state);
388 ~BackTexture();
390 // Create a new render texture.
391 void Create();
393 // Set the initial size and format of a render texture or resize it.
394 bool AllocateStorage(const gfx::Size& size, GLenum format, bool zero);
396 // Copy the contents of the currently bound frame buffer.
397 void Copy(const gfx::Size& size, GLenum format);
399 // Destroy the render texture. This must be explicitly called before
400 // destroying this object.
401 void Destroy();
403 // Invalidate the texture. This can be used when a context is lost and it is
404 // not possible to make it current in order to free the resource.
405 void Invalidate();
407 GLuint id() const {
408 return id_;
411 gfx::Size size() const {
412 return size_;
415 private:
416 MemoryTypeTracker memory_tracker_;
417 ContextState* state_;
418 size_t bytes_allocated_;
419 GLuint id_;
420 gfx::Size size_;
421 DISALLOW_COPY_AND_ASSIGN(BackTexture);
424 // Encapsulates an OpenGL render buffer of any format.
425 class BackRenderbuffer {
426 public:
427 explicit BackRenderbuffer(
428 RenderbufferManager* renderbuffer_manager,
429 MemoryTracker* memory_tracker,
430 ContextState* state);
431 ~BackRenderbuffer();
433 // Create a new render buffer.
434 void Create();
436 // Set the initial size and format of a render buffer or resize it.
437 bool AllocateStorage(const FeatureInfo* feature_info,
438 const gfx::Size& size,
439 GLenum format,
440 GLsizei samples);
442 // Destroy the render buffer. This must be explicitly called before destroying
443 // this object.
444 void Destroy();
446 // Invalidate the render buffer. This can be used when a context is lost and
447 // it is not possible to make it current in order to free the resource.
448 void Invalidate();
450 GLuint id() const {
451 return id_;
454 private:
455 RenderbufferManager* renderbuffer_manager_;
456 MemoryTypeTracker memory_tracker_;
457 ContextState* state_;
458 size_t bytes_allocated_;
459 GLuint id_;
460 DISALLOW_COPY_AND_ASSIGN(BackRenderbuffer);
463 // Encapsulates an OpenGL frame buffer.
464 class BackFramebuffer {
465 public:
466 explicit BackFramebuffer(GLES2DecoderImpl* decoder);
467 ~BackFramebuffer();
469 // Create a new frame buffer.
470 void Create();
472 // Attach a color render buffer to a frame buffer.
473 void AttachRenderTexture(BackTexture* texture);
475 // Attach a render buffer to a frame buffer. Note that this unbinds any
476 // currently bound frame buffer.
477 void AttachRenderBuffer(GLenum target, BackRenderbuffer* render_buffer);
479 // Destroy the frame buffer. This must be explicitly called before destroying
480 // this object.
481 void Destroy();
483 // Invalidate the frame buffer. This can be used when a context is lost and it
484 // is not possible to make it current in order to free the resource.
485 void Invalidate();
487 // See glCheckFramebufferStatusEXT.
488 GLenum CheckStatus();
490 GLuint id() const {
491 return id_;
494 private:
495 GLES2DecoderImpl* decoder_;
496 GLuint id_;
497 DISALLOW_COPY_AND_ASSIGN(BackFramebuffer);
500 struct FenceCallback {
501 explicit FenceCallback()
502 : fence(gfx::GLFence::Create()) {
503 DCHECK(fence);
505 std::vector<base::Closure> callbacks;
506 scoped_ptr<gfx::GLFence> fence;
509 class AsyncUploadTokenCompletionObserver
510 : public AsyncPixelTransferCompletionObserver {
511 public:
512 explicit AsyncUploadTokenCompletionObserver(uint32 async_upload_token)
513 : async_upload_token_(async_upload_token) {
516 void DidComplete(const AsyncMemoryParams& mem_params) override {
517 DCHECK(mem_params.buffer().get());
518 void* data = mem_params.GetDataAddress();
519 AsyncUploadSync* sync = static_cast<AsyncUploadSync*>(data);
520 sync->SetAsyncUploadToken(async_upload_token_);
523 private:
524 ~AsyncUploadTokenCompletionObserver() override {}
526 uint32 async_upload_token_;
528 DISALLOW_COPY_AND_ASSIGN(AsyncUploadTokenCompletionObserver);
531 // } // anonymous namespace.
533 // static
534 const unsigned int GLES2Decoder::kDefaultStencilMask =
535 static_cast<unsigned int>(-1);
537 bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id,
538 uint32* service_texture_id) {
539 return false;
542 GLES2Decoder::GLES2Decoder()
543 : initialized_(false),
544 debug_(false),
545 log_commands_(false),
546 unsafe_es3_apis_enabled_(false) {
549 GLES2Decoder::~GLES2Decoder() {
552 void GLES2Decoder::BeginDecoding() {}
554 void GLES2Decoder::EndDecoding() {}
556 // This class implements GLES2Decoder so we don't have to expose all the GLES2
557 // cmd stuff to outside this class.
558 class GLES2DecoderImpl : public GLES2Decoder,
559 public FramebufferManager::TextureDetachObserver,
560 public ErrorStateClient {
561 public:
562 explicit GLES2DecoderImpl(ContextGroup* group);
563 ~GLES2DecoderImpl() override;
565 // Overridden from AsyncAPIInterface.
566 Error DoCommand(unsigned int command,
567 unsigned int arg_count,
568 const void* args) override;
570 error::Error DoCommands(unsigned int num_commands,
571 const void* buffer,
572 int num_entries,
573 int* entries_processed) override;
575 template <bool DebugImpl>
576 error::Error DoCommandsImpl(unsigned int num_commands,
577 const void* buffer,
578 int num_entries,
579 int* entries_processed);
581 // Overridden from AsyncAPIInterface.
582 const char* GetCommandName(unsigned int command_id) const override;
584 // Overridden from GLES2Decoder.
585 bool Initialize(const scoped_refptr<gfx::GLSurface>& surface,
586 const scoped_refptr<gfx::GLContext>& context,
587 bool offscreen,
588 const gfx::Size& size,
589 const DisallowedFeatures& disallowed_features,
590 const std::vector<int32>& attribs) override;
591 void Destroy(bool have_context) override;
592 void SetSurface(const scoped_refptr<gfx::GLSurface>& surface) override;
593 void ProduceFrontBuffer(const Mailbox& mailbox) override;
594 bool ResizeOffscreenFrameBuffer(const gfx::Size& size) override;
595 void UpdateParentTextureInfo();
596 bool MakeCurrent() override;
597 GLES2Util* GetGLES2Util() override { return &util_; }
598 gfx::GLContext* GetGLContext() override { return context_.get(); }
599 ContextGroup* GetContextGroup() override { return group_.get(); }
600 Capabilities GetCapabilities() override;
601 void RestoreState(const ContextState* prev_state) override;
603 void RestoreActiveTexture() const override { state_.RestoreActiveTexture(); }
604 void RestoreAllTextureUnitBindings(
605 const ContextState* prev_state) const override {
606 state_.RestoreAllTextureUnitBindings(prev_state);
608 void RestoreActiveTextureUnitBinding(unsigned int target) const override {
609 state_.RestoreActiveTextureUnitBinding(target);
611 void RestoreBufferBindings() const override {
612 state_.RestoreBufferBindings();
614 void RestoreGlobalState() const override { state_.RestoreGlobalState(NULL); }
615 void RestoreProgramBindings() const override {
616 state_.RestoreProgramBindings();
618 void RestoreTextureUnitBindings(unsigned unit) const override {
619 state_.RestoreTextureUnitBindings(unit, NULL);
621 void RestoreFramebufferBindings() const override;
622 void RestoreRenderbufferBindings() override;
623 void RestoreTextureState(unsigned service_id) const override;
625 void ClearAllAttributes() const override;
626 void RestoreAllAttributes() const override;
628 QueryManager* GetQueryManager() override { return query_manager_.get(); }
629 VertexArrayManager* GetVertexArrayManager() override {
630 return vertex_array_manager_.get();
632 ImageManager* GetImageManager() override { return image_manager_.get(); }
634 ValuebufferManager* GetValuebufferManager() override {
635 return valuebuffer_manager();
638 bool ProcessPendingQueries(bool did_finish) override;
640 bool HasMoreIdleWork() override;
641 void PerformIdleWork() override;
643 void WaitForReadPixels(base::Closure callback) override;
645 void SetResizeCallback(
646 const base::Callback<void(gfx::Size, float)>& callback) override;
648 Logger* GetLogger() override;
650 void BeginDecoding() override;
651 void EndDecoding() override;
653 ErrorState* GetErrorState() override;
654 const ContextState* GetContextState() override { return &state_; }
656 void SetShaderCacheCallback(const ShaderCacheCallback& callback) override;
657 void SetWaitSyncPointCallback(const WaitSyncPointCallback& callback) override;
659 AsyncPixelTransferManager* GetAsyncPixelTransferManager() override;
660 void ResetAsyncPixelTransferManagerForTest() override;
661 void SetAsyncPixelTransferManagerForTest(
662 AsyncPixelTransferManager* manager) override;
663 void SetIgnoreCachedStateForTest(bool ignore) override;
664 void ProcessFinishedAsyncTransfers();
666 bool GetServiceTextureId(uint32 client_texture_id,
667 uint32* service_texture_id) override;
669 uint32 GetTextureUploadCount() override;
670 base::TimeDelta GetTotalTextureUploadTime() override;
671 base::TimeDelta GetTotalProcessingCommandsTime() override;
672 void AddProcessingCommandsTime(base::TimeDelta) override;
674 // Restores the current state to the user's settings.
675 void RestoreCurrentFramebufferBindings();
677 // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
678 void ApplyDirtyState();
680 // These check the state of the currently bound framebuffer or the
681 // backbuffer if no framebuffer is bound.
682 // If all_draw_buffers is false, only check with COLOR_ATTACHMENT0, otherwise
683 // check with all attached and enabled color attachments.
684 bool BoundFramebufferHasColorAttachmentWithAlpha(bool all_draw_buffers);
685 bool BoundFramebufferHasDepthAttachment();
686 bool BoundFramebufferHasStencilAttachment();
688 error::ContextLostReason GetContextLostReason() override;
690 // Overridden from FramebufferManager::TextureDetachObserver:
691 void OnTextureRefDetachedFromFramebuffer(TextureRef* texture) override;
693 // Overriden from ErrorStateClient.
694 void OnContextLostError() override;
695 void OnOutOfMemoryError() override;
697 // Ensure Renderbuffer corresponding to last DoBindRenderbuffer() is bound.
698 void EnsureRenderbufferBound();
700 // Helpers to facilitate calling into compatible extensions.
701 static void RenderbufferStorageMultisampleHelper(
702 const FeatureInfo* feature_info,
703 GLenum target,
704 GLsizei samples,
705 GLenum internal_format,
706 GLsizei width,
707 GLsizei height);
709 void BlitFramebufferHelper(GLint srcX0,
710 GLint srcY0,
711 GLint srcX1,
712 GLint srcY1,
713 GLint dstX0,
714 GLint dstY0,
715 GLint dstX1,
716 GLint dstY1,
717 GLbitfield mask,
718 GLenum filter);
720 private:
721 friend class ScopedFrameBufferBinder;
722 friend class ScopedResolvedFrameBufferBinder;
723 friend class BackFramebuffer;
725 // Initialize or re-initialize the shader translator.
726 bool InitializeShaderTranslator();
728 void UpdateCapabilities();
730 // Helpers for the glGen and glDelete functions.
731 bool GenTexturesHelper(GLsizei n, const GLuint* client_ids);
732 void DeleteTexturesHelper(GLsizei n, const GLuint* client_ids);
733 bool GenBuffersHelper(GLsizei n, const GLuint* client_ids);
734 void DeleteBuffersHelper(GLsizei n, const GLuint* client_ids);
735 bool GenFramebuffersHelper(GLsizei n, const GLuint* client_ids);
736 void DeleteFramebuffersHelper(GLsizei n, const GLuint* client_ids);
737 bool GenRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
738 void DeleteRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
739 bool GenValuebuffersCHROMIUMHelper(GLsizei n, const GLuint* client_ids);
740 void DeleteValuebuffersCHROMIUMHelper(GLsizei n, const GLuint* client_ids);
741 bool GenQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
742 void DeleteQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
743 bool GenVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
744 void DeleteVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
746 // Helper for async upload token completion notification callback.
747 base::Closure AsyncUploadTokenCompletionClosure(uint32 async_upload_token,
748 uint32 sync_data_shm_id,
749 uint32 sync_data_shm_offset);
753 // Workarounds
754 void OnFboChanged() const;
755 void OnUseFramebuffer() const;
757 // TODO(gman): Cache these pointers?
758 BufferManager* buffer_manager() {
759 return group_->buffer_manager();
762 RenderbufferManager* renderbuffer_manager() {
763 return group_->renderbuffer_manager();
766 FramebufferManager* framebuffer_manager() {
767 return group_->framebuffer_manager();
770 ValuebufferManager* valuebuffer_manager() {
771 return group_->valuebuffer_manager();
774 ProgramManager* program_manager() {
775 return group_->program_manager();
778 ShaderManager* shader_manager() {
779 return group_->shader_manager();
782 ShaderTranslatorCache* shader_translator_cache() {
783 return group_->shader_translator_cache();
786 const TextureManager* texture_manager() const {
787 return group_->texture_manager();
790 TextureManager* texture_manager() {
791 return group_->texture_manager();
794 MailboxManager* mailbox_manager() {
795 return group_->mailbox_manager();
798 ImageManager* image_manager() { return image_manager_.get(); }
800 VertexArrayManager* vertex_array_manager() {
801 return vertex_array_manager_.get();
804 MemoryTracker* memory_tracker() {
805 return group_->memory_tracker();
808 bool EnsureGPUMemoryAvailable(size_t estimated_size) {
809 MemoryTracker* tracker = memory_tracker();
810 if (tracker) {
811 return tracker->EnsureGPUMemoryAvailable(estimated_size);
813 return true;
816 bool IsOffscreenBufferMultisampled() const {
817 return offscreen_target_samples_ > 1;
820 // Creates a Texture for the given texture.
821 TextureRef* CreateTexture(
822 GLuint client_id, GLuint service_id) {
823 return texture_manager()->CreateTexture(client_id, service_id);
826 // Gets the texture info for the given texture. Returns NULL if none exists.
827 TextureRef* GetTexture(GLuint client_id) const {
828 return texture_manager()->GetTexture(client_id);
831 // Deletes the texture info for the given texture.
832 void RemoveTexture(GLuint client_id) {
833 texture_manager()->RemoveTexture(client_id);
836 // Get the size (in pixels) of the currently bound frame buffer (either FBO
837 // or regular back buffer).
838 gfx::Size GetBoundReadFrameBufferSize();
840 // Get the format of the currently bound frame buffer (either FBO or regular
841 // back buffer)
842 GLenum GetBoundReadFrameBufferTextureType();
843 GLenum GetBoundReadFrameBufferInternalFormat();
844 GLenum GetBoundDrawFrameBufferInternalFormat();
846 // Wrapper for CompressedTexImage2D commands.
847 error::Error DoCompressedTexImage2D(
848 GLenum target,
849 GLint level,
850 GLenum internal_format,
851 GLsizei width,
852 GLsizei height,
853 GLint border,
854 GLsizei image_size,
855 const void* data);
857 // Wrapper for CompressedTexSubImage2D.
858 void DoCompressedTexSubImage2D(
859 GLenum target,
860 GLint level,
861 GLint xoffset,
862 GLint yoffset,
863 GLsizei width,
864 GLsizei height,
865 GLenum format,
866 GLsizei imageSize,
867 const void * data);
869 // Wrapper for CopyTexImage2D.
870 void DoCopyTexImage2D(
871 GLenum target,
872 GLint level,
873 GLenum internal_format,
874 GLint x,
875 GLint y,
876 GLsizei width,
877 GLsizei height,
878 GLint border);
880 // Wrapper for SwapBuffers.
881 void DoSwapBuffers();
883 // Wrapper for SwapInterval.
884 void DoSwapInterval(int interval);
886 // Wrapper for CopyTexSubImage2D.
887 void DoCopyTexSubImage2D(
888 GLenum target,
889 GLint level,
890 GLint xoffset,
891 GLint yoffset,
892 GLint x,
893 GLint y,
894 GLsizei width,
895 GLsizei height);
897 // Validation for TexSubImage2D.
898 bool ValidateTexSubImage2D(
899 error::Error* error,
900 const char* function_name,
901 GLenum target,
902 GLint level,
903 GLint xoffset,
904 GLint yoffset,
905 GLsizei width,
906 GLsizei height,
907 GLenum format,
908 GLenum type,
909 const void * data);
911 // Wrapper for TexSubImage2D.
912 error::Error DoTexSubImage2D(
913 GLenum target,
914 GLint level,
915 GLint xoffset,
916 GLint yoffset,
917 GLsizei width,
918 GLsizei height,
919 GLenum format,
920 GLenum type,
921 const void * data);
923 // Extra validation for async tex(Sub)Image2D.
924 bool ValidateAsyncTransfer(
925 const char* function_name,
926 TextureRef* texture_ref,
927 GLenum target,
928 GLint level,
929 const void * data);
931 // Wrapper for TexImageIOSurface2DCHROMIUM.
932 void DoTexImageIOSurface2DCHROMIUM(
933 GLenum target,
934 GLsizei width,
935 GLsizei height,
936 GLuint io_surface_id,
937 GLuint plane);
939 void DoCopyTextureCHROMIUM(
940 GLenum target,
941 GLuint source_id,
942 GLuint target_id,
943 GLint level,
944 GLenum internal_format,
945 GLenum dest_type);
947 // Wrapper for TexStorage2DEXT.
948 void DoTexStorage2DEXT(
949 GLenum target,
950 GLint levels,
951 GLenum internal_format,
952 GLsizei width,
953 GLsizei height);
955 void DoProduceTextureCHROMIUM(GLenum target, const GLbyte* key);
956 void DoProduceTextureDirectCHROMIUM(GLuint texture, GLenum target,
957 const GLbyte* key);
958 void ProduceTextureRef(std::string func_name, TextureRef* texture_ref,
959 GLenum target, const GLbyte* data);
961 void DoConsumeTextureCHROMIUM(GLenum target, const GLbyte* key);
962 void DoCreateAndConsumeTextureCHROMIUM(GLenum target, const GLbyte* key,
963 GLuint client_id);
965 bool DoIsValuebufferCHROMIUM(GLuint client_id);
966 void DoBindValueBufferCHROMIUM(GLenum target, GLuint valuebuffer);
967 void DoSubscribeValueCHROMIUM(GLenum target, GLenum subscription);
968 void DoPopulateSubscribedValuesCHROMIUM(GLenum target);
969 void DoUniformValueBufferCHROMIUM(GLint location,
970 GLenum target,
971 GLenum subscription);
973 void DoBindTexImage2DCHROMIUM(
974 GLenum target,
975 GLint image_id);
976 void DoReleaseTexImage2DCHROMIUM(
977 GLenum target,
978 GLint image_id);
980 void DoTraceEndCHROMIUM(void);
982 void DoDrawBuffersEXT(GLsizei count, const GLenum* bufs);
984 void DoLoseContextCHROMIUM(GLenum current, GLenum other);
986 void DoMatrixLoadfCHROMIUM(GLenum matrix_mode, const GLfloat* matrix);
987 void DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode);
989 // Creates a Program for the given program.
990 Program* CreateProgram(
991 GLuint client_id, GLuint service_id) {
992 return program_manager()->CreateProgram(client_id, service_id);
995 // Gets the program info for the given program. Returns NULL if none exists.
996 Program* GetProgram(GLuint client_id) {
997 return program_manager()->GetProgram(client_id);
1000 #if defined(NDEBUG)
1001 void LogClientServiceMapping(
1002 const char* /* function_name */,
1003 GLuint /* client_id */,
1004 GLuint /* service_id */) {
1006 template<typename T>
1007 void LogClientServiceForInfo(
1008 T* /* info */, GLuint /* client_id */, const char* /* function_name */) {
1010 #else
1011 void LogClientServiceMapping(
1012 const char* function_name, GLuint client_id, GLuint service_id) {
1013 if (service_logging_) {
1014 VLOG(1) << "[" << logger_.GetLogPrefix() << "] " << function_name
1015 << ": client_id = " << client_id
1016 << ", service_id = " << service_id;
1019 template<typename T>
1020 void LogClientServiceForInfo(
1021 T* info, GLuint client_id, const char* function_name) {
1022 if (info) {
1023 LogClientServiceMapping(function_name, client_id, info->service_id());
1026 #endif
1028 // Gets the program info for the given program. If it's not a program
1029 // generates a GL error. Returns NULL if not program.
1030 Program* GetProgramInfoNotShader(
1031 GLuint client_id, const char* function_name) {
1032 Program* program = GetProgram(client_id);
1033 if (!program) {
1034 if (GetShader(client_id)) {
1035 LOCAL_SET_GL_ERROR(
1036 GL_INVALID_OPERATION, function_name, "shader passed for program");
1037 } else {
1038 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "unknown program");
1041 LogClientServiceForInfo(program, client_id, function_name);
1042 return program;
1046 // Creates a Shader for the given shader.
1047 Shader* CreateShader(
1048 GLuint client_id,
1049 GLuint service_id,
1050 GLenum shader_type) {
1051 return shader_manager()->CreateShader(
1052 client_id, service_id, shader_type);
1055 // Gets the shader info for the given shader. Returns NULL if none exists.
1056 Shader* GetShader(GLuint client_id) {
1057 return shader_manager()->GetShader(client_id);
1060 // Gets the shader info for the given shader. If it's not a shader generates a
1061 // GL error. Returns NULL if not shader.
1062 Shader* GetShaderInfoNotProgram(
1063 GLuint client_id, const char* function_name) {
1064 Shader* shader = GetShader(client_id);
1065 if (!shader) {
1066 if (GetProgram(client_id)) {
1067 LOCAL_SET_GL_ERROR(
1068 GL_INVALID_OPERATION, function_name, "program passed for shader");
1069 } else {
1070 LOCAL_SET_GL_ERROR(
1071 GL_INVALID_VALUE, function_name, "unknown shader");
1074 LogClientServiceForInfo(shader, client_id, function_name);
1075 return shader;
1078 // Creates a buffer info for the given buffer.
1079 void CreateBuffer(GLuint client_id, GLuint service_id) {
1080 return buffer_manager()->CreateBuffer(client_id, service_id);
1083 // Gets the buffer info for the given buffer.
1084 Buffer* GetBuffer(GLuint client_id) {
1085 Buffer* buffer = buffer_manager()->GetBuffer(client_id);
1086 return buffer;
1089 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
1090 // on glDeleteBuffers so we can make sure the user does not try to render
1091 // with deleted buffers.
1092 void RemoveBuffer(GLuint client_id);
1094 // Creates a framebuffer info for the given framebuffer.
1095 void CreateFramebuffer(GLuint client_id, GLuint service_id) {
1096 return framebuffer_manager()->CreateFramebuffer(client_id, service_id);
1099 // Gets the framebuffer info for the given framebuffer.
1100 Framebuffer* GetFramebuffer(GLuint client_id) {
1101 return framebuffer_manager()->GetFramebuffer(client_id);
1104 // Removes the framebuffer info for the given framebuffer.
1105 void RemoveFramebuffer(GLuint client_id) {
1106 framebuffer_manager()->RemoveFramebuffer(client_id);
1109 // Creates a renderbuffer info for the given renderbuffer.
1110 void CreateRenderbuffer(GLuint client_id, GLuint service_id) {
1111 return renderbuffer_manager()->CreateRenderbuffer(
1112 client_id, service_id);
1115 // Gets the renderbuffer info for the given renderbuffer.
1116 Renderbuffer* GetRenderbuffer(GLuint client_id) {
1117 return renderbuffer_manager()->GetRenderbuffer(client_id);
1120 // Removes the renderbuffer info for the given renderbuffer.
1121 void RemoveRenderbuffer(GLuint client_id) {
1122 renderbuffer_manager()->RemoveRenderbuffer(client_id);
1125 // Creates a valuebuffer info for the given valuebuffer.
1126 void CreateValuebuffer(GLuint client_id) {
1127 return valuebuffer_manager()->CreateValuebuffer(client_id);
1130 // Gets the valuebuffer info for a given valuebuffer.
1131 Valuebuffer* GetValuebuffer(GLuint client_id) {
1132 return valuebuffer_manager()->GetValuebuffer(client_id);
1135 // Removes the valuebuffer info for the given valuebuffer.
1136 void RemoveValuebuffer(GLuint client_id) {
1137 valuebuffer_manager()->RemoveValuebuffer(client_id);
1140 // Gets the vertex attrib manager for the given vertex array.
1141 VertexAttribManager* GetVertexAttribManager(GLuint client_id) {
1142 VertexAttribManager* info =
1143 vertex_array_manager()->GetVertexAttribManager(client_id);
1144 return info;
1147 // Removes the vertex attrib manager for the given vertex array.
1148 void RemoveVertexAttribManager(GLuint client_id) {
1149 vertex_array_manager()->RemoveVertexAttribManager(client_id);
1152 // Creates a vertex attrib manager for the given vertex array.
1153 scoped_refptr<VertexAttribManager> CreateVertexAttribManager(
1154 GLuint client_id,
1155 GLuint service_id,
1156 bool client_visible) {
1157 return vertex_array_manager()->CreateVertexAttribManager(
1158 client_id, service_id, group_->max_vertex_attribs(), client_visible);
1161 void DoBindAttribLocation(GLuint client_id, GLuint index, const char* name);
1162 void DoBindUniformLocationCHROMIUM(
1163 GLuint client_id, GLint location, const char* name);
1165 error::Error GetAttribLocationHelper(
1166 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1167 const std::string& name_str);
1169 error::Error GetUniformLocationHelper(
1170 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1171 const std::string& name_str);
1173 error::Error GetFragDataLocationHelper(
1174 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1175 const std::string& name_str);
1177 // Wrapper for glShaderSource.
1178 void DoShaderSource(
1179 GLuint client_id, GLsizei count, const char** data, const GLint* length);
1181 // Wrapper for glTransformFeedbackVaryings.
1182 void DoTransformFeedbackVaryings(
1183 GLuint client_program_id, GLsizei count, const char* const* varyings,
1184 GLenum buffer_mode);
1186 // Clear any textures used by the current program.
1187 bool ClearUnclearedTextures();
1189 // Clears any uncleared attachments attached to the given frame buffer.
1190 // Returns false if there was a generated GL error.
1191 void ClearUnclearedAttachments(GLenum target, Framebuffer* framebuffer);
1193 // overridden from GLES2Decoder
1194 bool ClearLevel(Texture* texture,
1195 unsigned target,
1196 int level,
1197 unsigned internal_format,
1198 unsigned format,
1199 unsigned type,
1200 int width,
1201 int height,
1202 bool is_texture_immutable) override;
1204 // Restore all GL state that affects clearing.
1205 void RestoreClearState();
1207 // Remembers the state of some capabilities.
1208 // Returns: true if glEnable/glDisable should actually be called.
1209 bool SetCapabilityState(GLenum cap, bool enabled);
1211 // Check that the currently bound framebuffers are valid.
1212 // Generates GL error if not.
1213 bool CheckBoundFramebuffersValid(const char* func_name);
1215 // Check that the currently bound read framebuffer has a color image
1216 // attached. Generates GL error if not.
1217 bool CheckBoundReadFramebufferColorAttachment(const char* func_name);
1219 // Check that the currently bound read framebuffer's color image
1220 // isn't the target texture of the glCopyTex{Sub}Image2D.
1221 bool FormsTextureCopyingFeedbackLoop(TextureRef* texture, GLint level);
1223 // Check if a framebuffer meets our requirements.
1224 bool CheckFramebufferValid(
1225 Framebuffer* framebuffer,
1226 GLenum target,
1227 const char* func_name);
1229 // Check if the current valuebuffer exists and is valid. If not generates
1230 // the appropriate GL error. Returns true if the current valuebuffer is in
1231 // a usable state.
1232 bool CheckCurrentValuebuffer(const char* function_name);
1234 // Check if the current valuebuffer exists and is valiud and that the
1235 // value buffer is actually subscribed to the given subscription
1236 bool CheckCurrentValuebufferForSubscription(GLenum subscription,
1237 const char* function_name);
1239 // Check if the location can be used for the given subscription target. If not
1240 // generates the appropriate GL error. Returns true if the location is usable
1241 bool CheckSubscriptionTarget(GLint location,
1242 GLenum subscription,
1243 const char* function_name);
1245 // Checks if the current program exists and is valid. If not generates the
1246 // appropriate GL error. Returns true if the current program is in a usable
1247 // state.
1248 bool CheckCurrentProgram(const char* function_name);
1250 // Checks if the current program exists and is valid and that location is not
1251 // -1. If the current program is not valid generates the appropriate GL
1252 // error. Returns true if the current program is in a usable state and
1253 // location is not -1.
1254 bool CheckCurrentProgramForUniform(GLint location, const char* function_name);
1256 // Checks if the current program samples a texture that is also the color
1257 // image of the current bound framebuffer, i.e., the source and destination
1258 // of the draw operation are the same.
1259 bool CheckDrawingFeedbackLoops();
1261 // Checks if |api_type| is valid for the given uniform
1262 // If the api type is not valid generates the appropriate GL
1263 // error. Returns true if |api_type| is valid for the uniform
1264 bool CheckUniformForApiType(const Program::UniformInfo* info,
1265 const char* function_name,
1266 Program::UniformApiType api_type);
1268 // Gets the type of a uniform for a location in the current program. Sets GL
1269 // errors if the current program is not valid. Returns true if the current
1270 // program is valid and the location exists. Adjusts count so it
1271 // does not overflow the uniform.
1272 bool PrepForSetUniformByLocation(GLint fake_location,
1273 const char* function_name,
1274 Program::UniformApiType api_type,
1275 GLint* real_location,
1276 GLenum* type,
1277 GLsizei* count);
1279 // Gets the service id for any simulated backbuffer fbo.
1280 GLuint GetBackbufferServiceId() const;
1282 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
1283 bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
1285 // Helper for glGetVertexAttrib
1286 void GetVertexAttribHelper(
1287 const VertexAttrib* attrib, GLenum pname, GLint* param);
1289 // Wrapper for glActiveTexture
1290 void DoActiveTexture(GLenum texture_unit);
1292 // Wrapper for glAttachShader
1293 void DoAttachShader(GLuint client_program_id, GLint client_shader_id);
1295 // Wrapper for glBindBuffer since we need to track the current targets.
1296 void DoBindBuffer(GLenum target, GLuint buffer);
1298 // Wrapper for glBindFramebuffer since we need to track the current targets.
1299 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
1301 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1302 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
1304 // Wrapper for glBindTexture since we need to track the current targets.
1305 void DoBindTexture(GLenum target, GLuint texture);
1307 // Wrapper for glBindVertexArrayOES
1308 void DoBindVertexArrayOES(GLuint array);
1309 void EmulateVertexArrayState();
1311 // Wrapper for glBlitFramebufferCHROMIUM.
1312 void DoBlitFramebufferCHROMIUM(
1313 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
1314 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
1315 GLbitfield mask, GLenum filter);
1317 // Wrapper for glBufferSubData.
1318 void DoBufferSubData(
1319 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
1321 // Wrapper for glCheckFramebufferStatus
1322 GLenum DoCheckFramebufferStatus(GLenum target);
1324 // Wrapper for glClear
1325 error::Error DoClear(GLbitfield mask);
1327 // Wrappers for various state.
1328 void DoDepthRangef(GLclampf znear, GLclampf zfar);
1329 void DoSampleCoverage(GLclampf value, GLboolean invert);
1331 // Wrapper for glCompileShader.
1332 void DoCompileShader(GLuint shader);
1334 // Wrapper for glDetachShader
1335 void DoDetachShader(GLuint client_program_id, GLint client_shader_id);
1337 // Wrapper for glDisable
1338 void DoDisable(GLenum cap);
1340 // Wrapper for glDisableVertexAttribArray.
1341 void DoDisableVertexAttribArray(GLuint index);
1343 // Wrapper for glDiscardFramebufferEXT, since we need to track undefined
1344 // attachments.
1345 void DoDiscardFramebufferEXT(GLenum target,
1346 GLsizei numAttachments,
1347 const GLenum* attachments);
1349 // Wrapper for glEnable
1350 void DoEnable(GLenum cap);
1352 // Wrapper for glEnableVertexAttribArray.
1353 void DoEnableVertexAttribArray(GLuint index);
1355 // Wrapper for glFinish.
1356 void DoFinish();
1358 // Wrapper for glFlush.
1359 void DoFlush();
1361 // Wrapper for glFramebufferRenderbufffer.
1362 void DoFramebufferRenderbuffer(
1363 GLenum target, GLenum attachment, GLenum renderbuffertarget,
1364 GLuint renderbuffer);
1366 // Wrapper for glFramebufferTexture2D.
1367 void DoFramebufferTexture2D(
1368 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
1369 GLint level);
1371 // Wrapper for glFramebufferTexture2DMultisampleEXT.
1372 void DoFramebufferTexture2DMultisample(
1373 GLenum target, GLenum attachment, GLenum textarget,
1374 GLuint texture, GLint level, GLsizei samples);
1376 // Common implementation for both DoFramebufferTexture2D wrappers.
1377 void DoFramebufferTexture2DCommon(const char* name,
1378 GLenum target, GLenum attachment, GLenum textarget,
1379 GLuint texture, GLint level, GLsizei samples);
1381 // Wrapper for glFramebufferTextureLayer.
1382 void DoFramebufferTextureLayer(
1383 GLenum target, GLenum attachment, GLuint texture, GLint level,
1384 GLint layer);
1386 // Wrapper for glGenerateMipmap
1387 void DoGenerateMipmap(GLenum target);
1389 // Helper for DoGetBooleanv, Floatv, and Intergerv to adjust pname
1390 // to account for different pname values defined in different extension
1391 // variants.
1392 GLenum AdjustGetPname(GLenum pname);
1394 // Wrapper for DoGetBooleanv.
1395 void DoGetBooleanv(GLenum pname, GLboolean* params);
1397 // Wrapper for DoGetFloatv.
1398 void DoGetFloatv(GLenum pname, GLfloat* params);
1400 // Wrapper for glGetFramebufferAttachmentParameteriv.
1401 void DoGetFramebufferAttachmentParameteriv(
1402 GLenum target, GLenum attachment, GLenum pname, GLint* params);
1404 // Wrapper for glGetIntegerv.
1405 void DoGetIntegerv(GLenum pname, GLint* params);
1407 // Gets the max value in a range in a buffer.
1408 GLuint DoGetMaxValueInBufferCHROMIUM(
1409 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset);
1411 // Wrapper for glGetBufferParameteriv.
1412 void DoGetBufferParameteriv(
1413 GLenum target, GLenum pname, GLint* params);
1415 // Wrapper for glGetProgramiv.
1416 void DoGetProgramiv(
1417 GLuint program_id, GLenum pname, GLint* params);
1419 // Wrapper for glRenderbufferParameteriv.
1420 void DoGetRenderbufferParameteriv(
1421 GLenum target, GLenum pname, GLint* params);
1423 // Wrapper for glGetShaderiv
1424 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
1426 // Wrappers for glGetTexParameter.
1427 void DoGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params);
1428 void DoGetTexParameteriv(GLenum target, GLenum pname, GLint* params);
1429 void InitTextureMaxAnisotropyIfNeeded(GLenum target, GLenum pname);
1431 // Wrappers for glGetVertexAttrib.
1432 void DoGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params);
1433 void DoGetVertexAttribiv(GLuint index, GLenum pname, GLint *params);
1435 // Wrappers for glIsXXX functions.
1436 bool DoIsEnabled(GLenum cap);
1437 bool DoIsBuffer(GLuint client_id);
1438 bool DoIsFramebuffer(GLuint client_id);
1439 bool DoIsProgram(GLuint client_id);
1440 bool DoIsRenderbuffer(GLuint client_id);
1441 bool DoIsShader(GLuint client_id);
1442 bool DoIsTexture(GLuint client_id);
1443 bool DoIsVertexArrayOES(GLuint client_id);
1445 // Wrapper for glLinkProgram
1446 void DoLinkProgram(GLuint program);
1448 // Wrapper for glRenderbufferStorage.
1449 void DoRenderbufferStorage(
1450 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
1452 // Handler for glRenderbufferStorageMultisampleCHROMIUM.
1453 void DoRenderbufferStorageMultisampleCHROMIUM(
1454 GLenum target, GLsizei samples, GLenum internalformat,
1455 GLsizei width, GLsizei height);
1457 // Handler for glRenderbufferStorageMultisampleEXT
1458 // (multisampled_render_to_texture).
1459 void DoRenderbufferStorageMultisampleEXT(
1460 GLenum target, GLsizei samples, GLenum internalformat,
1461 GLsizei width, GLsizei height);
1463 // Common validation for multisample extensions.
1464 bool ValidateRenderbufferStorageMultisample(GLsizei samples,
1465 GLenum internalformat,
1466 GLsizei width,
1467 GLsizei height);
1469 // Verifies that the currently bound multisample renderbuffer is valid
1470 // Very slow! Only done on platforms with driver bugs that return invalid
1471 // buffers under memory pressure
1472 bool VerifyMultisampleRenderbufferIntegrity(
1473 GLuint renderbuffer, GLenum format);
1475 // Wrapper for glReleaseShaderCompiler.
1476 void DoReleaseShaderCompiler() { }
1478 // Wrappers for glSamplerParameter*v functions.
1479 void DoSamplerParameterfv(
1480 GLuint sampler, GLenum pname, const GLfloat* params);
1481 void DoSamplerParameteriv(GLuint sampler, GLenum pname, const GLint* params);
1483 // Wrappers for glTexParameter functions.
1484 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
1485 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
1486 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
1487 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
1489 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1490 // spec only these 2 functions can be used to set sampler uniforms.
1491 void DoUniform1i(GLint fake_location, GLint v0);
1492 void DoUniform1iv(GLint fake_location, GLsizei count, const GLint* value);
1493 void DoUniform2iv(GLint fake_location, GLsizei count, const GLint* value);
1494 void DoUniform3iv(GLint fake_location, GLsizei count, const GLint* value);
1495 void DoUniform4iv(GLint fake_location, GLsizei count, const GLint* value);
1497 // Wrappers for glUniformfv because some drivers don't correctly accept
1498 // bool uniforms.
1499 void DoUniform1fv(GLint fake_location, GLsizei count, const GLfloat* value);
1500 void DoUniform2fv(GLint fake_location, GLsizei count, const GLfloat* value);
1501 void DoUniform3fv(GLint fake_location, GLsizei count, const GLfloat* value);
1502 void DoUniform4fv(GLint fake_location, GLsizei count, const GLfloat* value);
1504 void DoUniformMatrix2fv(
1505 GLint fake_location, GLsizei count, GLboolean transpose,
1506 const GLfloat* value);
1507 void DoUniformMatrix3fv(
1508 GLint fake_location, GLsizei count, GLboolean transpose,
1509 const GLfloat* value);
1510 void DoUniformMatrix4fv(
1511 GLint fake_location, GLsizei count, GLboolean transpose,
1512 const GLfloat* value);
1514 bool SetVertexAttribValue(
1515 const char* function_name, GLuint index, const GLfloat* value);
1517 // Wrappers for glVertexAttrib??
1518 void DoVertexAttrib1f(GLuint index, GLfloat v0);
1519 void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
1520 void DoVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
1521 void DoVertexAttrib4f(
1522 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
1523 void DoVertexAttrib1fv(GLuint index, const GLfloat *v);
1524 void DoVertexAttrib2fv(GLuint index, const GLfloat *v);
1525 void DoVertexAttrib3fv(GLuint index, const GLfloat *v);
1526 void DoVertexAttrib4fv(GLuint index, const GLfloat *v);
1528 // Wrapper for glViewport
1529 void DoViewport(GLint x, GLint y, GLsizei width, GLsizei height);
1531 // Wrapper for glUseProgram
1532 void DoUseProgram(GLuint program);
1534 // Wrapper for glValidateProgram.
1535 void DoValidateProgram(GLuint program_client_id);
1537 void DoInsertEventMarkerEXT(GLsizei length, const GLchar* marker);
1538 void DoPushGroupMarkerEXT(GLsizei length, const GLchar* group);
1539 void DoPopGroupMarkerEXT(void);
1541 // Gets the number of values that will be returned by glGetXXX. Returns
1542 // false if pname is unknown.
1543 bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
1545 // Checks if the current program and vertex attributes are valid for drawing.
1546 bool IsDrawValid(
1547 const char* function_name, GLuint max_vertex_accessed, bool instanced,
1548 GLsizei primcount);
1550 // Returns true if successful, simulated will be true if attrib0 was
1551 // simulated.
1552 bool SimulateAttrib0(
1553 const char* function_name, GLuint max_vertex_accessed, bool* simulated);
1554 void RestoreStateForAttrib(GLuint attrib, bool restore_array_binding);
1556 // If an image is bound to texture, this will call Will/DidUseTexImage
1557 // if needed.
1558 void DoWillUseTexImageIfNeeded(Texture* texture, GLenum textarget);
1559 void DoDidUseTexImageIfNeeded(Texture* texture, GLenum textarget);
1561 // Returns false if textures were replaced.
1562 bool PrepareTexturesForRender();
1563 void RestoreStateForTextures();
1565 // Returns true if GL_FIXED attribs were simulated.
1566 bool SimulateFixedAttribs(
1567 const char* function_name,
1568 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount);
1569 void RestoreStateForSimulatedFixedAttribs();
1571 // Handle DrawArrays and DrawElements for both instanced and non-instanced
1572 // cases (primcount is always 1 for non-instanced).
1573 error::Error DoDrawArrays(
1574 const char* function_name,
1575 bool instanced, GLenum mode, GLint first, GLsizei count,
1576 GLsizei primcount);
1577 error::Error DoDrawElements(
1578 const char* function_name,
1579 bool instanced, GLenum mode, GLsizei count, GLenum type,
1580 int32 offset, GLsizei primcount);
1582 GLenum GetBindTargetForSamplerType(GLenum type) {
1583 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
1584 type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB);
1585 switch (type) {
1586 case GL_SAMPLER_2D:
1587 return GL_TEXTURE_2D;
1588 case GL_SAMPLER_CUBE:
1589 return GL_TEXTURE_CUBE_MAP;
1590 case GL_SAMPLER_EXTERNAL_OES:
1591 return GL_TEXTURE_EXTERNAL_OES;
1592 case GL_SAMPLER_2D_RECT_ARB:
1593 return GL_TEXTURE_RECTANGLE_ARB;
1596 NOTREACHED();
1597 return 0;
1600 // Gets the framebuffer info for a particular target.
1601 Framebuffer* GetFramebufferInfoForTarget(GLenum target) {
1602 Framebuffer* framebuffer = NULL;
1603 switch (target) {
1604 case GL_FRAMEBUFFER:
1605 case GL_DRAW_FRAMEBUFFER_EXT:
1606 framebuffer = framebuffer_state_.bound_draw_framebuffer.get();
1607 break;
1608 case GL_READ_FRAMEBUFFER_EXT:
1609 framebuffer = framebuffer_state_.bound_read_framebuffer.get();
1610 break;
1611 default:
1612 NOTREACHED();
1613 break;
1615 return framebuffer;
1618 Renderbuffer* GetRenderbufferInfoForTarget(
1619 GLenum target) {
1620 Renderbuffer* renderbuffer = NULL;
1621 switch (target) {
1622 case GL_RENDERBUFFER:
1623 renderbuffer = state_.bound_renderbuffer.get();
1624 break;
1625 default:
1626 NOTREACHED();
1627 break;
1629 return renderbuffer;
1632 // Validates the program and location for a glGetUniform call and returns
1633 // a SizeResult setup to receive the result. Returns true if glGetUniform
1634 // should be called.
1635 bool GetUniformSetup(
1636 GLuint program, GLint fake_location,
1637 uint32 shm_id, uint32 shm_offset,
1638 error::Error* error, GLint* real_location, GLuint* service_id,
1639 void** result, GLenum* result_type);
1641 void MaybeExitOnContextLost();
1642 bool WasContextLost() override;
1643 bool WasContextLostByRobustnessExtension() override;
1644 void LoseContext(uint32 reset_status) override;
1646 #if defined(OS_MACOSX)
1647 void ReleaseIOSurfaceForTexture(GLuint texture_id);
1648 #endif
1650 bool ValidateCompressedTexDimensions(
1651 const char* function_name,
1652 GLint level, GLsizei width, GLsizei height, GLenum format);
1653 bool ValidateCompressedTexFuncData(
1654 const char* function_name,
1655 GLsizei width, GLsizei height, GLenum format, size_t size);
1656 bool ValidateCompressedTexSubDimensions(
1657 const char* function_name,
1658 GLenum target, GLint level, GLint xoffset, GLint yoffset,
1659 GLsizei width, GLsizei height, GLenum format,
1660 Texture* texture);
1662 void RenderWarning(const char* filename, int line, const std::string& msg);
1663 void PerformanceWarning(
1664 const char* filename, int line, const std::string& msg);
1666 const FeatureInfo::FeatureFlags& features() const {
1667 return feature_info_->feature_flags();
1670 const FeatureInfo::Workarounds& workarounds() const {
1671 return feature_info_->workarounds();
1674 bool ShouldDeferDraws() {
1675 return !offscreen_target_frame_buffer_.get() &&
1676 framebuffer_state_.bound_draw_framebuffer.get() == NULL &&
1677 surface_->DeferDraws();
1680 bool ShouldDeferReads() {
1681 return !offscreen_target_frame_buffer_.get() &&
1682 framebuffer_state_.bound_read_framebuffer.get() == NULL &&
1683 surface_->DeferDraws();
1686 bool IsRobustnessSupported() {
1687 return has_robustness_extension_ &&
1688 context_->WasAllocatedUsingRobustnessExtension();
1691 error::Error WillAccessBoundFramebufferForDraw() {
1692 if (ShouldDeferDraws())
1693 return error::kDeferCommandUntilLater;
1694 if (!offscreen_target_frame_buffer_.get() &&
1695 !framebuffer_state_.bound_draw_framebuffer.get() &&
1696 !surface_->SetBackbufferAllocation(true))
1697 return error::kLostContext;
1698 return error::kNoError;
1701 error::Error WillAccessBoundFramebufferForRead() {
1702 if (ShouldDeferReads())
1703 return error::kDeferCommandUntilLater;
1704 if (!offscreen_target_frame_buffer_.get() &&
1705 !framebuffer_state_.bound_read_framebuffer.get() &&
1706 !surface_->SetBackbufferAllocation(true))
1707 return error::kLostContext;
1708 return error::kNoError;
1711 // Set remaining commands to process to 0 to force DoCommands to return
1712 // and allow context preemption and GPU watchdog checks in GpuScheduler().
1713 void ExitCommandProcessingEarly() { commands_to_process_ = 0; }
1715 void ProcessPendingReadPixels();
1716 void FinishReadPixels(const cmds::ReadPixels& c, GLuint buffer);
1718 // Generate a member function prototype for each command in an automated and
1719 // typesafe way.
1720 #define GLES2_CMD_OP(name) \
1721 Error Handle##name(uint32 immediate_data_size, const void* data);
1723 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1725 #undef GLES2_CMD_OP
1727 // The GL context this decoder renders to on behalf of the client.
1728 scoped_refptr<gfx::GLSurface> surface_;
1729 scoped_refptr<gfx::GLContext> context_;
1731 // The ContextGroup for this decoder uses to track resources.
1732 scoped_refptr<ContextGroup> group_;
1734 DebugMarkerManager debug_marker_manager_;
1735 Logger logger_;
1737 // All the state for this context.
1738 ContextState state_;
1740 // Current width and height of the offscreen frame buffer.
1741 gfx::Size offscreen_size_;
1743 // Util to help with GL.
1744 GLES2Util util_;
1746 // unpack flip y as last set by glPixelStorei
1747 bool unpack_flip_y_;
1749 // unpack (un)premultiply alpha as last set by glPixelStorei
1750 bool unpack_premultiply_alpha_;
1751 bool unpack_unpremultiply_alpha_;
1753 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1754 GLuint attrib_0_buffer_id_;
1756 // The value currently in attrib_0.
1757 Vec4 attrib_0_value_;
1759 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1760 bool attrib_0_buffer_matches_value_;
1762 // The size of attrib 0.
1763 GLsizei attrib_0_size_;
1765 // The buffer used to simulate GL_FIXED attribs.
1766 GLuint fixed_attrib_buffer_id_;
1768 // The size of fiixed attrib buffer.
1769 GLsizei fixed_attrib_buffer_size_;
1771 // The offscreen frame buffer that the client renders to. With EGL, the
1772 // depth and stencil buffers are separate. With regular GL there is a single
1773 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1774 // offscreen_target_stencil_render_buffer_ is unused.
1775 scoped_ptr<BackFramebuffer> offscreen_target_frame_buffer_;
1776 scoped_ptr<BackTexture> offscreen_target_color_texture_;
1777 scoped_ptr<BackRenderbuffer> offscreen_target_color_render_buffer_;
1778 scoped_ptr<BackRenderbuffer> offscreen_target_depth_render_buffer_;
1779 scoped_ptr<BackRenderbuffer> offscreen_target_stencil_render_buffer_;
1780 GLenum offscreen_target_color_format_;
1781 GLenum offscreen_target_depth_format_;
1782 GLenum offscreen_target_stencil_format_;
1783 GLsizei offscreen_target_samples_;
1784 GLboolean offscreen_target_buffer_preserved_;
1786 // The copy that is saved when SwapBuffers is called.
1787 scoped_ptr<BackFramebuffer> offscreen_saved_frame_buffer_;
1788 scoped_ptr<BackTexture> offscreen_saved_color_texture_;
1789 scoped_refptr<TextureRef>
1790 offscreen_saved_color_texture_info_;
1792 // The copy that is used as the destination for multi-sample resolves.
1793 scoped_ptr<BackFramebuffer> offscreen_resolved_frame_buffer_;
1794 scoped_ptr<BackTexture> offscreen_resolved_color_texture_;
1795 GLenum offscreen_saved_color_format_;
1797 scoped_ptr<QueryManager> query_manager_;
1799 scoped_ptr<VertexArrayManager> vertex_array_manager_;
1801 scoped_ptr<ImageManager> image_manager_;
1803 base::Callback<void(gfx::Size, float)> resize_callback_;
1805 WaitSyncPointCallback wait_sync_point_callback_;
1807 ShaderCacheCallback shader_cache_callback_;
1809 scoped_ptr<AsyncPixelTransferManager> async_pixel_transfer_manager_;
1811 // The format of the back buffer_
1812 GLenum back_buffer_color_format_;
1813 bool back_buffer_has_depth_;
1814 bool back_buffer_has_stencil_;
1816 bool surfaceless_;
1818 // Backbuffer attachments that are currently undefined.
1819 uint32 backbuffer_needs_clear_bits_;
1821 // The current decoder error communicates the decoder error through command
1822 // processing functions that do not return the error value. Should be set only
1823 // if not returning an error.
1824 error::Error current_decoder_error_;
1826 bool use_shader_translator_;
1827 scoped_refptr<ShaderTranslatorInterface> vertex_translator_;
1828 scoped_refptr<ShaderTranslatorInterface> fragment_translator_;
1830 DisallowedFeatures disallowed_features_;
1832 // Cached from ContextGroup
1833 const Validators* validators_;
1834 scoped_refptr<FeatureInfo> feature_info_;
1836 int frame_number_;
1838 // Number of commands remaining to be processed in DoCommands().
1839 int commands_to_process_;
1841 bool has_robustness_extension_;
1842 GLenum reset_status_;
1843 bool reset_by_robustness_extension_;
1844 bool supports_post_sub_buffer_;
1846 // These flags are used to override the state of the shared feature_info_
1847 // member. Because the same FeatureInfo instance may be shared among many
1848 // contexts, the assumptions on the availablity of extensions in WebGL
1849 // contexts may be broken. These flags override the shared state to preserve
1850 // WebGL semantics.
1851 bool force_webgl_glsl_validation_;
1852 bool derivatives_explicitly_enabled_;
1853 bool frag_depth_explicitly_enabled_;
1854 bool draw_buffers_explicitly_enabled_;
1855 bool shader_texture_lod_explicitly_enabled_;
1857 bool compile_shader_always_succeeds_;
1859 // An optional behaviour to lose the context and group when OOM.
1860 bool lose_context_when_out_of_memory_;
1862 // Log extra info.
1863 bool service_logging_;
1865 #if defined(OS_MACOSX)
1866 typedef std::map<GLuint, IOSurfaceRef> TextureToIOSurfaceMap;
1867 TextureToIOSurfaceMap texture_to_io_surface_map_;
1868 #endif
1870 scoped_ptr<CopyTextureCHROMIUMResourceManager> copy_texture_CHROMIUM_;
1871 scoped_ptr<ClearFramebufferResourceManager> clear_framebuffer_blit_;
1873 // Cached values of the currently assigned viewport dimensions.
1874 GLsizei viewport_max_width_;
1875 GLsizei viewport_max_height_;
1877 // Command buffer stats.
1878 base::TimeDelta total_processing_commands_time_;
1880 // States related to each manager.
1881 DecoderTextureState texture_state_;
1882 DecoderFramebufferState framebuffer_state_;
1884 scoped_ptr<GPUTracer> gpu_tracer_;
1885 scoped_ptr<GPUStateTracer> gpu_state_tracer_;
1886 const unsigned char* cb_command_trace_category_;
1887 const unsigned char* gpu_decoder_category_;
1888 int gpu_trace_level_;
1889 bool gpu_trace_commands_;
1890 bool gpu_debug_commands_;
1892 std::queue<linked_ptr<FenceCallback> > pending_readpixel_fences_;
1894 // Used to validate multisample renderbuffers if needed
1895 GLuint validation_texture_;
1896 GLuint validation_fbo_multisample_;
1897 GLuint validation_fbo_;
1899 typedef gpu::gles2::GLES2Decoder::Error (GLES2DecoderImpl::*CmdHandler)(
1900 uint32 immediate_data_size,
1901 const void* data);
1903 // A struct to hold info about each command.
1904 struct CommandInfo {
1905 CmdHandler cmd_handler;
1906 uint8 arg_flags; // How to handle the arguments for this command
1907 uint8 cmd_flags; // How to handle this command
1908 uint16 arg_count; // How many arguments are expected for this command.
1911 // A table of CommandInfo for all the commands.
1912 static const CommandInfo command_info[kNumCommands - kStartPoint];
1914 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
1917 const GLES2DecoderImpl::CommandInfo GLES2DecoderImpl::command_info[] = {
1918 #define GLES2_CMD_OP(name) \
1920 &GLES2DecoderImpl::Handle##name, cmds::name::kArgFlags, \
1921 cmds::name::cmd_flags, \
1922 sizeof(cmds::name) / sizeof(CommandBufferEntry) - 1, \
1924 , /* NOLINT */
1925 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1926 #undef GLES2_CMD_OP
1929 ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(
1930 const char* function_name, ErrorState* error_state)
1931 : function_name_(function_name),
1932 error_state_(error_state) {
1933 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state_, function_name_);
1936 ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
1937 ERRORSTATE_CLEAR_REAL_GL_ERRORS(error_state_, function_name_);
1940 static void RestoreCurrentTextureBindings(ContextState* state, GLenum target) {
1941 TextureUnit& info = state->texture_units[0];
1942 GLuint last_id;
1943 scoped_refptr<TextureRef> texture_ref;
1944 switch (target) {
1945 case GL_TEXTURE_2D:
1946 texture_ref = info.bound_texture_2d;
1947 break;
1948 case GL_TEXTURE_CUBE_MAP:
1949 texture_ref = info.bound_texture_cube_map;
1950 break;
1951 case GL_TEXTURE_EXTERNAL_OES:
1952 texture_ref = info.bound_texture_external_oes;
1953 break;
1954 case GL_TEXTURE_RECTANGLE_ARB:
1955 texture_ref = info.bound_texture_rectangle_arb;
1956 break;
1957 default:
1958 NOTREACHED();
1959 break;
1961 if (texture_ref.get()) {
1962 last_id = texture_ref->service_id();
1963 } else {
1964 last_id = 0;
1967 glBindTexture(target, last_id);
1968 glActiveTexture(GL_TEXTURE0 + state->active_texture_unit);
1971 ScopedTextureBinder::ScopedTextureBinder(ContextState* state,
1972 GLuint id,
1973 GLenum target)
1974 : state_(state),
1975 target_(target) {
1976 ScopedGLErrorSuppressor suppressor(
1977 "ScopedTextureBinder::ctor", state_->GetErrorState());
1979 // TODO(apatrick): Check if there are any other states that need to be reset
1980 // before binding a new texture.
1981 glActiveTexture(GL_TEXTURE0);
1982 glBindTexture(target, id);
1985 ScopedTextureBinder::~ScopedTextureBinder() {
1986 ScopedGLErrorSuppressor suppressor(
1987 "ScopedTextureBinder::dtor", state_->GetErrorState());
1988 RestoreCurrentTextureBindings(state_, target_);
1991 ScopedRenderBufferBinder::ScopedRenderBufferBinder(ContextState* state,
1992 GLuint id)
1993 : state_(state) {
1994 ScopedGLErrorSuppressor suppressor(
1995 "ScopedRenderBufferBinder::ctor", state_->GetErrorState());
1996 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
1999 ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
2000 ScopedGLErrorSuppressor suppressor(
2001 "ScopedRenderBufferBinder::dtor", state_->GetErrorState());
2002 state_->RestoreRenderbufferBindings();
2005 ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
2006 GLuint id)
2007 : decoder_(decoder) {
2008 ScopedGLErrorSuppressor suppressor(
2009 "ScopedFrameBufferBinder::ctor", decoder_->GetErrorState());
2010 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
2011 decoder->OnFboChanged();
2014 ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
2015 ScopedGLErrorSuppressor suppressor(
2016 "ScopedFrameBufferBinder::dtor", decoder_->GetErrorState());
2017 decoder_->RestoreCurrentFramebufferBindings();
2020 ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
2021 GLES2DecoderImpl* decoder, bool enforce_internal_framebuffer, bool internal)
2022 : decoder_(decoder) {
2023 resolve_and_bind_ = (
2024 decoder_->offscreen_target_frame_buffer_.get() &&
2025 decoder_->IsOffscreenBufferMultisampled() &&
2026 (!decoder_->framebuffer_state_.bound_read_framebuffer.get() ||
2027 enforce_internal_framebuffer));
2028 if (!resolve_and_bind_)
2029 return;
2031 ScopedGLErrorSuppressor suppressor(
2032 "ScopedResolvedFrameBufferBinder::ctor", decoder_->GetErrorState());
2033 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT,
2034 decoder_->offscreen_target_frame_buffer_->id());
2035 GLuint targetid;
2036 if (internal) {
2037 if (!decoder_->offscreen_resolved_frame_buffer_.get()) {
2038 decoder_->offscreen_resolved_frame_buffer_.reset(
2039 new BackFramebuffer(decoder_));
2040 decoder_->offscreen_resolved_frame_buffer_->Create();
2041 decoder_->offscreen_resolved_color_texture_.reset(
2042 new BackTexture(decoder->memory_tracker(), &decoder->state_));
2043 decoder_->offscreen_resolved_color_texture_->Create();
2045 DCHECK(decoder_->offscreen_saved_color_format_);
2046 decoder_->offscreen_resolved_color_texture_->AllocateStorage(
2047 decoder_->offscreen_size_, decoder_->offscreen_saved_color_format_,
2048 false);
2049 decoder_->offscreen_resolved_frame_buffer_->AttachRenderTexture(
2050 decoder_->offscreen_resolved_color_texture_.get());
2051 if (decoder_->offscreen_resolved_frame_buffer_->CheckStatus() !=
2052 GL_FRAMEBUFFER_COMPLETE) {
2053 LOG(ERROR) << "ScopedResolvedFrameBufferBinder failed "
2054 << "because offscreen resolved FBO was incomplete.";
2055 return;
2058 targetid = decoder_->offscreen_resolved_frame_buffer_->id();
2059 } else {
2060 targetid = decoder_->offscreen_saved_frame_buffer_->id();
2062 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, targetid);
2063 const int width = decoder_->offscreen_size_.width();
2064 const int height = decoder_->offscreen_size_.height();
2065 decoder->state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
2066 decoder->BlitFramebufferHelper(0,
2068 width,
2069 height,
2072 width,
2073 height,
2074 GL_COLOR_BUFFER_BIT,
2075 GL_NEAREST);
2076 glBindFramebufferEXT(GL_FRAMEBUFFER, targetid);
2079 ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
2080 if (!resolve_and_bind_)
2081 return;
2083 ScopedGLErrorSuppressor suppressor(
2084 "ScopedResolvedFrameBufferBinder::dtor", decoder_->GetErrorState());
2085 decoder_->RestoreCurrentFramebufferBindings();
2086 if (decoder_->state_.enable_flags.scissor_test) {
2087 decoder_->state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
2091 BackTexture::BackTexture(
2092 MemoryTracker* memory_tracker,
2093 ContextState* state)
2094 : memory_tracker_(memory_tracker, MemoryTracker::kUnmanaged),
2095 state_(state),
2096 bytes_allocated_(0),
2097 id_(0) {
2100 BackTexture::~BackTexture() {
2101 // This does not destroy the render texture because that would require that
2102 // the associated GL context was current. Just check that it was explicitly
2103 // destroyed.
2104 DCHECK_EQ(id_, 0u);
2107 void BackTexture::Create() {
2108 ScopedGLErrorSuppressor suppressor("BackTexture::Create",
2109 state_->GetErrorState());
2110 Destroy();
2111 glGenTextures(1, &id_);
2112 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2113 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2114 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2115 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2116 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2118 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
2119 // never called on an offscreen context, no data will ever be uploaded to the
2120 // saved offscreen color texture (it is deferred until to when SwapBuffers
2121 // is called). My idea is that some nvidia drivers might have a bug where
2122 // deleting a texture that has never been populated might cause a
2123 // crash.
2124 glTexImage2D(
2125 GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
2127 bytes_allocated_ = 16u * 16u * 4u;
2128 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2131 bool BackTexture::AllocateStorage(
2132 const gfx::Size& size, GLenum format, bool zero) {
2133 DCHECK_NE(id_, 0u);
2134 ScopedGLErrorSuppressor suppressor("BackTexture::AllocateStorage",
2135 state_->GetErrorState());
2136 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2137 uint32 image_size = 0;
2138 GLES2Util::ComputeImageDataSizes(
2139 size.width(), size.height(), 1, format, GL_UNSIGNED_BYTE, 8, &image_size,
2140 NULL, NULL);
2142 if (!memory_tracker_.EnsureGPUMemoryAvailable(image_size)) {
2143 return false;
2146 scoped_ptr<char[]> zero_data;
2147 if (zero) {
2148 zero_data.reset(new char[image_size]);
2149 memset(zero_data.get(), 0, image_size);
2152 glTexImage2D(GL_TEXTURE_2D,
2153 0, // mip level
2154 format,
2155 size.width(),
2156 size.height(),
2157 0, // border
2158 format,
2159 GL_UNSIGNED_BYTE,
2160 zero_data.get());
2162 size_ = size;
2164 bool success = glGetError() == GL_NO_ERROR;
2165 if (success) {
2166 memory_tracker_.TrackMemFree(bytes_allocated_);
2167 bytes_allocated_ = image_size;
2168 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2170 return success;
2173 void BackTexture::Copy(const gfx::Size& size, GLenum format) {
2174 DCHECK_NE(id_, 0u);
2175 ScopedGLErrorSuppressor suppressor("BackTexture::Copy",
2176 state_->GetErrorState());
2177 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2178 glCopyTexImage2D(GL_TEXTURE_2D,
2179 0, // level
2180 format,
2181 0, 0,
2182 size.width(),
2183 size.height(),
2184 0); // border
2187 void BackTexture::Destroy() {
2188 if (id_ != 0) {
2189 ScopedGLErrorSuppressor suppressor("BackTexture::Destroy",
2190 state_->GetErrorState());
2191 glDeleteTextures(1, &id_);
2192 id_ = 0;
2194 memory_tracker_.TrackMemFree(bytes_allocated_);
2195 bytes_allocated_ = 0;
2198 void BackTexture::Invalidate() {
2199 id_ = 0;
2202 BackRenderbuffer::BackRenderbuffer(
2203 RenderbufferManager* renderbuffer_manager,
2204 MemoryTracker* memory_tracker,
2205 ContextState* state)
2206 : renderbuffer_manager_(renderbuffer_manager),
2207 memory_tracker_(memory_tracker, MemoryTracker::kUnmanaged),
2208 state_(state),
2209 bytes_allocated_(0),
2210 id_(0) {
2213 BackRenderbuffer::~BackRenderbuffer() {
2214 // This does not destroy the render buffer because that would require that
2215 // the associated GL context was current. Just check that it was explicitly
2216 // destroyed.
2217 DCHECK_EQ(id_, 0u);
2220 void BackRenderbuffer::Create() {
2221 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Create",
2222 state_->GetErrorState());
2223 Destroy();
2224 glGenRenderbuffersEXT(1, &id_);
2227 bool BackRenderbuffer::AllocateStorage(const FeatureInfo* feature_info,
2228 const gfx::Size& size,
2229 GLenum format,
2230 GLsizei samples) {
2231 ScopedGLErrorSuppressor suppressor(
2232 "BackRenderbuffer::AllocateStorage", state_->GetErrorState());
2233 ScopedRenderBufferBinder binder(state_, id_);
2235 uint32 estimated_size = 0;
2236 if (!renderbuffer_manager_->ComputeEstimatedRenderbufferSize(
2237 size.width(), size.height(), samples, format, &estimated_size)) {
2238 return false;
2241 if (!memory_tracker_.EnsureGPUMemoryAvailable(estimated_size)) {
2242 return false;
2245 if (samples <= 1) {
2246 glRenderbufferStorageEXT(GL_RENDERBUFFER,
2247 format,
2248 size.width(),
2249 size.height());
2250 } else {
2251 GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(feature_info,
2252 GL_RENDERBUFFER,
2253 samples,
2254 format,
2255 size.width(),
2256 size.height());
2258 bool success = glGetError() == GL_NO_ERROR;
2259 if (success) {
2260 // Mark the previously allocated bytes as free.
2261 memory_tracker_.TrackMemFree(bytes_allocated_);
2262 bytes_allocated_ = estimated_size;
2263 // Track the newly allocated bytes.
2264 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2266 return success;
2269 void BackRenderbuffer::Destroy() {
2270 if (id_ != 0) {
2271 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Destroy",
2272 state_->GetErrorState());
2273 glDeleteRenderbuffersEXT(1, &id_);
2274 id_ = 0;
2276 memory_tracker_.TrackMemFree(bytes_allocated_);
2277 bytes_allocated_ = 0;
2280 void BackRenderbuffer::Invalidate() {
2281 id_ = 0;
2284 BackFramebuffer::BackFramebuffer(GLES2DecoderImpl* decoder)
2285 : decoder_(decoder),
2286 id_(0) {
2289 BackFramebuffer::~BackFramebuffer() {
2290 // This does not destroy the frame buffer because that would require that
2291 // the associated GL context was current. Just check that it was explicitly
2292 // destroyed.
2293 DCHECK_EQ(id_, 0u);
2296 void BackFramebuffer::Create() {
2297 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Create",
2298 decoder_->GetErrorState());
2299 Destroy();
2300 glGenFramebuffersEXT(1, &id_);
2303 void BackFramebuffer::AttachRenderTexture(BackTexture* texture) {
2304 DCHECK_NE(id_, 0u);
2305 ScopedGLErrorSuppressor suppressor(
2306 "BackFramebuffer::AttachRenderTexture", decoder_->GetErrorState());
2307 ScopedFrameBufferBinder binder(decoder_, id_);
2308 GLuint attach_id = texture ? texture->id() : 0;
2309 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
2310 GL_COLOR_ATTACHMENT0,
2311 GL_TEXTURE_2D,
2312 attach_id,
2316 void BackFramebuffer::AttachRenderBuffer(GLenum target,
2317 BackRenderbuffer* render_buffer) {
2318 DCHECK_NE(id_, 0u);
2319 ScopedGLErrorSuppressor suppressor(
2320 "BackFramebuffer::AttachRenderBuffer", decoder_->GetErrorState());
2321 ScopedFrameBufferBinder binder(decoder_, id_);
2322 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
2323 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
2324 target,
2325 GL_RENDERBUFFER,
2326 attach_id);
2329 void BackFramebuffer::Destroy() {
2330 if (id_ != 0) {
2331 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Destroy",
2332 decoder_->GetErrorState());
2333 glDeleteFramebuffersEXT(1, &id_);
2334 id_ = 0;
2338 void BackFramebuffer::Invalidate() {
2339 id_ = 0;
2342 GLenum BackFramebuffer::CheckStatus() {
2343 DCHECK_NE(id_, 0u);
2344 ScopedGLErrorSuppressor suppressor("BackFramebuffer::CheckStatus",
2345 decoder_->GetErrorState());
2346 ScopedFrameBufferBinder binder(decoder_, id_);
2347 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
2350 GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
2351 return new GLES2DecoderImpl(group);
2354 GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
2355 : GLES2Decoder(),
2356 group_(group),
2357 logger_(&debug_marker_manager_),
2358 state_(group_->feature_info(), this, &logger_),
2359 unpack_flip_y_(false),
2360 unpack_premultiply_alpha_(false),
2361 unpack_unpremultiply_alpha_(false),
2362 attrib_0_buffer_id_(0),
2363 attrib_0_buffer_matches_value_(true),
2364 attrib_0_size_(0),
2365 fixed_attrib_buffer_id_(0),
2366 fixed_attrib_buffer_size_(0),
2367 offscreen_target_color_format_(0),
2368 offscreen_target_depth_format_(0),
2369 offscreen_target_stencil_format_(0),
2370 offscreen_target_samples_(0),
2371 offscreen_target_buffer_preserved_(true),
2372 offscreen_saved_color_format_(0),
2373 back_buffer_color_format_(0),
2374 back_buffer_has_depth_(false),
2375 back_buffer_has_stencil_(false),
2376 surfaceless_(false),
2377 backbuffer_needs_clear_bits_(0),
2378 current_decoder_error_(error::kNoError),
2379 use_shader_translator_(true),
2380 validators_(group_->feature_info()->validators()),
2381 feature_info_(group_->feature_info()),
2382 frame_number_(0),
2383 has_robustness_extension_(false),
2384 reset_status_(GL_NO_ERROR),
2385 reset_by_robustness_extension_(false),
2386 supports_post_sub_buffer_(false),
2387 force_webgl_glsl_validation_(false),
2388 derivatives_explicitly_enabled_(false),
2389 frag_depth_explicitly_enabled_(false),
2390 draw_buffers_explicitly_enabled_(false),
2391 shader_texture_lod_explicitly_enabled_(false),
2392 compile_shader_always_succeeds_(false),
2393 lose_context_when_out_of_memory_(false),
2394 service_logging_(base::CommandLine::ForCurrentProcess()->HasSwitch(
2395 switches::kEnableGPUServiceLoggingGPU)),
2396 viewport_max_width_(0),
2397 viewport_max_height_(0),
2398 texture_state_(group_->feature_info()
2399 ->workarounds()
2400 .texsubimage2d_faster_than_teximage2d),
2401 cb_command_trace_category_(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
2402 TRACE_DISABLED_BY_DEFAULT("cb_command"))),
2403 gpu_decoder_category_(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
2404 TRACE_DISABLED_BY_DEFAULT("gpu_decoder"))),
2405 gpu_trace_level_(2),
2406 gpu_trace_commands_(false),
2407 gpu_debug_commands_(false),
2408 validation_texture_(0),
2409 validation_fbo_multisample_(0),
2410 validation_fbo_(0) {
2411 DCHECK(group);
2413 attrib_0_value_.v[0] = 0.0f;
2414 attrib_0_value_.v[1] = 0.0f;
2415 attrib_0_value_.v[2] = 0.0f;
2416 attrib_0_value_.v[3] = 1.0f;
2418 // The shader translator is used for WebGL even when running on EGL
2419 // because additional restrictions are needed (like only enabling
2420 // GL_OES_standard_derivatives on demand). It is used for the unit
2421 // tests because GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes
2422 // the empty string to CompileShader and this is not a valid shader.
2423 if (gfx::GetGLImplementation() == gfx::kGLImplementationMockGL ||
2424 base::CommandLine::ForCurrentProcess()->HasSwitch(
2425 switches::kDisableGLSLTranslator)) {
2426 use_shader_translator_ = false;
2430 GLES2DecoderImpl::~GLES2DecoderImpl() {
2433 bool GLES2DecoderImpl::Initialize(
2434 const scoped_refptr<gfx::GLSurface>& surface,
2435 const scoped_refptr<gfx::GLContext>& context,
2436 bool offscreen,
2437 const gfx::Size& size,
2438 const DisallowedFeatures& disallowed_features,
2439 const std::vector<int32>& attribs) {
2440 TRACE_EVENT0("gpu", "GLES2DecoderImpl::Initialize");
2441 DCHECK(context->IsCurrent(surface.get()));
2442 DCHECK(!context_.get());
2444 surfaceless_ = surface->IsSurfaceless() && !offscreen;
2446 set_initialized();
2447 gpu_state_tracer_ = GPUStateTracer::Create(&state_);
2449 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2450 switches::kEnableGPUDebugging)) {
2451 set_debug(true);
2454 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2455 switches::kEnableGPUCommandLogging)) {
2456 set_log_commands(true);
2459 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2460 switches::kEnableUnsafeES3APIs)) {
2461 set_unsafe_es3_apis_enabled(true);
2464 compile_shader_always_succeeds_ =
2465 base::CommandLine::ForCurrentProcess()->HasSwitch(
2466 switches::kCompileShaderAlwaysSucceeds);
2468 // Take ownership of the context and surface. The surface can be replaced with
2469 // SetSurface.
2470 context_ = context;
2471 surface_ = surface;
2473 ContextCreationAttribHelper attrib_parser;
2474 if (!attrib_parser.Parse(attribs))
2475 return false;
2477 // Create GPU Tracer for timing values.
2478 gpu_tracer_.reset(new GPUTracer(this));
2480 // Save the loseContextWhenOutOfMemory context creation attribute.
2481 lose_context_when_out_of_memory_ =
2482 attrib_parser.lose_context_when_out_of_memory;
2484 // If the failIfMajorPerformanceCaveat context creation attribute was true
2485 // and we are using a software renderer, fail.
2486 if (attrib_parser.fail_if_major_perf_caveat &&
2487 feature_info_->feature_flags().is_swiftshader) {
2488 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
2489 Destroy(true);
2490 return false;
2493 if (!group_->Initialize(this, disallowed_features)) {
2494 LOG(ERROR) << "GpuScheduler::InitializeCommon failed because group "
2495 << "failed to initialize.";
2496 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
2497 Destroy(true);
2498 return false;
2500 CHECK_GL_ERROR();
2502 disallowed_features_ = disallowed_features;
2504 state_.attrib_values.resize(group_->max_vertex_attribs());
2505 vertex_array_manager_.reset(new VertexArrayManager());
2507 GLuint default_vertex_attrib_service_id = 0;
2508 if (features().native_vertex_array_object) {
2509 glGenVertexArraysOES(1, &default_vertex_attrib_service_id);
2510 glBindVertexArrayOES(default_vertex_attrib_service_id);
2513 state_.default_vertex_attrib_manager =
2514 CreateVertexAttribManager(0, default_vertex_attrib_service_id, false);
2516 state_.default_vertex_attrib_manager->Initialize(
2517 group_->max_vertex_attribs(),
2518 feature_info_->workarounds().init_vertex_attributes);
2520 // vertex_attrib_manager is set to default_vertex_attrib_manager by this call
2521 DoBindVertexArrayOES(0);
2523 query_manager_.reset(new QueryManager(this, feature_info_.get()));
2525 image_manager_.reset(new ImageManager);
2527 util_.set_num_compressed_texture_formats(
2528 validators_->compressed_texture_format.GetValues().size());
2530 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2531 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
2532 // OpenGL ES 2.0 does not have this issue.
2533 glEnableVertexAttribArray(0);
2535 glGenBuffersARB(1, &attrib_0_buffer_id_);
2536 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
2537 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
2538 glBindBuffer(GL_ARRAY_BUFFER, 0);
2539 glGenBuffersARB(1, &fixed_attrib_buffer_id_);
2541 state_.texture_units.resize(group_->max_texture_units());
2542 for (uint32 tt = 0; tt < state_.texture_units.size(); ++tt) {
2543 glActiveTexture(GL_TEXTURE0 + tt);
2544 // We want the last bind to be 2D.
2545 TextureRef* ref;
2546 if (features().oes_egl_image_external) {
2547 ref = texture_manager()->GetDefaultTextureInfo(
2548 GL_TEXTURE_EXTERNAL_OES);
2549 state_.texture_units[tt].bound_texture_external_oes = ref;
2550 glBindTexture(GL_TEXTURE_EXTERNAL_OES, ref ? ref->service_id() : 0);
2552 if (features().arb_texture_rectangle) {
2553 ref = texture_manager()->GetDefaultTextureInfo(
2554 GL_TEXTURE_RECTANGLE_ARB);
2555 state_.texture_units[tt].bound_texture_rectangle_arb = ref;
2556 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, ref ? ref->service_id() : 0);
2558 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
2559 state_.texture_units[tt].bound_texture_cube_map = ref;
2560 glBindTexture(GL_TEXTURE_CUBE_MAP, ref ? ref->service_id() : 0);
2561 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
2562 state_.texture_units[tt].bound_texture_2d = ref;
2563 glBindTexture(GL_TEXTURE_2D, ref ? ref->service_id() : 0);
2565 glActiveTexture(GL_TEXTURE0);
2566 CHECK_GL_ERROR();
2568 if (offscreen) {
2569 if (attrib_parser.samples > 0 && attrib_parser.sample_buffers > 0 &&
2570 features().chromium_framebuffer_multisample) {
2571 // Per ext_framebuffer_multisample spec, need max bound on sample count.
2572 // max_sample_count must be initialized to a sane value. If
2573 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2574 GLint max_sample_count = 1;
2575 glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count);
2576 offscreen_target_samples_ = std::min(attrib_parser.samples,
2577 max_sample_count);
2578 } else {
2579 offscreen_target_samples_ = 1;
2581 offscreen_target_buffer_preserved_ = attrib_parser.buffer_preserved;
2583 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
2584 const bool rgb8_supported =
2585 context_->HasExtension("GL_OES_rgb8_rgba8");
2586 // The only available default render buffer formats in GLES2 have very
2587 // little precision. Don't enable multisampling unless 8-bit render
2588 // buffer formats are available--instead fall back to 8-bit textures.
2589 if (rgb8_supported && offscreen_target_samples_ > 1) {
2590 offscreen_target_color_format_ = attrib_parser.alpha_size > 0 ?
2591 GL_RGBA8 : GL_RGB8;
2592 } else {
2593 offscreen_target_samples_ = 1;
2594 offscreen_target_color_format_ = attrib_parser.alpha_size > 0 ?
2595 GL_RGBA : GL_RGB;
2598 // ANGLE only supports packed depth/stencil formats, so use it if it is
2599 // available.
2600 const bool depth24_stencil8_supported =
2601 feature_info_->feature_flags().packed_depth24_stencil8;
2602 VLOG(1) << "GL_OES_packed_depth_stencil "
2603 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
2604 if ((attrib_parser.depth_size > 0 || attrib_parser.stencil_size > 0) &&
2605 depth24_stencil8_supported) {
2606 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2607 offscreen_target_stencil_format_ = 0;
2608 } else {
2609 // It may be the case that this depth/stencil combination is not
2610 // supported, but this will be checked later by CheckFramebufferStatus.
2611 offscreen_target_depth_format_ = attrib_parser.depth_size > 0 ?
2612 GL_DEPTH_COMPONENT16 : 0;
2613 offscreen_target_stencil_format_ = attrib_parser.stencil_size > 0 ?
2614 GL_STENCIL_INDEX8 : 0;
2616 } else {
2617 offscreen_target_color_format_ = attrib_parser.alpha_size > 0 ?
2618 GL_RGBA : GL_RGB;
2620 // If depth is requested at all, use the packed depth stencil format if
2621 // it's available, as some desktop GL drivers don't support any non-packed
2622 // formats for depth attachments.
2623 const bool depth24_stencil8_supported =
2624 feature_info_->feature_flags().packed_depth24_stencil8;
2625 VLOG(1) << "GL_EXT_packed_depth_stencil "
2626 << (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 offscreen_target_depth_format_ = attrib_parser.depth_size > 0 ?
2634 GL_DEPTH_COMPONENT : 0;
2635 offscreen_target_stencil_format_ = attrib_parser.stencil_size > 0 ?
2636 GL_STENCIL_INDEX : 0;
2640 offscreen_saved_color_format_ = attrib_parser.alpha_size > 0 ?
2641 GL_RGBA : GL_RGB;
2643 // Create the target frame buffer. This is the one that the client renders
2644 // directly to.
2645 offscreen_target_frame_buffer_.reset(new BackFramebuffer(this));
2646 offscreen_target_frame_buffer_->Create();
2647 // Due to GLES2 format limitations, either the color texture (for
2648 // non-multisampling) or the color render buffer (for multisampling) will be
2649 // attached to the offscreen frame buffer. The render buffer has more
2650 // limited formats available to it, but the texture can't do multisampling.
2651 if (IsOffscreenBufferMultisampled()) {
2652 offscreen_target_color_render_buffer_.reset(new BackRenderbuffer(
2653 renderbuffer_manager(), memory_tracker(), &state_));
2654 offscreen_target_color_render_buffer_->Create();
2655 } else {
2656 offscreen_target_color_texture_.reset(new BackTexture(
2657 memory_tracker(), &state_));
2658 offscreen_target_color_texture_->Create();
2660 offscreen_target_depth_render_buffer_.reset(new BackRenderbuffer(
2661 renderbuffer_manager(), memory_tracker(), &state_));
2662 offscreen_target_depth_render_buffer_->Create();
2663 offscreen_target_stencil_render_buffer_.reset(new BackRenderbuffer(
2664 renderbuffer_manager(), memory_tracker(), &state_));
2665 offscreen_target_stencil_render_buffer_->Create();
2667 // Create the saved offscreen texture. The target frame buffer is copied
2668 // here when SwapBuffers is called.
2669 offscreen_saved_frame_buffer_.reset(new BackFramebuffer(this));
2670 offscreen_saved_frame_buffer_->Create();
2672 offscreen_saved_color_texture_.reset(new BackTexture(
2673 memory_tracker(), &state_));
2674 offscreen_saved_color_texture_->Create();
2676 // Allocate the render buffers at their initial size and check the status
2677 // of the frame buffers is okay.
2678 if (!ResizeOffscreenFrameBuffer(size)) {
2679 LOG(ERROR) << "Could not allocate offscreen buffer storage.";
2680 Destroy(true);
2681 return false;
2684 // Allocate the offscreen saved color texture.
2685 DCHECK(offscreen_saved_color_format_);
2686 offscreen_saved_color_texture_->AllocateStorage(
2687 gfx::Size(1, 1), offscreen_saved_color_format_, true);
2689 offscreen_saved_frame_buffer_->AttachRenderTexture(
2690 offscreen_saved_color_texture_.get());
2691 if (offscreen_saved_frame_buffer_->CheckStatus() !=
2692 GL_FRAMEBUFFER_COMPLETE) {
2693 LOG(ERROR) << "Offscreen saved FBO was incomplete.";
2694 Destroy(true);
2695 return false;
2698 // Bind to the new default frame buffer (the offscreen target frame buffer).
2699 // This should now be associated with ID zero.
2700 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2701 } else {
2702 glBindFramebufferEXT(GL_FRAMEBUFFER, GetBackbufferServiceId());
2703 // These are NOT if the back buffer has these proprorties. They are
2704 // if we want the command buffer to enforce them regardless of what
2705 // the real backbuffer is assuming the real back buffer gives us more than
2706 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2707 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2708 // can't do anything about that.
2710 if (!surfaceless_) {
2711 GLint v = 0;
2712 glGetIntegerv(GL_ALPHA_BITS, &v);
2713 // This checks if the user requested RGBA and we have RGBA then RGBA. If
2714 // the user requested RGB then RGB. If the user did not specify a
2715 // preference than use whatever we were given. Same for DEPTH and STENCIL.
2716 back_buffer_color_format_ =
2717 (attrib_parser.alpha_size != 0 && v > 0) ? GL_RGBA : GL_RGB;
2718 glGetIntegerv(GL_DEPTH_BITS, &v);
2719 back_buffer_has_depth_ = attrib_parser.depth_size != 0 && v > 0;
2720 glGetIntegerv(GL_STENCIL_BITS, &v);
2721 back_buffer_has_stencil_ = attrib_parser.stencil_size != 0 && v > 0;
2725 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2726 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2727 // isn't well documented; it was discovered in the Khronos OpenGL ES
2728 // mailing list archives. It also implicitly enables the desktop GL
2729 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2730 // variable in fragment shaders.
2731 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2732 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
2733 glEnable(GL_POINT_SPRITE);
2736 has_robustness_extension_ =
2737 context->HasExtension("GL_ARB_robustness") ||
2738 context->HasExtension("GL_KHR_robustness") ||
2739 context->HasExtension("GL_EXT_robustness");
2741 if (!InitializeShaderTranslator()) {
2742 return false;
2745 state_.viewport_width = size.width();
2746 state_.viewport_height = size.height();
2748 GLint viewport_params[4] = { 0 };
2749 glGetIntegerv(GL_MAX_VIEWPORT_DIMS, viewport_params);
2750 viewport_max_width_ = viewport_params[0];
2751 viewport_max_height_ = viewport_params[1];
2753 state_.scissor_width = state_.viewport_width;
2754 state_.scissor_height = state_.viewport_height;
2756 // Set all the default state because some GL drivers get it wrong.
2757 state_.InitCapabilities(NULL);
2758 state_.InitState(NULL);
2759 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
2761 DoBindBuffer(GL_ARRAY_BUFFER, 0);
2762 DoBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
2763 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2764 DoBindRenderbuffer(GL_RENDERBUFFER, 0);
2765 DoBindValueBufferCHROMIUM(GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM, 0);
2767 bool call_gl_clear = !surfaceless_;
2768 #if defined(OS_ANDROID)
2769 // Temporary workaround for Android WebView because this clear ignores the
2770 // clip and corrupts that external UI of the App. Not calling glClear is ok
2771 // because the system already clears the buffer before each draw. Proper
2772 // fix might be setting the scissor clip properly before initialize. See
2773 // crbug.com/259023 for details.
2774 call_gl_clear = surface_->GetHandle();
2775 #endif
2776 if (call_gl_clear) {
2777 // Clear the backbuffer.
2778 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2781 supports_post_sub_buffer_ = surface->SupportsPostSubBuffer();
2782 if (feature_info_->workarounds()
2783 .disable_post_sub_buffers_for_onscreen_surfaces &&
2784 !surface->IsOffscreen())
2785 supports_post_sub_buffer_ = false;
2787 if (feature_info_->workarounds().reverse_point_sprite_coord_origin) {
2788 glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT);
2791 if (feature_info_->workarounds().unbind_fbo_on_context_switch) {
2792 context_->SetUnbindFboOnMakeCurrent();
2795 // Only compositor contexts are known to use only the subset of GL
2796 // that can be safely migrated between the iGPU and the dGPU. Mark
2797 // those contexts as safe to forcibly transition between the GPUs.
2798 // http://crbug.com/180876, http://crbug.com/227228
2799 if (!offscreen)
2800 context_->SetSafeToForceGpuSwitch();
2802 async_pixel_transfer_manager_.reset(
2803 AsyncPixelTransferManager::Create(context.get()));
2804 async_pixel_transfer_manager_->Initialize(texture_manager());
2806 if (workarounds().gl_clear_broken) {
2807 DCHECK(!clear_framebuffer_blit_.get());
2808 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glClearWorkaroundInit");
2809 clear_framebuffer_blit_.reset(new ClearFramebufferResourceManager(this));
2810 if (LOCAL_PEEK_GL_ERROR("glClearWorkaroundInit") != GL_NO_ERROR)
2811 return false;
2814 framebuffer_manager()->AddObserver(this);
2816 return true;
2819 Capabilities GLES2DecoderImpl::GetCapabilities() {
2820 DCHECK(initialized());
2822 Capabilities caps;
2823 caps.VisitPrecisions([](GLenum shader, GLenum type,
2824 Capabilities::ShaderPrecision* shader_precision) {
2825 GLint range[2] = {0, 0};
2826 GLint precision = 0;
2827 GetShaderPrecisionFormatImpl(shader, type, range, &precision);
2828 shader_precision->min_range = range[0];
2829 shader_precision->max_range = range[1];
2830 shader_precision->precision = precision;
2832 DoGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS,
2833 &caps.max_combined_texture_image_units);
2834 DoGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &caps.max_cube_map_texture_size);
2835 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS,
2836 &caps.max_fragment_uniform_vectors);
2837 DoGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &caps.max_renderbuffer_size);
2838 DoGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &caps.max_texture_image_units);
2839 DoGetIntegerv(GL_MAX_TEXTURE_SIZE, &caps.max_texture_size);
2840 DoGetIntegerv(GL_MAX_VARYING_VECTORS, &caps.max_varying_vectors);
2841 DoGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &caps.max_vertex_attribs);
2842 DoGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS,
2843 &caps.max_vertex_texture_image_units);
2844 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS,
2845 &caps.max_vertex_uniform_vectors);
2846 DoGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS,
2847 &caps.num_compressed_texture_formats);
2848 DoGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS, &caps.num_shader_binary_formats);
2849 DoGetIntegerv(GL_BIND_GENERATES_RESOURCE_CHROMIUM,
2850 &caps.bind_generates_resource_chromium);
2851 if (unsafe_es3_apis_enabled()) {
2852 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS,
2853 &caps.max_transform_feedback_separate_attribs);
2854 DoGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS,
2855 &caps.max_uniform_buffer_bindings);
2856 DoGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT,
2857 &caps.uniform_buffer_offset_alignment);
2860 caps.egl_image_external =
2861 feature_info_->feature_flags().oes_egl_image_external;
2862 caps.texture_format_atc =
2863 feature_info_->feature_flags().ext_texture_format_atc;
2864 caps.texture_format_bgra8888 =
2865 feature_info_->feature_flags().ext_texture_format_bgra8888;
2866 caps.texture_format_dxt1 =
2867 feature_info_->feature_flags().ext_texture_format_dxt1;
2868 caps.texture_format_dxt5 =
2869 feature_info_->feature_flags().ext_texture_format_dxt5;
2870 caps.texture_format_etc1 =
2871 feature_info_->feature_flags().oes_compressed_etc1_rgb8_texture;
2872 caps.texture_format_etc1_npot =
2873 caps.texture_format_etc1 && !workarounds().etc1_power_of_two_only;
2874 caps.texture_rectangle = feature_info_->feature_flags().arb_texture_rectangle;
2875 caps.texture_usage = feature_info_->feature_flags().angle_texture_usage;
2876 caps.texture_storage = feature_info_->feature_flags().ext_texture_storage;
2877 caps.discard_framebuffer =
2878 feature_info_->feature_flags().ext_discard_framebuffer;
2879 caps.sync_query = feature_info_->feature_flags().chromium_sync_query;
2881 #if defined(OS_MACOSX)
2882 // This is unconditionally true on mac, no need to test for it at runtime.
2883 caps.iosurface = true;
2884 #endif
2886 caps.post_sub_buffer = supports_post_sub_buffer_;
2887 caps.image = true;
2889 caps.blend_equation_advanced =
2890 feature_info_->feature_flags().blend_equation_advanced;
2891 caps.blend_equation_advanced_coherent =
2892 feature_info_->feature_flags().blend_equation_advanced_coherent;
2893 caps.texture_rg = feature_info_->feature_flags().ext_texture_rg;
2894 return caps;
2897 void GLES2DecoderImpl::UpdateCapabilities() {
2898 util_.set_num_compressed_texture_formats(
2899 validators_->compressed_texture_format.GetValues().size());
2900 util_.set_num_shader_binary_formats(
2901 validators_->shader_binary_format.GetValues().size());
2904 bool GLES2DecoderImpl::InitializeShaderTranslator() {
2905 TRACE_EVENT0("gpu", "GLES2DecoderImpl::InitializeShaderTranslator");
2907 if (!use_shader_translator_) {
2908 return true;
2910 ShBuiltInResources resources;
2911 ShInitBuiltInResources(&resources);
2912 resources.MaxVertexAttribs = group_->max_vertex_attribs();
2913 resources.MaxVertexUniformVectors =
2914 group_->max_vertex_uniform_vectors();
2915 resources.MaxVaryingVectors = group_->max_varying_vectors();
2916 resources.MaxVertexTextureImageUnits =
2917 group_->max_vertex_texture_image_units();
2918 resources.MaxCombinedTextureImageUnits = group_->max_texture_units();
2919 resources.MaxTextureImageUnits = group_->max_texture_image_units();
2920 resources.MaxFragmentUniformVectors =
2921 group_->max_fragment_uniform_vectors();
2922 resources.MaxDrawBuffers = group_->max_draw_buffers();
2923 resources.MaxExpressionComplexity = 256;
2924 resources.MaxCallStackDepth = 256;
2926 GLint range[2] = { 0, 0 };
2927 GLint precision = 0;
2928 GetShaderPrecisionFormatImpl(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT,
2929 range, &precision);
2930 resources.FragmentPrecisionHigh =
2931 PrecisionMeetsSpecForHighpFloat(range[0], range[1], precision);
2933 if (force_webgl_glsl_validation_) {
2934 resources.OES_standard_derivatives = derivatives_explicitly_enabled_;
2935 resources.EXT_frag_depth = frag_depth_explicitly_enabled_;
2936 resources.EXT_draw_buffers = draw_buffers_explicitly_enabled_;
2937 if (!draw_buffers_explicitly_enabled_)
2938 resources.MaxDrawBuffers = 1;
2939 resources.EXT_shader_texture_lod = shader_texture_lod_explicitly_enabled_;
2940 resources.NV_draw_buffers =
2941 draw_buffers_explicitly_enabled_ && features().nv_draw_buffers;
2942 } else {
2943 resources.OES_standard_derivatives =
2944 features().oes_standard_derivatives ? 1 : 0;
2945 resources.ARB_texture_rectangle =
2946 features().arb_texture_rectangle ? 1 : 0;
2947 resources.OES_EGL_image_external =
2948 features().oes_egl_image_external ? 1 : 0;
2949 resources.EXT_draw_buffers =
2950 features().ext_draw_buffers ? 1 : 0;
2951 resources.EXT_frag_depth =
2952 features().ext_frag_depth ? 1 : 0;
2953 resources.EXT_shader_texture_lod =
2954 features().ext_shader_texture_lod ? 1 : 0;
2955 resources.NV_draw_buffers =
2956 features().nv_draw_buffers ? 1 : 0;
2959 ShShaderSpec shader_spec = force_webgl_glsl_validation_ ? SH_WEBGL_SPEC
2960 : SH_GLES2_SPEC;
2961 if (shader_spec == SH_WEBGL_SPEC && features().enable_shader_name_hashing)
2962 resources.HashFunction = &CityHash64;
2963 else
2964 resources.HashFunction = NULL;
2965 ShaderTranslatorInterface::GlslImplementationType implementation_type =
2966 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 ?
2967 ShaderTranslatorInterface::kGlslES : ShaderTranslatorInterface::kGlsl;
2968 int driver_bug_workarounds = 0;
2969 if (workarounds().needs_glsl_built_in_function_emulation)
2970 driver_bug_workarounds |= SH_EMULATE_BUILT_IN_FUNCTIONS;
2971 if (workarounds().init_gl_position_in_vertex_shader)
2972 driver_bug_workarounds |= SH_INIT_GL_POSITION;
2973 if (workarounds().unfold_short_circuit_as_ternary_operation)
2974 driver_bug_workarounds |= SH_UNFOLD_SHORT_CIRCUIT;
2975 if (workarounds().init_varyings_without_static_use)
2976 driver_bug_workarounds |= SH_INIT_VARYINGS_WITHOUT_STATIC_USE;
2977 if (workarounds().unroll_for_loop_with_sampler_array_index)
2978 driver_bug_workarounds |= SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX;
2979 if (workarounds().scalarize_vec_and_mat_constructor_args)
2980 driver_bug_workarounds |= SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS;
2981 if (workarounds().regenerate_struct_names)
2982 driver_bug_workarounds |= SH_REGENERATE_STRUCT_NAMES;
2984 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2985 switches::kEmulateShaderPrecision))
2986 resources.WEBGL_debug_shader_precision = true;
2988 vertex_translator_ = shader_translator_cache()->GetTranslator(
2989 GL_VERTEX_SHADER,
2990 shader_spec,
2991 &resources,
2992 implementation_type,
2993 static_cast<ShCompileOptions>(driver_bug_workarounds));
2994 if (!vertex_translator_.get()) {
2995 LOG(ERROR) << "Could not initialize vertex shader translator.";
2996 Destroy(true);
2997 return false;
3000 fragment_translator_ = shader_translator_cache()->GetTranslator(
3001 GL_FRAGMENT_SHADER,
3002 shader_spec,
3003 &resources,
3004 implementation_type,
3005 static_cast<ShCompileOptions>(driver_bug_workarounds));
3006 if (!fragment_translator_.get()) {
3007 LOG(ERROR) << "Could not initialize fragment shader translator.";
3008 Destroy(true);
3009 return false;
3011 return true;
3014 bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
3015 for (GLsizei ii = 0; ii < n; ++ii) {
3016 if (GetBuffer(client_ids[ii])) {
3017 return false;
3020 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3021 glGenBuffersARB(n, service_ids.get());
3022 for (GLsizei ii = 0; ii < n; ++ii) {
3023 CreateBuffer(client_ids[ii], service_ids[ii]);
3025 return true;
3028 bool GLES2DecoderImpl::GenFramebuffersHelper(
3029 GLsizei n, const GLuint* client_ids) {
3030 for (GLsizei ii = 0; ii < n; ++ii) {
3031 if (GetFramebuffer(client_ids[ii])) {
3032 return false;
3035 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3036 glGenFramebuffersEXT(n, service_ids.get());
3037 for (GLsizei ii = 0; ii < n; ++ii) {
3038 CreateFramebuffer(client_ids[ii], service_ids[ii]);
3040 return true;
3043 bool GLES2DecoderImpl::GenRenderbuffersHelper(
3044 GLsizei n, const GLuint* client_ids) {
3045 for (GLsizei ii = 0; ii < n; ++ii) {
3046 if (GetRenderbuffer(client_ids[ii])) {
3047 return false;
3050 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3051 glGenRenderbuffersEXT(n, service_ids.get());
3052 for (GLsizei ii = 0; ii < n; ++ii) {
3053 CreateRenderbuffer(client_ids[ii], service_ids[ii]);
3055 return true;
3058 bool GLES2DecoderImpl::GenValuebuffersCHROMIUMHelper(GLsizei n,
3059 const GLuint* client_ids) {
3060 for (GLsizei ii = 0; ii < n; ++ii) {
3061 if (GetValuebuffer(client_ids[ii])) {
3062 return false;
3065 for (GLsizei ii = 0; ii < n; ++ii) {
3066 CreateValuebuffer(client_ids[ii]);
3068 return true;
3071 bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
3072 for (GLsizei ii = 0; ii < n; ++ii) {
3073 if (GetTexture(client_ids[ii])) {
3074 return false;
3077 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3078 glGenTextures(n, service_ids.get());
3079 for (GLsizei ii = 0; ii < n; ++ii) {
3080 CreateTexture(client_ids[ii], service_ids[ii]);
3082 return true;
3085 void GLES2DecoderImpl::DeleteBuffersHelper(
3086 GLsizei n, const GLuint* client_ids) {
3087 for (GLsizei ii = 0; ii < n; ++ii) {
3088 Buffer* buffer = GetBuffer(client_ids[ii]);
3089 if (buffer && !buffer->IsDeleted()) {
3090 state_.vertex_attrib_manager->Unbind(buffer);
3091 if (state_.bound_array_buffer.get() == buffer) {
3092 state_.bound_array_buffer = NULL;
3094 RemoveBuffer(client_ids[ii]);
3099 void GLES2DecoderImpl::DeleteFramebuffersHelper(
3100 GLsizei n, const GLuint* client_ids) {
3101 bool supports_separate_framebuffer_binds =
3102 features().chromium_framebuffer_multisample;
3104 for (GLsizei ii = 0; ii < n; ++ii) {
3105 Framebuffer* framebuffer =
3106 GetFramebuffer(client_ids[ii]);
3107 if (framebuffer && !framebuffer->IsDeleted()) {
3108 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
3109 GLenum target = supports_separate_framebuffer_binds ?
3110 GL_DRAW_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
3112 // Unbind attachments on FBO before deletion.
3113 if (workarounds().unbind_attachments_on_bound_render_fbo_delete)
3114 framebuffer->DoUnbindGLAttachmentsForWorkaround(target);
3116 glBindFramebufferEXT(target, GetBackbufferServiceId());
3117 framebuffer_state_.bound_draw_framebuffer = NULL;
3118 framebuffer_state_.clear_state_dirty = true;
3120 if (framebuffer == framebuffer_state_.bound_read_framebuffer.get()) {
3121 framebuffer_state_.bound_read_framebuffer = NULL;
3122 GLenum target = supports_separate_framebuffer_binds ?
3123 GL_READ_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
3124 glBindFramebufferEXT(target, GetBackbufferServiceId());
3126 OnFboChanged();
3127 RemoveFramebuffer(client_ids[ii]);
3132 void GLES2DecoderImpl::DeleteRenderbuffersHelper(
3133 GLsizei n, const GLuint* client_ids) {
3134 bool supports_separate_framebuffer_binds =
3135 features().chromium_framebuffer_multisample;
3136 for (GLsizei ii = 0; ii < n; ++ii) {
3137 Renderbuffer* renderbuffer =
3138 GetRenderbuffer(client_ids[ii]);
3139 if (renderbuffer && !renderbuffer->IsDeleted()) {
3140 if (state_.bound_renderbuffer.get() == renderbuffer) {
3141 state_.bound_renderbuffer = NULL;
3143 // Unbind from current framebuffers.
3144 if (supports_separate_framebuffer_binds) {
3145 if (framebuffer_state_.bound_read_framebuffer.get()) {
3146 framebuffer_state_.bound_read_framebuffer
3147 ->UnbindRenderbuffer(GL_READ_FRAMEBUFFER_EXT, renderbuffer);
3149 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3150 framebuffer_state_.bound_draw_framebuffer
3151 ->UnbindRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT, renderbuffer);
3153 } else {
3154 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3155 framebuffer_state_.bound_draw_framebuffer
3156 ->UnbindRenderbuffer(GL_FRAMEBUFFER, renderbuffer);
3159 framebuffer_state_.clear_state_dirty = true;
3160 RemoveRenderbuffer(client_ids[ii]);
3165 void GLES2DecoderImpl::DeleteValuebuffersCHROMIUMHelper(
3166 GLsizei n,
3167 const GLuint* client_ids) {
3168 for (GLsizei ii = 0; ii < n; ++ii) {
3169 Valuebuffer* valuebuffer = GetValuebuffer(client_ids[ii]);
3170 if (valuebuffer) {
3171 if (state_.bound_valuebuffer.get() == valuebuffer) {
3172 state_.bound_valuebuffer = NULL;
3174 RemoveValuebuffer(client_ids[ii]);
3179 void GLES2DecoderImpl::DeleteTexturesHelper(
3180 GLsizei n, const GLuint* client_ids) {
3181 bool supports_separate_framebuffer_binds =
3182 features().chromium_framebuffer_multisample;
3183 for (GLsizei ii = 0; ii < n; ++ii) {
3184 TextureRef* texture_ref = GetTexture(client_ids[ii]);
3185 if (texture_ref) {
3186 Texture* texture = texture_ref->texture();
3187 if (texture->IsAttachedToFramebuffer()) {
3188 framebuffer_state_.clear_state_dirty = true;
3190 // Unbind texture_ref from texture_ref units.
3191 for (size_t jj = 0; jj < state_.texture_units.size(); ++jj) {
3192 state_.texture_units[jj].Unbind(texture_ref);
3194 // Unbind from current framebuffers.
3195 if (supports_separate_framebuffer_binds) {
3196 if (framebuffer_state_.bound_read_framebuffer.get()) {
3197 framebuffer_state_.bound_read_framebuffer
3198 ->UnbindTexture(GL_READ_FRAMEBUFFER_EXT, texture_ref);
3200 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3201 framebuffer_state_.bound_draw_framebuffer
3202 ->UnbindTexture(GL_DRAW_FRAMEBUFFER_EXT, texture_ref);
3204 } else {
3205 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3206 framebuffer_state_.bound_draw_framebuffer
3207 ->UnbindTexture(GL_FRAMEBUFFER, texture_ref);
3210 #if defined(OS_MACOSX)
3211 GLuint service_id = texture->service_id();
3212 if (texture->target() == GL_TEXTURE_RECTANGLE_ARB) {
3213 ReleaseIOSurfaceForTexture(service_id);
3215 #endif
3216 RemoveTexture(client_ids[ii]);
3221 // } // anonymous namespace
3223 bool GLES2DecoderImpl::MakeCurrent() {
3224 if (!context_.get())
3225 return false;
3227 if (!context_->MakeCurrent(surface_.get()) || WasContextLost()) {
3228 LOG(ERROR) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
3230 MaybeExitOnContextLost();
3232 return false;
3235 ProcessFinishedAsyncTransfers();
3237 // Rebind the FBO if it was unbound by the context.
3238 if (workarounds().unbind_fbo_on_context_switch)
3239 RestoreFramebufferBindings();
3241 framebuffer_state_.clear_state_dirty = true;
3243 return true;
3246 void GLES2DecoderImpl::ProcessFinishedAsyncTransfers() {
3247 ProcessPendingReadPixels();
3248 if (engine() && query_manager_.get())
3249 query_manager_->ProcessPendingTransferQueries();
3251 // TODO(epenner): Is there a better place to do this?
3252 // This needs to occur before we execute any batch of commands
3253 // from the client, as the client may have recieved an async
3254 // completion while issuing those commands.
3255 // "DidFlushStart" would be ideal if we had such a callback.
3256 async_pixel_transfer_manager_->BindCompletedAsyncTransfers();
3259 static void RebindCurrentFramebuffer(
3260 GLenum target,
3261 Framebuffer* framebuffer,
3262 GLuint back_buffer_service_id) {
3263 GLuint framebuffer_id = framebuffer ? framebuffer->service_id() : 0;
3265 if (framebuffer_id == 0) {
3266 framebuffer_id = back_buffer_service_id;
3269 glBindFramebufferEXT(target, framebuffer_id);
3272 void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
3273 framebuffer_state_.clear_state_dirty = true;
3275 if (!features().chromium_framebuffer_multisample) {
3276 RebindCurrentFramebuffer(
3277 GL_FRAMEBUFFER,
3278 framebuffer_state_.bound_draw_framebuffer.get(),
3279 GetBackbufferServiceId());
3280 } else {
3281 RebindCurrentFramebuffer(
3282 GL_READ_FRAMEBUFFER_EXT,
3283 framebuffer_state_.bound_read_framebuffer.get(),
3284 GetBackbufferServiceId());
3285 RebindCurrentFramebuffer(
3286 GL_DRAW_FRAMEBUFFER_EXT,
3287 framebuffer_state_.bound_draw_framebuffer.get(),
3288 GetBackbufferServiceId());
3290 OnFboChanged();
3293 bool GLES2DecoderImpl::CheckFramebufferValid(
3294 Framebuffer* framebuffer,
3295 GLenum target, const char* func_name) {
3296 if (!framebuffer) {
3297 if (surfaceless_)
3298 return false;
3299 if (backbuffer_needs_clear_bits_) {
3300 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3301 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1.f);
3302 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3303 glClearStencil(0);
3304 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
3305 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
3306 glClearDepth(1.0f);
3307 state_.SetDeviceDepthMask(GL_TRUE);
3308 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
3309 bool reset_draw_buffer = false;
3310 if ((backbuffer_needs_clear_bits_ & GL_COLOR_BUFFER_BIT) != 0 &&
3311 group_->draw_buffer() == GL_NONE) {
3312 reset_draw_buffer = true;
3313 GLenum buf = GL_BACK;
3314 if (GetBackbufferServiceId() != 0) // emulated backbuffer
3315 buf = GL_COLOR_ATTACHMENT0;
3316 glDrawBuffersARB(1, &buf);
3318 glClear(backbuffer_needs_clear_bits_);
3319 if (reset_draw_buffer) {
3320 GLenum buf = GL_NONE;
3321 glDrawBuffersARB(1, &buf);
3323 backbuffer_needs_clear_bits_ = 0;
3324 RestoreClearState();
3326 return true;
3329 if (framebuffer_manager()->IsComplete(framebuffer)) {
3330 return true;
3333 GLenum completeness = framebuffer->IsPossiblyComplete();
3334 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
3335 LOCAL_SET_GL_ERROR(
3336 GL_INVALID_FRAMEBUFFER_OPERATION, func_name, "framebuffer incomplete");
3337 return false;
3340 // Are all the attachments cleared?
3341 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
3342 texture_manager()->HaveUnclearedMips()) {
3343 if (!framebuffer->IsCleared()) {
3344 // Can we clear them?
3345 if (framebuffer->GetStatus(texture_manager(), target) !=
3346 GL_FRAMEBUFFER_COMPLETE) {
3347 LOCAL_SET_GL_ERROR(
3348 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
3349 "framebuffer incomplete (clear)");
3350 return false;
3352 ClearUnclearedAttachments(target, framebuffer);
3356 if (!framebuffer_manager()->IsComplete(framebuffer)) {
3357 if (framebuffer->GetStatus(texture_manager(), target) !=
3358 GL_FRAMEBUFFER_COMPLETE) {
3359 LOCAL_SET_GL_ERROR(
3360 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
3361 "framebuffer incomplete (check)");
3362 return false;
3364 framebuffer_manager()->MarkAsComplete(framebuffer);
3367 // NOTE: At this point we don't know if the framebuffer is complete but
3368 // we DO know that everything that needs to be cleared has been cleared.
3369 return true;
3372 bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name) {
3373 if (!features().chromium_framebuffer_multisample) {
3374 bool valid = CheckFramebufferValid(
3375 framebuffer_state_.bound_draw_framebuffer.get(), GL_FRAMEBUFFER_EXT,
3376 func_name);
3378 if (valid)
3379 OnUseFramebuffer();
3381 return valid;
3383 return CheckFramebufferValid(framebuffer_state_.bound_draw_framebuffer.get(),
3384 GL_DRAW_FRAMEBUFFER_EXT,
3385 func_name) &&
3386 CheckFramebufferValid(framebuffer_state_.bound_read_framebuffer.get(),
3387 GL_READ_FRAMEBUFFER_EXT,
3388 func_name);
3391 bool GLES2DecoderImpl::CheckBoundReadFramebufferColorAttachment(
3392 const char* func_name) {
3393 Framebuffer* framebuffer = features().chromium_framebuffer_multisample ?
3394 framebuffer_state_.bound_read_framebuffer.get() :
3395 framebuffer_state_.bound_draw_framebuffer.get();
3396 if (!framebuffer)
3397 return true;
3398 if (framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0) == NULL) {
3399 LOCAL_SET_GL_ERROR(
3400 GL_INVALID_OPERATION, func_name, "no color image attached");
3401 return false;
3403 return true;
3406 bool GLES2DecoderImpl::FormsTextureCopyingFeedbackLoop(
3407 TextureRef* texture, GLint level) {
3408 Framebuffer* framebuffer = features().chromium_framebuffer_multisample ?
3409 framebuffer_state_.bound_read_framebuffer.get() :
3410 framebuffer_state_.bound_draw_framebuffer.get();
3411 if (!framebuffer)
3412 return false;
3413 const Framebuffer::Attachment* attachment = framebuffer->GetAttachment(
3414 GL_COLOR_ATTACHMENT0);
3415 if (!attachment)
3416 return false;
3417 return attachment->FormsFeedbackLoop(texture, level);
3420 gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
3421 Framebuffer* framebuffer =
3422 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3423 if (framebuffer != NULL) {
3424 const Framebuffer::Attachment* attachment =
3425 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
3426 if (attachment) {
3427 return gfx::Size(attachment->width(), attachment->height());
3429 return gfx::Size(0, 0);
3430 } else if (offscreen_target_frame_buffer_.get()) {
3431 return offscreen_size_;
3432 } else {
3433 return surface_->GetSize();
3437 GLenum GLES2DecoderImpl::GetBoundReadFrameBufferTextureType() {
3438 Framebuffer* framebuffer =
3439 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3440 if (framebuffer != NULL) {
3441 return framebuffer->GetColorAttachmentTextureType();
3442 } else {
3443 return GL_UNSIGNED_BYTE;
3447 GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
3448 Framebuffer* framebuffer =
3449 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3450 if (framebuffer != NULL) {
3451 return framebuffer->GetColorAttachmentFormat();
3452 } else if (offscreen_target_frame_buffer_.get()) {
3453 return offscreen_target_color_format_;
3454 } else {
3455 return back_buffer_color_format_;
3459 GLenum GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
3460 Framebuffer* framebuffer =
3461 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3462 if (framebuffer != NULL) {
3463 return framebuffer->GetColorAttachmentFormat();
3464 } else if (offscreen_target_frame_buffer_.get()) {
3465 return offscreen_target_color_format_;
3466 } else {
3467 return back_buffer_color_format_;
3471 void GLES2DecoderImpl::UpdateParentTextureInfo() {
3472 if (!offscreen_saved_color_texture_info_.get())
3473 return;
3474 GLenum target = offscreen_saved_color_texture_info_->texture()->target();
3475 glBindTexture(target, offscreen_saved_color_texture_info_->service_id());
3476 texture_manager()->SetLevelInfo(
3477 offscreen_saved_color_texture_info_.get(),
3478 GL_TEXTURE_2D,
3479 0, // level
3480 GL_RGBA,
3481 offscreen_size_.width(),
3482 offscreen_size_.height(),
3483 1, // depth
3484 0, // border
3485 GL_RGBA,
3486 GL_UNSIGNED_BYTE,
3487 true);
3488 texture_manager()->SetParameteri(
3489 "UpdateParentTextureInfo",
3490 GetErrorState(),
3491 offscreen_saved_color_texture_info_.get(),
3492 GL_TEXTURE_MAG_FILTER,
3493 GL_LINEAR);
3494 texture_manager()->SetParameteri(
3495 "UpdateParentTextureInfo",
3496 GetErrorState(),
3497 offscreen_saved_color_texture_info_.get(),
3498 GL_TEXTURE_MIN_FILTER,
3499 GL_LINEAR);
3500 texture_manager()->SetParameteri(
3501 "UpdateParentTextureInfo",
3502 GetErrorState(),
3503 offscreen_saved_color_texture_info_.get(),
3504 GL_TEXTURE_WRAP_S,
3505 GL_CLAMP_TO_EDGE);
3506 texture_manager()->SetParameteri(
3507 "UpdateParentTextureInfo",
3508 GetErrorState(),
3509 offscreen_saved_color_texture_info_.get(),
3510 GL_TEXTURE_WRAP_T,
3511 GL_CLAMP_TO_EDGE);
3512 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
3513 &state_, target);
3514 glBindTexture(target, texture_ref ? texture_ref->service_id() : 0);
3517 void GLES2DecoderImpl::SetResizeCallback(
3518 const base::Callback<void(gfx::Size, float)>& callback) {
3519 resize_callback_ = callback;
3522 Logger* GLES2DecoderImpl::GetLogger() {
3523 return &logger_;
3526 void GLES2DecoderImpl::BeginDecoding() {
3527 gpu_tracer_->BeginDecoding();
3528 gpu_trace_commands_ = gpu_tracer_->IsTracing() && *gpu_decoder_category_;
3529 gpu_debug_commands_ = log_commands() || debug() || gpu_trace_commands_ ||
3530 (*cb_command_trace_category_ != 0);
3533 void GLES2DecoderImpl::EndDecoding() {
3534 gpu_tracer_->EndDecoding();
3537 ErrorState* GLES2DecoderImpl::GetErrorState() {
3538 return state_.GetErrorState();
3541 void GLES2DecoderImpl::SetShaderCacheCallback(
3542 const ShaderCacheCallback& callback) {
3543 shader_cache_callback_ = callback;
3546 void GLES2DecoderImpl::SetWaitSyncPointCallback(
3547 const WaitSyncPointCallback& callback) {
3548 wait_sync_point_callback_ = callback;
3551 AsyncPixelTransferManager*
3552 GLES2DecoderImpl::GetAsyncPixelTransferManager() {
3553 return async_pixel_transfer_manager_.get();
3556 void GLES2DecoderImpl::ResetAsyncPixelTransferManagerForTest() {
3557 async_pixel_transfer_manager_.reset();
3560 void GLES2DecoderImpl::SetAsyncPixelTransferManagerForTest(
3561 AsyncPixelTransferManager* manager) {
3562 async_pixel_transfer_manager_ = make_scoped_ptr(manager);
3565 bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
3566 uint32* service_texture_id) {
3567 TextureRef* texture_ref = texture_manager()->GetTexture(client_texture_id);
3568 if (texture_ref) {
3569 *service_texture_id = texture_ref->service_id();
3570 return true;
3572 return false;
3575 uint32 GLES2DecoderImpl::GetTextureUploadCount() {
3576 return texture_state_.texture_upload_count +
3577 async_pixel_transfer_manager_->GetTextureUploadCount();
3580 base::TimeDelta GLES2DecoderImpl::GetTotalTextureUploadTime() {
3581 return texture_state_.total_texture_upload_time +
3582 async_pixel_transfer_manager_->GetTotalTextureUploadTime();
3585 base::TimeDelta GLES2DecoderImpl::GetTotalProcessingCommandsTime() {
3586 return total_processing_commands_time_;
3589 void GLES2DecoderImpl::AddProcessingCommandsTime(base::TimeDelta time) {
3590 total_processing_commands_time_ += time;
3593 void GLES2DecoderImpl::Destroy(bool have_context) {
3594 if (!initialized())
3595 return;
3597 DCHECK(!have_context || context_->IsCurrent(NULL));
3599 // Unbind everything.
3600 state_.vertex_attrib_manager = NULL;
3601 state_.default_vertex_attrib_manager = NULL;
3602 state_.texture_units.clear();
3603 state_.bound_array_buffer = NULL;
3604 state_.current_queries.clear();
3605 framebuffer_state_.bound_read_framebuffer = NULL;
3606 framebuffer_state_.bound_draw_framebuffer = NULL;
3607 state_.bound_renderbuffer = NULL;
3608 state_.bound_valuebuffer = NULL;
3610 if (offscreen_saved_color_texture_info_.get()) {
3611 DCHECK(offscreen_target_color_texture_);
3612 DCHECK_EQ(offscreen_saved_color_texture_info_->service_id(),
3613 offscreen_saved_color_texture_->id());
3614 offscreen_saved_color_texture_->Invalidate();
3615 offscreen_saved_color_texture_info_ = NULL;
3617 if (have_context) {
3618 if (copy_texture_CHROMIUM_.get()) {
3619 copy_texture_CHROMIUM_->Destroy();
3620 copy_texture_CHROMIUM_.reset();
3623 clear_framebuffer_blit_.reset();
3625 if (state_.current_program.get()) {
3626 program_manager()->UnuseProgram(shader_manager(),
3627 state_.current_program.get());
3630 if (attrib_0_buffer_id_) {
3631 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
3633 if (fixed_attrib_buffer_id_) {
3634 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_);
3637 if (validation_texture_) {
3638 glDeleteTextures(1, &validation_texture_);
3639 glDeleteFramebuffersEXT(1, &validation_fbo_multisample_);
3640 glDeleteFramebuffersEXT(1, &validation_fbo_);
3643 if (offscreen_target_frame_buffer_.get())
3644 offscreen_target_frame_buffer_->Destroy();
3645 if (offscreen_target_color_texture_.get())
3646 offscreen_target_color_texture_->Destroy();
3647 if (offscreen_target_color_render_buffer_.get())
3648 offscreen_target_color_render_buffer_->Destroy();
3649 if (offscreen_target_depth_render_buffer_.get())
3650 offscreen_target_depth_render_buffer_->Destroy();
3651 if (offscreen_target_stencil_render_buffer_.get())
3652 offscreen_target_stencil_render_buffer_->Destroy();
3653 if (offscreen_saved_frame_buffer_.get())
3654 offscreen_saved_frame_buffer_->Destroy();
3655 if (offscreen_saved_color_texture_.get())
3656 offscreen_saved_color_texture_->Destroy();
3657 if (offscreen_resolved_frame_buffer_.get())
3658 offscreen_resolved_frame_buffer_->Destroy();
3659 if (offscreen_resolved_color_texture_.get())
3660 offscreen_resolved_color_texture_->Destroy();
3661 } else {
3662 if (offscreen_target_frame_buffer_.get())
3663 offscreen_target_frame_buffer_->Invalidate();
3664 if (offscreen_target_color_texture_.get())
3665 offscreen_target_color_texture_->Invalidate();
3666 if (offscreen_target_color_render_buffer_.get())
3667 offscreen_target_color_render_buffer_->Invalidate();
3668 if (offscreen_target_depth_render_buffer_.get())
3669 offscreen_target_depth_render_buffer_->Invalidate();
3670 if (offscreen_target_stencil_render_buffer_.get())
3671 offscreen_target_stencil_render_buffer_->Invalidate();
3672 if (offscreen_saved_frame_buffer_.get())
3673 offscreen_saved_frame_buffer_->Invalidate();
3674 if (offscreen_saved_color_texture_.get())
3675 offscreen_saved_color_texture_->Invalidate();
3676 if (offscreen_resolved_frame_buffer_.get())
3677 offscreen_resolved_frame_buffer_->Invalidate();
3678 if (offscreen_resolved_color_texture_.get())
3679 offscreen_resolved_color_texture_->Invalidate();
3682 // Current program must be cleared after calling ProgramManager::UnuseProgram.
3683 // Otherwise, we can leak objects. http://crbug.com/258772.
3684 // state_.current_program must be reset before group_ is reset because
3685 // the later deletes the ProgramManager object that referred by
3686 // state_.current_program object.
3687 state_.current_program = NULL;
3689 copy_texture_CHROMIUM_.reset();
3690 clear_framebuffer_blit_.reset();
3692 if (query_manager_.get()) {
3693 query_manager_->Destroy(have_context);
3694 query_manager_.reset();
3697 if (vertex_array_manager_ .get()) {
3698 vertex_array_manager_->Destroy(have_context);
3699 vertex_array_manager_.reset();
3702 if (image_manager_.get()) {
3703 image_manager_->Destroy(have_context);
3704 image_manager_.reset();
3707 offscreen_target_frame_buffer_.reset();
3708 offscreen_target_color_texture_.reset();
3709 offscreen_target_color_render_buffer_.reset();
3710 offscreen_target_depth_render_buffer_.reset();
3711 offscreen_target_stencil_render_buffer_.reset();
3712 offscreen_saved_frame_buffer_.reset();
3713 offscreen_saved_color_texture_.reset();
3714 offscreen_resolved_frame_buffer_.reset();
3715 offscreen_resolved_color_texture_.reset();
3717 // Need to release these before releasing |group_| which may own the
3718 // ShaderTranslatorCache.
3719 fragment_translator_ = NULL;
3720 vertex_translator_ = NULL;
3722 // Should destroy the transfer manager before the texture manager held
3723 // by the context group.
3724 async_pixel_transfer_manager_.reset();
3726 if (group_.get()) {
3727 framebuffer_manager()->RemoveObserver(this);
3728 group_->Destroy(this, have_context);
3729 group_ = NULL;
3732 if (context_.get()) {
3733 context_->ReleaseCurrent(NULL);
3734 context_ = NULL;
3737 #if defined(OS_MACOSX)
3738 for (TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.begin();
3739 it != texture_to_io_surface_map_.end(); ++it) {
3740 CFRelease(it->second);
3742 texture_to_io_surface_map_.clear();
3743 #endif
3746 void GLES2DecoderImpl::SetSurface(
3747 const scoped_refptr<gfx::GLSurface>& surface) {
3748 DCHECK(context_->IsCurrent(NULL));
3749 DCHECK(surface_.get());
3750 surface_ = surface;
3751 RestoreCurrentFramebufferBindings();
3754 void GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox& mailbox) {
3755 if (!offscreen_saved_color_texture_.get()) {
3756 LOG(ERROR) << "Called ProduceFrontBuffer on a non-offscreen context";
3757 return;
3759 if (!offscreen_saved_color_texture_info_.get()) {
3760 GLuint service_id = offscreen_saved_color_texture_->id();
3761 offscreen_saved_color_texture_info_ = TextureRef::Create(
3762 texture_manager(), 0, service_id);
3763 texture_manager()->SetTarget(offscreen_saved_color_texture_info_.get(),
3764 GL_TEXTURE_2D);
3765 UpdateParentTextureInfo();
3767 mailbox_manager()->ProduceTexture(
3768 mailbox, offscreen_saved_color_texture_info_->texture());
3771 bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
3772 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
3773 if (!is_offscreen) {
3774 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
3775 << " with an onscreen framebuffer.";
3776 return false;
3779 if (offscreen_size_ == size)
3780 return true;
3782 offscreen_size_ = size;
3783 int w = offscreen_size_.width();
3784 int h = offscreen_size_.height();
3785 if (w < 0 || h < 0 || h >= (INT_MAX / 4) / (w ? w : 1)) {
3786 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3787 << "to allocate storage due to excessive dimensions.";
3788 return false;
3791 // Reallocate the offscreen target buffers.
3792 DCHECK(offscreen_target_color_format_);
3793 if (IsOffscreenBufferMultisampled()) {
3794 if (!offscreen_target_color_render_buffer_->AllocateStorage(
3795 feature_info_.get(),
3796 offscreen_size_,
3797 offscreen_target_color_format_,
3798 offscreen_target_samples_)) {
3799 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3800 << "to allocate storage for offscreen target color buffer.";
3801 return false;
3803 } else {
3804 if (!offscreen_target_color_texture_->AllocateStorage(
3805 offscreen_size_, offscreen_target_color_format_, false)) {
3806 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3807 << "to allocate storage for offscreen target color texture.";
3808 return false;
3811 if (offscreen_target_depth_format_ &&
3812 !offscreen_target_depth_render_buffer_->AllocateStorage(
3813 feature_info_.get(),
3814 offscreen_size_,
3815 offscreen_target_depth_format_,
3816 offscreen_target_samples_)) {
3817 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3818 << "to allocate storage for offscreen target depth buffer.";
3819 return false;
3821 if (offscreen_target_stencil_format_ &&
3822 !offscreen_target_stencil_render_buffer_->AllocateStorage(
3823 feature_info_.get(),
3824 offscreen_size_,
3825 offscreen_target_stencil_format_,
3826 offscreen_target_samples_)) {
3827 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3828 << "to allocate storage for offscreen target stencil buffer.";
3829 return false;
3832 // Attach the offscreen target buffers to the target frame buffer.
3833 if (IsOffscreenBufferMultisampled()) {
3834 offscreen_target_frame_buffer_->AttachRenderBuffer(
3835 GL_COLOR_ATTACHMENT0,
3836 offscreen_target_color_render_buffer_.get());
3837 } else {
3838 offscreen_target_frame_buffer_->AttachRenderTexture(
3839 offscreen_target_color_texture_.get());
3841 if (offscreen_target_depth_format_) {
3842 offscreen_target_frame_buffer_->AttachRenderBuffer(
3843 GL_DEPTH_ATTACHMENT,
3844 offscreen_target_depth_render_buffer_.get());
3846 const bool packed_depth_stencil =
3847 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
3848 if (packed_depth_stencil) {
3849 offscreen_target_frame_buffer_->AttachRenderBuffer(
3850 GL_STENCIL_ATTACHMENT,
3851 offscreen_target_depth_render_buffer_.get());
3852 } else if (offscreen_target_stencil_format_) {
3853 offscreen_target_frame_buffer_->AttachRenderBuffer(
3854 GL_STENCIL_ATTACHMENT,
3855 offscreen_target_stencil_render_buffer_.get());
3858 if (offscreen_target_frame_buffer_->CheckStatus() !=
3859 GL_FRAMEBUFFER_COMPLETE) {
3860 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3861 << "because offscreen FBO was incomplete.";
3862 return false;
3865 // Clear the target frame buffer.
3867 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
3868 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3869 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1.f);
3870 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3871 glClearStencil(0);
3872 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
3873 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
3874 glClearDepth(0);
3875 state_.SetDeviceDepthMask(GL_TRUE);
3876 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
3877 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3878 RestoreClearState();
3881 // Destroy the offscreen resolved framebuffers.
3882 if (offscreen_resolved_frame_buffer_.get())
3883 offscreen_resolved_frame_buffer_->Destroy();
3884 if (offscreen_resolved_color_texture_.get())
3885 offscreen_resolved_color_texture_->Destroy();
3886 offscreen_resolved_color_texture_.reset();
3887 offscreen_resolved_frame_buffer_.reset();
3889 return true;
3892 error::Error GLES2DecoderImpl::HandleResizeCHROMIUM(uint32 immediate_data_size,
3893 const void* cmd_data) {
3894 const gles2::cmds::ResizeCHROMIUM& c =
3895 *static_cast<const gles2::cmds::ResizeCHROMIUM*>(cmd_data);
3896 if (!offscreen_target_frame_buffer_.get() && surface_->DeferDraws())
3897 return error::kDeferCommandUntilLater;
3899 GLuint width = static_cast<GLuint>(c.width);
3900 GLuint height = static_cast<GLuint>(c.height);
3901 GLfloat scale_factor = c.scale_factor;
3902 TRACE_EVENT2("gpu", "glResizeChromium", "width", width, "height", height);
3904 width = std::max(1U, width);
3905 height = std::max(1U, height);
3907 #if defined(OS_POSIX) && !defined(OS_MACOSX) && \
3908 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
3909 // Make sure that we are done drawing to the back buffer before resizing.
3910 glFinish();
3911 #endif
3912 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
3913 if (is_offscreen) {
3914 if (!ResizeOffscreenFrameBuffer(gfx::Size(width, height))) {
3915 LOG(ERROR) << "GLES2DecoderImpl: Context lost because "
3916 << "ResizeOffscreenFrameBuffer failed.";
3917 return error::kLostContext;
3921 if (!resize_callback_.is_null()) {
3922 resize_callback_.Run(gfx::Size(width, height), scale_factor);
3923 DCHECK(context_->IsCurrent(surface_.get()));
3924 if (!context_->IsCurrent(surface_.get())) {
3925 LOG(ERROR) << "GLES2DecoderImpl: Context lost because context no longer "
3926 << "current after resize callback.";
3927 return error::kLostContext;
3931 return error::kNoError;
3934 const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
3935 if (command_id > kStartPoint && command_id < kNumCommands) {
3936 return gles2::GetCommandName(static_cast<CommandId>(command_id));
3938 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
3941 // Decode a command, and call the corresponding GL functions.
3942 // NOTE: DoCommand() is slower than calling DoCommands() on larger batches
3943 // of commands at once, and is now only used for tests that need to track
3944 // individual commands.
3945 error::Error GLES2DecoderImpl::DoCommand(unsigned int command,
3946 unsigned int arg_count,
3947 const void* cmd_data) {
3948 return DoCommands(1, cmd_data, arg_count + 1, 0);
3951 // Decode multiple commands, and call the corresponding GL functions.
3952 // NOTE: 'buffer' is a pointer to the command buffer. As such, it could be
3953 // changed by a (malicious) client at any time, so if validation has to happen,
3954 // it should operate on a copy of them.
3955 // NOTE: This is duplicating code from AsyncAPIInterface::DoCommands() in the
3956 // interest of performance in this critical execution loop.
3957 template <bool DebugImpl>
3958 error::Error GLES2DecoderImpl::DoCommandsImpl(unsigned int num_commands,
3959 const void* buffer,
3960 int num_entries,
3961 int* entries_processed) {
3962 commands_to_process_ = num_commands;
3963 error::Error result = error::kNoError;
3964 const CommandBufferEntry* cmd_data =
3965 static_cast<const CommandBufferEntry*>(buffer);
3966 int process_pos = 0;
3967 unsigned int command = 0;
3969 while (process_pos < num_entries && result == error::kNoError &&
3970 commands_to_process_--) {
3971 const unsigned int size = cmd_data->value_header.size;
3972 command = cmd_data->value_header.command;
3974 if (size == 0) {
3975 result = error::kInvalidSize;
3976 break;
3979 if (static_cast<int>(size) + process_pos > num_entries) {
3980 result = error::kOutOfBounds;
3981 break;
3984 if (DebugImpl) {
3985 TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
3986 GetCommandName(command));
3988 if (log_commands()) {
3989 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "]"
3990 << "cmd: " << GetCommandName(command);
3994 const unsigned int arg_count = size - 1;
3995 unsigned int command_index = command - kStartPoint - 1;
3996 if (command_index < arraysize(command_info)) {
3997 const CommandInfo& info = command_info[command_index];
3998 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
3999 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
4000 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
4001 bool doing_gpu_trace = false;
4002 if (DebugImpl && gpu_trace_commands_) {
4003 if (CMD_FLAG_GET_TRACE_LEVEL(info.cmd_flags) <= gpu_trace_level_) {
4004 doing_gpu_trace = true;
4005 gpu_tracer_->Begin(TRACE_DISABLED_BY_DEFAULT("gpu_decoder"),
4006 GetCommandName(command),
4007 kTraceDecoder);
4011 uint32 immediate_data_size = (arg_count - info_arg_count) *
4012 sizeof(CommandBufferEntry); // NOLINT
4014 result = (this->*info.cmd_handler)(immediate_data_size, cmd_data);
4016 if (DebugImpl && doing_gpu_trace)
4017 gpu_tracer_->End(kTraceDecoder);
4019 if (DebugImpl && debug()) {
4020 GLenum error;
4021 while ((error = glGetError()) != GL_NO_ERROR) {
4022 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "] "
4023 << "GL ERROR: " << GLES2Util::GetStringEnum(error)
4024 << " : " << GetCommandName(command);
4025 LOCAL_SET_GL_ERROR(error, "DoCommand", "GL error from driver");
4028 } else {
4029 result = error::kInvalidArguments;
4031 } else {
4032 result = DoCommonCommand(command, arg_count, cmd_data);
4035 if (DebugImpl) {
4036 TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
4037 GetCommandName(command));
4040 if (result == error::kNoError &&
4041 current_decoder_error_ != error::kNoError) {
4042 result = current_decoder_error_;
4043 current_decoder_error_ = error::kNoError;
4046 if (result != error::kDeferCommandUntilLater) {
4047 process_pos += size;
4048 cmd_data += size;
4052 if (entries_processed)
4053 *entries_processed = process_pos;
4055 if (error::IsError(result)) {
4056 LOG(ERROR) << "Error: " << result << " for Command "
4057 << GetCommandName(command);
4060 return result;
4063 error::Error GLES2DecoderImpl::DoCommands(unsigned int num_commands,
4064 const void* buffer,
4065 int num_entries,
4066 int* entries_processed) {
4067 if (gpu_debug_commands_) {
4068 return DoCommandsImpl<true>(
4069 num_commands, buffer, num_entries, entries_processed);
4070 } else {
4071 return DoCommandsImpl<false>(
4072 num_commands, buffer, num_entries, entries_processed);
4076 void GLES2DecoderImpl::RemoveBuffer(GLuint client_id) {
4077 buffer_manager()->RemoveBuffer(client_id);
4080 void GLES2DecoderImpl::DoFinish() {
4081 glFinish();
4082 ProcessPendingReadPixels();
4083 ProcessPendingQueries(true);
4086 void GLES2DecoderImpl::DoFlush() {
4087 glFlush();
4088 ProcessPendingQueries(false);
4091 void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
4092 GLuint texture_index = texture_unit - GL_TEXTURE0;
4093 if (texture_index >= state_.texture_units.size()) {
4094 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4095 "glActiveTexture", texture_unit, "texture_unit");
4096 return;
4098 state_.active_texture_unit = texture_index;
4099 glActiveTexture(texture_unit);
4102 void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
4103 Buffer* buffer = NULL;
4104 GLuint service_id = 0;
4105 if (client_id != 0) {
4106 buffer = GetBuffer(client_id);
4107 if (!buffer) {
4108 if (!group_->bind_generates_resource()) {
4109 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4110 "glBindBuffer",
4111 "id not generated by glGenBuffers");
4112 return;
4115 // It's a new id so make a buffer buffer for it.
4116 glGenBuffersARB(1, &service_id);
4117 CreateBuffer(client_id, service_id);
4118 buffer = GetBuffer(client_id);
4121 LogClientServiceForInfo(buffer, client_id, "glBindBuffer");
4122 if (buffer) {
4123 if (!buffer_manager()->SetTarget(buffer, target)) {
4124 LOCAL_SET_GL_ERROR(
4125 GL_INVALID_OPERATION,
4126 "glBindBuffer", "buffer bound to more than 1 target");
4127 return;
4129 service_id = buffer->service_id();
4131 switch (target) {
4132 case GL_ARRAY_BUFFER:
4133 state_.bound_array_buffer = buffer;
4134 break;
4135 case GL_ELEMENT_ARRAY_BUFFER:
4136 state_.vertex_attrib_manager->SetElementArrayBuffer(buffer);
4137 break;
4138 default:
4139 NOTREACHED(); // Validation should prevent us getting here.
4140 break;
4142 glBindBuffer(target, service_id);
4145 bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha(
4146 bool all_draw_buffers) {
4147 Framebuffer* framebuffer =
4148 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4149 if (!all_draw_buffers || !framebuffer) {
4150 return (GLES2Util::GetChannelsForFormat(
4151 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
4153 return framebuffer->HasAlphaMRT();
4156 bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
4157 Framebuffer* framebuffer =
4158 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4159 if (framebuffer) {
4160 return framebuffer->HasDepthAttachment();
4162 if (offscreen_target_frame_buffer_.get()) {
4163 return offscreen_target_depth_format_ != 0;
4165 return back_buffer_has_depth_;
4168 bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
4169 Framebuffer* framebuffer =
4170 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4171 if (framebuffer) {
4172 return framebuffer->HasStencilAttachment();
4174 if (offscreen_target_frame_buffer_.get()) {
4175 return offscreen_target_stencil_format_ != 0 ||
4176 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
4178 return back_buffer_has_stencil_;
4181 void GLES2DecoderImpl::ApplyDirtyState() {
4182 if (framebuffer_state_.clear_state_dirty) {
4183 bool have_alpha = BoundFramebufferHasColorAttachmentWithAlpha(true);
4184 state_.SetDeviceColorMask(state_.color_mask_red,
4185 state_.color_mask_green,
4186 state_.color_mask_blue,
4187 state_.color_mask_alpha && have_alpha);
4189 bool have_depth = BoundFramebufferHasDepthAttachment();
4190 state_.SetDeviceDepthMask(state_.depth_mask && have_depth);
4192 bool have_stencil = BoundFramebufferHasStencilAttachment();
4193 state_.SetDeviceStencilMaskSeparate(
4194 GL_FRONT, have_stencil ? state_.stencil_front_writemask : 0);
4195 state_.SetDeviceStencilMaskSeparate(
4196 GL_BACK, have_stencil ? state_.stencil_back_writemask : 0);
4198 state_.SetDeviceCapabilityState(
4199 GL_DEPTH_TEST, state_.enable_flags.depth_test && have_depth);
4200 state_.SetDeviceCapabilityState(
4201 GL_STENCIL_TEST, state_.enable_flags.stencil_test && have_stencil);
4202 framebuffer_state_.clear_state_dirty = false;
4206 GLuint GLES2DecoderImpl::GetBackbufferServiceId() const {
4207 return (offscreen_target_frame_buffer_.get())
4208 ? offscreen_target_frame_buffer_->id()
4209 : (surface_.get() ? surface_->GetBackingFrameBufferObject() : 0);
4212 void GLES2DecoderImpl::RestoreState(const ContextState* prev_state) {
4213 TRACE_EVENT1("gpu", "GLES2DecoderImpl::RestoreState",
4214 "context", logger_.GetLogPrefix());
4215 // Restore the Framebuffer first because of bugs in Intel drivers.
4216 // Intel drivers incorrectly clip the viewport settings to
4217 // the size of the current framebuffer object.
4218 RestoreFramebufferBindings();
4219 state_.RestoreState(prev_state);
4222 void GLES2DecoderImpl::RestoreFramebufferBindings() const {
4223 GLuint service_id =
4224 framebuffer_state_.bound_draw_framebuffer.get()
4225 ? framebuffer_state_.bound_draw_framebuffer->service_id()
4226 : GetBackbufferServiceId();
4227 if (!features().chromium_framebuffer_multisample) {
4228 glBindFramebufferEXT(GL_FRAMEBUFFER, service_id);
4229 } else {
4230 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, service_id);
4231 service_id = framebuffer_state_.bound_read_framebuffer.get()
4232 ? framebuffer_state_.bound_read_framebuffer->service_id()
4233 : GetBackbufferServiceId();
4234 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, service_id);
4236 OnFboChanged();
4239 void GLES2DecoderImpl::RestoreRenderbufferBindings() {
4240 state_.RestoreRenderbufferBindings();
4243 void GLES2DecoderImpl::RestoreTextureState(unsigned service_id) const {
4244 Texture* texture = texture_manager()->GetTextureForServiceId(service_id);
4245 if (texture) {
4246 GLenum target = texture->target();
4247 glBindTexture(target, service_id);
4248 glTexParameteri(
4249 target, GL_TEXTURE_WRAP_S, texture->wrap_s());
4250 glTexParameteri(
4251 target, GL_TEXTURE_WRAP_T, texture->wrap_t());
4252 glTexParameteri(
4253 target, GL_TEXTURE_MIN_FILTER, texture->min_filter());
4254 glTexParameteri(
4255 target, GL_TEXTURE_MAG_FILTER, texture->mag_filter());
4256 RestoreTextureUnitBindings(state_.active_texture_unit);
4260 void GLES2DecoderImpl::ClearAllAttributes() const {
4261 // Must use native VAO 0, as RestoreAllAttributes can't fully restore
4262 // other VAOs.
4263 if (feature_info_->feature_flags().native_vertex_array_object)
4264 glBindVertexArrayOES(0);
4266 for (uint32 i = 0; i < group_->max_vertex_attribs(); ++i) {
4267 if (i != 0) // Never disable attribute 0
4268 glDisableVertexAttribArray(i);
4269 if(features().angle_instanced_arrays)
4270 glVertexAttribDivisorANGLE(i, 0);
4274 void GLES2DecoderImpl::RestoreAllAttributes() const {
4275 state_.RestoreVertexAttribs();
4278 void GLES2DecoderImpl::SetIgnoreCachedStateForTest(bool ignore) {
4279 state_.SetIgnoreCachedStateForTest(ignore);
4282 void GLES2DecoderImpl::OnFboChanged() const {
4283 if (workarounds().restore_scissor_on_fbo_change)
4284 state_.fbo_binding_for_scissor_workaround_dirty_ = true;
4286 if (workarounds().gl_begin_gl_end_on_fbo_change_to_backbuffer) {
4287 GLint bound_fbo_unsigned = -1;
4288 glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &bound_fbo_unsigned);
4289 GLuint bound_fbo = static_cast<GLuint>(bound_fbo_unsigned);
4290 if (surface_ && surface_->GetBackingFrameBufferObject() == bound_fbo)
4291 surface_->NotifyWasBound();
4295 // Called after the FBO is checked for completeness.
4296 void GLES2DecoderImpl::OnUseFramebuffer() const {
4297 if (state_.fbo_binding_for_scissor_workaround_dirty_) {
4298 state_.fbo_binding_for_scissor_workaround_dirty_ = false;
4299 // The driver forgets the correct scissor when modifying the FBO binding.
4300 glScissor(state_.scissor_x,
4301 state_.scissor_y,
4302 state_.scissor_width,
4303 state_.scissor_height);
4305 // crbug.com/222018 - Also on QualComm, the flush here avoids flicker,
4306 // it's unclear how this bug works.
4307 glFlush();
4311 void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
4312 Framebuffer* framebuffer = NULL;
4313 GLuint service_id = 0;
4314 if (client_id != 0) {
4315 framebuffer = GetFramebuffer(client_id);
4316 if (!framebuffer) {
4317 if (!group_->bind_generates_resource()) {
4318 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4319 "glBindFramebuffer",
4320 "id not generated by glGenFramebuffers");
4321 return;
4324 // It's a new id so make a framebuffer framebuffer for it.
4325 glGenFramebuffersEXT(1, &service_id);
4326 CreateFramebuffer(client_id, service_id);
4327 framebuffer = GetFramebuffer(client_id);
4328 } else {
4329 service_id = framebuffer->service_id();
4331 framebuffer->MarkAsValid();
4333 LogClientServiceForInfo(framebuffer, client_id, "glBindFramebuffer");
4335 if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) {
4336 framebuffer_state_.bound_draw_framebuffer = framebuffer;
4339 // vmiura: This looks like dup code
4340 if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) {
4341 framebuffer_state_.bound_read_framebuffer = framebuffer;
4344 framebuffer_state_.clear_state_dirty = true;
4346 // If we are rendering to the backbuffer get the FBO id for any simulated
4347 // backbuffer.
4348 if (framebuffer == NULL) {
4349 service_id = GetBackbufferServiceId();
4352 glBindFramebufferEXT(target, service_id);
4353 OnFboChanged();
4356 void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
4357 Renderbuffer* renderbuffer = NULL;
4358 GLuint service_id = 0;
4359 if (client_id != 0) {
4360 renderbuffer = GetRenderbuffer(client_id);
4361 if (!renderbuffer) {
4362 if (!group_->bind_generates_resource()) {
4363 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4364 "glBindRenderbuffer",
4365 "id not generated by glGenRenderbuffers");
4366 return;
4369 // It's a new id so make a renderbuffer for it.
4370 glGenRenderbuffersEXT(1, &service_id);
4371 CreateRenderbuffer(client_id, service_id);
4372 renderbuffer = GetRenderbuffer(client_id);
4373 } else {
4374 service_id = renderbuffer->service_id();
4376 renderbuffer->MarkAsValid();
4378 LogClientServiceForInfo(renderbuffer, client_id, "glBindRenderbuffer");
4379 state_.bound_renderbuffer = renderbuffer;
4380 state_.bound_renderbuffer_valid = true;
4381 glBindRenderbufferEXT(GL_RENDERBUFFER, service_id);
4384 void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
4385 TextureRef* texture_ref = NULL;
4386 GLuint service_id = 0;
4387 if (client_id != 0) {
4388 texture_ref = GetTexture(client_id);
4389 if (!texture_ref) {
4390 if (!group_->bind_generates_resource()) {
4391 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4392 "glBindTexture",
4393 "id not generated by glGenTextures");
4394 return;
4397 // It's a new id so make a texture texture for it.
4398 glGenTextures(1, &service_id);
4399 DCHECK_NE(0u, service_id);
4400 CreateTexture(client_id, service_id);
4401 texture_ref = GetTexture(client_id);
4403 } else {
4404 texture_ref = texture_manager()->GetDefaultTextureInfo(target);
4407 // Check the texture exists
4408 if (texture_ref) {
4409 Texture* texture = texture_ref->texture();
4410 // Check that we are not trying to bind it to a different target.
4411 if (texture->target() != 0 && texture->target() != target) {
4412 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4413 "glBindTexture",
4414 "texture bound to more than 1 target.");
4415 return;
4417 LogClientServiceForInfo(texture, client_id, "glBindTexture");
4418 if (texture->target() == 0) {
4419 texture_manager()->SetTarget(texture_ref, target);
4421 glBindTexture(target, texture->service_id());
4422 } else {
4423 glBindTexture(target, 0);
4426 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4427 unit.bind_target = target;
4428 switch (target) {
4429 case GL_TEXTURE_2D:
4430 unit.bound_texture_2d = texture_ref;
4431 break;
4432 case GL_TEXTURE_CUBE_MAP:
4433 unit.bound_texture_cube_map = texture_ref;
4434 break;
4435 case GL_TEXTURE_EXTERNAL_OES:
4436 unit.bound_texture_external_oes = texture_ref;
4437 break;
4438 case GL_TEXTURE_RECTANGLE_ARB:
4439 unit.bound_texture_rectangle_arb = texture_ref;
4440 break;
4441 default:
4442 NOTREACHED(); // Validation should prevent us getting here.
4443 break;
4447 void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
4448 if (state_.vertex_attrib_manager->Enable(index, false)) {
4449 if (index != 0 ||
4450 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
4451 glDisableVertexAttribArray(index);
4453 } else {
4454 LOCAL_SET_GL_ERROR(
4455 GL_INVALID_VALUE,
4456 "glDisableVertexAttribArray", "index out of range");
4460 void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target,
4461 GLsizei numAttachments,
4462 const GLenum* attachments) {
4463 Framebuffer* framebuffer =
4464 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4466 // Validates the attachments. If one of them fails
4467 // the whole command fails.
4468 for (GLsizei i = 0; i < numAttachments; ++i) {
4469 if ((framebuffer &&
4470 !validators_->attachment.IsValid(attachments[i])) ||
4471 (!framebuffer &&
4472 !validators_->backbuffer_attachment.IsValid(attachments[i]))) {
4473 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4474 "glDiscardFramebufferEXT", attachments[i], "attachments");
4475 return;
4479 // Marks each one of them as not cleared
4480 for (GLsizei i = 0; i < numAttachments; ++i) {
4481 if (framebuffer) {
4482 framebuffer->MarkAttachmentAsCleared(renderbuffer_manager(),
4483 texture_manager(),
4484 attachments[i],
4485 false);
4486 } else {
4487 switch (attachments[i]) {
4488 case GL_COLOR_EXT:
4489 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
4490 break;
4491 case GL_DEPTH_EXT:
4492 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
4493 case GL_STENCIL_EXT:
4494 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
4495 break;
4496 default:
4497 NOTREACHED();
4498 break;
4503 // If the default framebuffer is bound but we are still rendering to an
4504 // FBO, translate attachment names that refer to default framebuffer
4505 // channels to corresponding framebuffer attachments.
4506 scoped_ptr<GLenum[]> translated_attachments(new GLenum[numAttachments]);
4507 for (GLsizei i = 0; i < numAttachments; ++i) {
4508 GLenum attachment = attachments[i];
4509 if (!framebuffer && GetBackbufferServiceId()) {
4510 switch (attachment) {
4511 case GL_COLOR_EXT:
4512 attachment = GL_COLOR_ATTACHMENT0;
4513 break;
4514 case GL_DEPTH_EXT:
4515 attachment = GL_DEPTH_ATTACHMENT;
4516 break;
4517 case GL_STENCIL_EXT:
4518 attachment = GL_STENCIL_ATTACHMENT;
4519 break;
4520 default:
4521 NOTREACHED();
4522 return;
4525 translated_attachments[i] = attachment;
4528 ScopedRenderTo do_render(framebuffer);
4529 if (feature_info_->gl_version_info().is_es3) {
4530 glInvalidateFramebuffer(
4531 target, numAttachments, translated_attachments.get());
4532 } else {
4533 glDiscardFramebufferEXT(
4534 target, numAttachments, translated_attachments.get());
4538 void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
4539 if (state_.vertex_attrib_manager->Enable(index, true)) {
4540 glEnableVertexAttribArray(index);
4541 } else {
4542 LOCAL_SET_GL_ERROR(
4543 GL_INVALID_VALUE, "glEnableVertexAttribArray", "index out of range");
4547 void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
4548 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
4549 &state_, target);
4550 if (!texture_ref ||
4551 !texture_manager()->CanGenerateMipmaps(texture_ref)) {
4552 LOCAL_SET_GL_ERROR(
4553 GL_INVALID_OPERATION, "glGenerateMipmap", "Can not generate mips");
4554 return;
4557 if (target == GL_TEXTURE_CUBE_MAP) {
4558 for (int i = 0; i < 6; ++i) {
4559 GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;
4560 if (!texture_manager()->ClearTextureLevel(this, texture_ref, face, 0)) {
4561 LOCAL_SET_GL_ERROR(
4562 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
4563 return;
4566 } else {
4567 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, 0)) {
4568 LOCAL_SET_GL_ERROR(
4569 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
4570 return;
4574 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glGenerateMipmap");
4575 // Workaround for Mac driver bug. In the large scheme of things setting
4576 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
4577 // hit so there's probably no need to make this conditional. The bug appears
4578 // to be that if the filtering mode is set to something that doesn't require
4579 // mipmaps for rendering, or is never set to something other than the default,
4580 // then glGenerateMipmap misbehaves.
4581 if (workarounds().set_texture_filter_before_generating_mipmap) {
4582 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
4584 glGenerateMipmapEXT(target);
4585 if (workarounds().set_texture_filter_before_generating_mipmap) {
4586 glTexParameteri(target, GL_TEXTURE_MIN_FILTER,
4587 texture_ref->texture()->min_filter());
4589 GLenum error = LOCAL_PEEK_GL_ERROR("glGenerateMipmap");
4590 if (error == GL_NO_ERROR) {
4591 texture_manager()->MarkMipmapsGenerated(texture_ref);
4595 bool GLES2DecoderImpl::GetHelper(
4596 GLenum pname, GLint* params, GLsizei* num_written) {
4597 DCHECK(num_written);
4598 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
4599 switch (pname) {
4600 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
4601 *num_written = 1;
4602 // Return the GL implementation's preferred format and (see below type)
4603 // if we have the GL extension that exposes this. This allows the GPU
4604 // client to use the implementation's preferred format for glReadPixels
4605 // for optimisation.
4607 // A conflicting extension (GL_ARB_ES2_compatibility) specifies an error
4608 // case when requested on integer/floating point buffers but which is
4609 // acceptable on GLES2 and with the GL_OES_read_format extension.
4611 // Therefore if an error occurs we swallow the error and use the
4612 // internal implementation.
4613 if (params) {
4614 if (context_->HasExtension("GL_OES_read_format")) {
4615 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper",
4616 GetErrorState());
4617 glGetIntegerv(pname, params);
4618 if (glGetError() == GL_NO_ERROR)
4619 return true;
4621 *params = GLES2Util::GetPreferredGLReadPixelsFormat(
4622 GetBoundReadFrameBufferInternalFormat());
4624 return true;
4625 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
4626 *num_written = 1;
4627 if (params) {
4628 if (context_->HasExtension("GL_OES_read_format")) {
4629 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper",
4630 GetErrorState());
4631 glGetIntegerv(pname, params);
4632 if (glGetError() == GL_NO_ERROR)
4633 return true;
4635 *params = GLES2Util::GetPreferredGLReadPixelsType(
4636 GetBoundReadFrameBufferInternalFormat(),
4637 GetBoundReadFrameBufferTextureType());
4639 return true;
4640 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
4641 *num_written = 1;
4642 if (params) {
4643 *params = group_->max_fragment_uniform_vectors();
4645 return true;
4646 case GL_MAX_VARYING_VECTORS:
4647 *num_written = 1;
4648 if (params) {
4649 *params = group_->max_varying_vectors();
4651 return true;
4652 case GL_MAX_VERTEX_UNIFORM_VECTORS:
4653 *num_written = 1;
4654 if (params) {
4655 *params = group_->max_vertex_uniform_vectors();
4657 return true;
4660 switch (pname) {
4661 case GL_MAX_VIEWPORT_DIMS:
4662 if (offscreen_target_frame_buffer_.get()) {
4663 *num_written = 2;
4664 if (params) {
4665 params[0] = renderbuffer_manager()->max_renderbuffer_size();
4666 params[1] = renderbuffer_manager()->max_renderbuffer_size();
4668 return true;
4670 return false;
4671 case GL_MAX_SAMPLES:
4672 *num_written = 1;
4673 if (params) {
4674 params[0] = renderbuffer_manager()->max_samples();
4676 return true;
4677 case GL_MAX_RENDERBUFFER_SIZE:
4678 *num_written = 1;
4679 if (params) {
4680 params[0] = renderbuffer_manager()->max_renderbuffer_size();
4682 return true;
4683 case GL_MAX_TEXTURE_SIZE:
4684 *num_written = 1;
4685 if (params) {
4686 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D);
4688 return true;
4689 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
4690 *num_written = 1;
4691 if (params) {
4692 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP);
4694 return true;
4695 case GL_MAX_COLOR_ATTACHMENTS_EXT:
4696 *num_written = 1;
4697 if (params) {
4698 params[0] = group_->max_color_attachments();
4700 return true;
4701 case GL_MAX_DRAW_BUFFERS_ARB:
4702 *num_written = 1;
4703 if (params) {
4704 params[0] = group_->max_draw_buffers();
4706 return true;
4707 case GL_ALPHA_BITS:
4708 *num_written = 1;
4709 if (params) {
4710 GLint v = 0;
4711 glGetIntegerv(GL_ALPHA_BITS, &v);
4712 params[0] = BoundFramebufferHasColorAttachmentWithAlpha(false) ? v : 0;
4714 return true;
4715 case GL_DEPTH_BITS:
4716 *num_written = 1;
4717 if (params) {
4718 GLint v = 0;
4719 glGetIntegerv(GL_DEPTH_BITS, &v);
4720 params[0] = BoundFramebufferHasDepthAttachment() ? v : 0;
4722 return true;
4723 case GL_STENCIL_BITS:
4724 *num_written = 1;
4725 if (params) {
4726 GLint v = 0;
4727 glGetIntegerv(GL_STENCIL_BITS, &v);
4728 params[0] = BoundFramebufferHasStencilAttachment() ? v : 0;
4730 return true;
4731 case GL_COMPRESSED_TEXTURE_FORMATS:
4732 *num_written = validators_->compressed_texture_format.GetValues().size();
4733 if (params) {
4734 for (GLint ii = 0; ii < *num_written; ++ii) {
4735 params[ii] = validators_->compressed_texture_format.GetValues()[ii];
4738 return true;
4739 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
4740 *num_written = 1;
4741 if (params) {
4742 *params = validators_->compressed_texture_format.GetValues().size();
4744 return true;
4745 case GL_NUM_SHADER_BINARY_FORMATS:
4746 *num_written = 1;
4747 if (params) {
4748 *params = validators_->shader_binary_format.GetValues().size();
4750 return true;
4751 case GL_SHADER_BINARY_FORMATS:
4752 *num_written = validators_->shader_binary_format.GetValues().size();
4753 if (params) {
4754 for (GLint ii = 0; ii < *num_written; ++ii) {
4755 params[ii] = validators_->shader_binary_format.GetValues()[ii];
4758 return true;
4759 case GL_SHADER_COMPILER:
4760 *num_written = 1;
4761 if (params) {
4762 *params = GL_TRUE;
4764 return true;
4765 case GL_ARRAY_BUFFER_BINDING:
4766 *num_written = 1;
4767 if (params) {
4768 if (state_.bound_array_buffer.get()) {
4769 GLuint client_id = 0;
4770 buffer_manager()->GetClientId(state_.bound_array_buffer->service_id(),
4771 &client_id);
4772 *params = client_id;
4773 } else {
4774 *params = 0;
4777 return true;
4778 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
4779 *num_written = 1;
4780 if (params) {
4781 if (state_.vertex_attrib_manager->element_array_buffer()) {
4782 GLuint client_id = 0;
4783 buffer_manager()->GetClientId(
4784 state_.vertex_attrib_manager->element_array_buffer()->
4785 service_id(), &client_id);
4786 *params = client_id;
4787 } else {
4788 *params = 0;
4791 return true;
4792 case GL_FRAMEBUFFER_BINDING:
4793 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
4794 *num_written = 1;
4795 if (params) {
4796 Framebuffer* framebuffer =
4797 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4798 if (framebuffer) {
4799 GLuint client_id = 0;
4800 framebuffer_manager()->GetClientId(
4801 framebuffer->service_id(), &client_id);
4802 *params = client_id;
4803 } else {
4804 *params = 0;
4807 return true;
4808 case GL_READ_FRAMEBUFFER_BINDING_EXT:
4809 *num_written = 1;
4810 if (params) {
4811 Framebuffer* framebuffer =
4812 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
4813 if (framebuffer) {
4814 GLuint client_id = 0;
4815 framebuffer_manager()->GetClientId(
4816 framebuffer->service_id(), &client_id);
4817 *params = client_id;
4818 } else {
4819 *params = 0;
4822 return true;
4823 case GL_RENDERBUFFER_BINDING:
4824 *num_written = 1;
4825 if (params) {
4826 Renderbuffer* renderbuffer =
4827 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4828 if (renderbuffer) {
4829 *params = renderbuffer->client_id();
4830 } else {
4831 *params = 0;
4834 return true;
4835 case GL_CURRENT_PROGRAM:
4836 *num_written = 1;
4837 if (params) {
4838 if (state_.current_program.get()) {
4839 GLuint client_id = 0;
4840 program_manager()->GetClientId(
4841 state_.current_program->service_id(), &client_id);
4842 *params = client_id;
4843 } else {
4844 *params = 0;
4847 return true;
4848 case GL_VERTEX_ARRAY_BINDING_OES:
4849 *num_written = 1;
4850 if (params) {
4851 if (state_.vertex_attrib_manager.get() !=
4852 state_.default_vertex_attrib_manager.get()) {
4853 GLuint client_id = 0;
4854 vertex_array_manager_->GetClientId(
4855 state_.vertex_attrib_manager->service_id(), &client_id);
4856 *params = client_id;
4857 } else {
4858 *params = 0;
4861 return true;
4862 case GL_TEXTURE_BINDING_2D:
4863 *num_written = 1;
4864 if (params) {
4865 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4866 if (unit.bound_texture_2d.get()) {
4867 *params = unit.bound_texture_2d->client_id();
4868 } else {
4869 *params = 0;
4872 return true;
4873 case GL_TEXTURE_BINDING_CUBE_MAP:
4874 *num_written = 1;
4875 if (params) {
4876 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4877 if (unit.bound_texture_cube_map.get()) {
4878 *params = unit.bound_texture_cube_map->client_id();
4879 } else {
4880 *params = 0;
4883 return true;
4884 case GL_TEXTURE_BINDING_EXTERNAL_OES:
4885 *num_written = 1;
4886 if (params) {
4887 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4888 if (unit.bound_texture_external_oes.get()) {
4889 *params = unit.bound_texture_external_oes->client_id();
4890 } else {
4891 *params = 0;
4894 return true;
4895 case GL_TEXTURE_BINDING_RECTANGLE_ARB:
4896 *num_written = 1;
4897 if (params) {
4898 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4899 if (unit.bound_texture_rectangle_arb.get()) {
4900 *params = unit.bound_texture_rectangle_arb->client_id();
4901 } else {
4902 *params = 0;
4905 return true;
4906 case GL_UNPACK_FLIP_Y_CHROMIUM:
4907 *num_written = 1;
4908 if (params) {
4909 params[0] = unpack_flip_y_;
4911 return true;
4912 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
4913 *num_written = 1;
4914 if (params) {
4915 params[0] = unpack_premultiply_alpha_;
4917 return true;
4918 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM:
4919 *num_written = 1;
4920 if (params) {
4921 params[0] = unpack_unpremultiply_alpha_;
4923 return true;
4924 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
4925 *num_written = 1;
4926 if (params) {
4927 params[0] = group_->bind_generates_resource() ? 1 : 0;
4929 return true;
4930 default:
4931 if (pname >= GL_DRAW_BUFFER0_ARB &&
4932 pname < GL_DRAW_BUFFER0_ARB + group_->max_draw_buffers()) {
4933 *num_written = 1;
4934 if (params) {
4935 Framebuffer* framebuffer =
4936 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4937 if (framebuffer) {
4938 params[0] = framebuffer->GetDrawBuffer(pname);
4939 } else { // backbuffer
4940 if (pname == GL_DRAW_BUFFER0_ARB)
4941 params[0] = group_->draw_buffer();
4942 else
4943 params[0] = GL_NONE;
4946 return true;
4948 *num_written = util_.GLGetNumValuesReturned(pname);
4949 return false;
4953 bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
4954 GLenum pname, GLsizei* num_values) {
4955 if (state_.GetStateAsGLint(pname, NULL, num_values)) {
4956 return true;
4958 return GetHelper(pname, NULL, num_values);
4961 GLenum GLES2DecoderImpl::AdjustGetPname(GLenum pname) {
4962 if (GL_MAX_SAMPLES == pname &&
4963 features().use_img_for_multisampled_render_to_texture) {
4964 return GL_MAX_SAMPLES_IMG;
4966 return pname;
4969 void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
4970 DCHECK(params);
4971 GLsizei num_written = 0;
4972 if (GetNumValuesReturnedForGLGet(pname, &num_written)) {
4973 scoped_ptr<GLint[]> values(new GLint[num_written]);
4974 if (!state_.GetStateAsGLint(pname, values.get(), &num_written)) {
4975 GetHelper(pname, values.get(), &num_written);
4977 for (GLsizei ii = 0; ii < num_written; ++ii) {
4978 params[ii] = static_cast<GLboolean>(values[ii]);
4980 } else {
4981 pname = AdjustGetPname(pname);
4982 glGetBooleanv(pname, params);
4986 void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
4987 DCHECK(params);
4988 GLsizei num_written = 0;
4989 if (!state_.GetStateAsGLfloat(pname, params, &num_written)) {
4990 if (GetHelper(pname, NULL, &num_written)) {
4991 scoped_ptr<GLint[]> values(new GLint[num_written]);
4992 GetHelper(pname, values.get(), &num_written);
4993 for (GLsizei ii = 0; ii < num_written; ++ii) {
4994 params[ii] = static_cast<GLfloat>(values[ii]);
4996 } else {
4997 pname = AdjustGetPname(pname);
4998 glGetFloatv(pname, params);
5003 void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
5004 DCHECK(params);
5005 GLsizei num_written;
5006 if (!state_.GetStateAsGLint(pname, params, &num_written) &&
5007 !GetHelper(pname, params, &num_written)) {
5008 pname = AdjustGetPname(pname);
5009 glGetIntegerv(pname, params);
5013 void GLES2DecoderImpl::DoGetProgramiv(
5014 GLuint program_id, GLenum pname, GLint* params) {
5015 Program* program = GetProgramInfoNotShader(program_id, "glGetProgramiv");
5016 if (!program) {
5017 return;
5019 program->GetProgramiv(pname, params);
5022 void GLES2DecoderImpl::DoGetBufferParameteriv(
5023 GLenum target, GLenum pname, GLint* params) {
5024 // Just delegate it. Some validation is actually done before this.
5025 buffer_manager()->ValidateAndDoGetBufferParameteriv(
5026 &state_, target, pname, params);
5029 void GLES2DecoderImpl::DoBindAttribLocation(
5030 GLuint program_id, GLuint index, const char* name) {
5031 if (!StringIsValidForGLES(name)) {
5032 LOCAL_SET_GL_ERROR(
5033 GL_INVALID_VALUE, "glBindAttribLocation", "Invalid character");
5034 return;
5036 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
5037 LOCAL_SET_GL_ERROR(
5038 GL_INVALID_OPERATION, "glBindAttribLocation", "reserved prefix");
5039 return;
5041 if (index >= group_->max_vertex_attribs()) {
5042 LOCAL_SET_GL_ERROR(
5043 GL_INVALID_VALUE, "glBindAttribLocation", "index out of range");
5044 return;
5046 Program* program = GetProgramInfoNotShader(
5047 program_id, "glBindAttribLocation");
5048 if (!program) {
5049 return;
5051 // At this point, the program's shaders may not be translated yet,
5052 // therefore, we may not find the hashed attribute name.
5053 // glBindAttribLocation call with original name is useless.
5054 // So instead, we should simply cache the binding, and then call
5055 // Program::ExecuteBindAttribLocationCalls() right before link.
5056 program->SetAttribLocationBinding(name, static_cast<GLint>(index));
5057 // TODO(zmo): Get rid of the following glBindAttribLocation call.
5058 glBindAttribLocation(program->service_id(), index, name);
5061 error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
5062 uint32 immediate_data_size,
5063 const void* cmd_data) {
5064 const gles2::cmds::BindAttribLocationBucket& c =
5065 *static_cast<const gles2::cmds::BindAttribLocationBucket*>(cmd_data);
5066 GLuint program = static_cast<GLuint>(c.program);
5067 GLuint index = static_cast<GLuint>(c.index);
5068 Bucket* bucket = GetBucket(c.name_bucket_id);
5069 if (!bucket || bucket->size() == 0) {
5070 return error::kInvalidArguments;
5072 std::string name_str;
5073 if (!bucket->GetAsString(&name_str)) {
5074 return error::kInvalidArguments;
5076 DoBindAttribLocation(program, index, name_str.c_str());
5077 return error::kNoError;
5080 void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM(
5081 GLuint program_id, GLint location, const char* name) {
5082 if (!StringIsValidForGLES(name)) {
5083 LOCAL_SET_GL_ERROR(
5084 GL_INVALID_VALUE,
5085 "glBindUniformLocationCHROMIUM", "Invalid character");
5086 return;
5088 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
5089 LOCAL_SET_GL_ERROR(
5090 GL_INVALID_OPERATION,
5091 "glBindUniformLocationCHROMIUM", "reserved prefix");
5092 return;
5094 if (location < 0 || static_cast<uint32>(location) >=
5095 (group_->max_fragment_uniform_vectors() +
5096 group_->max_vertex_uniform_vectors()) * 4) {
5097 LOCAL_SET_GL_ERROR(
5098 GL_INVALID_VALUE,
5099 "glBindUniformLocationCHROMIUM", "location out of range");
5100 return;
5102 Program* program = GetProgramInfoNotShader(
5103 program_id, "glBindUniformLocationCHROMIUM");
5104 if (!program) {
5105 return;
5107 if (!program->SetUniformLocationBinding(name, location)) {
5108 LOCAL_SET_GL_ERROR(
5109 GL_INVALID_VALUE,
5110 "glBindUniformLocationCHROMIUM", "location out of range");
5114 error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMBucket(
5115 uint32 immediate_data_size,
5116 const void* cmd_data) {
5117 const gles2::cmds::BindUniformLocationCHROMIUMBucket& c =
5118 *static_cast<const gles2::cmds::BindUniformLocationCHROMIUMBucket*>(
5119 cmd_data);
5120 GLuint program = static_cast<GLuint>(c.program);
5121 GLint location = static_cast<GLint>(c.location);
5122 Bucket* bucket = GetBucket(c.name_bucket_id);
5123 if (!bucket || bucket->size() == 0) {
5124 return error::kInvalidArguments;
5126 std::string name_str;
5127 if (!bucket->GetAsString(&name_str)) {
5128 return error::kInvalidArguments;
5130 DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
5131 return error::kNoError;
5134 error::Error GLES2DecoderImpl::HandleDeleteShader(uint32 immediate_data_size,
5135 const void* cmd_data) {
5136 const gles2::cmds::DeleteShader& c =
5137 *static_cast<const gles2::cmds::DeleteShader*>(cmd_data);
5138 GLuint client_id = c.shader;
5139 if (client_id) {
5140 Shader* shader = GetShader(client_id);
5141 if (shader) {
5142 if (!shader->IsDeleted()) {
5143 shader_manager()->Delete(shader);
5145 } else {
5146 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glDeleteShader", "unknown shader");
5149 return error::kNoError;
5152 error::Error GLES2DecoderImpl::HandleDeleteProgram(uint32 immediate_data_size,
5153 const void* cmd_data) {
5154 const gles2::cmds::DeleteProgram& c =
5155 *static_cast<const gles2::cmds::DeleteProgram*>(cmd_data);
5156 GLuint client_id = c.program;
5157 if (client_id) {
5158 Program* program = GetProgram(client_id);
5159 if (program) {
5160 if (!program->IsDeleted()) {
5161 program_manager()->MarkAsDeleted(shader_manager(), program);
5163 } else {
5164 LOCAL_SET_GL_ERROR(
5165 GL_INVALID_VALUE, "glDeleteProgram", "unknown program");
5168 return error::kNoError;
5171 error::Error GLES2DecoderImpl::DoClear(GLbitfield mask) {
5172 DCHECK(!ShouldDeferDraws());
5173 if (CheckBoundFramebuffersValid("glClear")) {
5174 ApplyDirtyState();
5175 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
5176 if (workarounds().gl_clear_broken) {
5177 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::ClearWorkaround",
5178 GetErrorState());
5179 if (!BoundFramebufferHasDepthAttachment())
5180 mask &= ~GL_DEPTH_BUFFER_BIT;
5181 if (!BoundFramebufferHasStencilAttachment())
5182 mask &= ~GL_STENCIL_BUFFER_BIT;
5183 clear_framebuffer_blit_->ClearFramebuffer(
5184 this, GetBoundReadFrameBufferSize(), mask, state_.color_clear_red,
5185 state_.color_clear_green, state_.color_clear_blue,
5186 state_.color_clear_alpha, state_.depth_clear, state_.stencil_clear);
5187 return error::kNoError;
5189 glClear(mask);
5191 return error::kNoError;
5194 void GLES2DecoderImpl::DoFramebufferRenderbuffer(
5195 GLenum target, GLenum attachment, GLenum renderbuffertarget,
5196 GLuint client_renderbuffer_id) {
5197 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5198 if (!framebuffer) {
5199 LOCAL_SET_GL_ERROR(
5200 GL_INVALID_OPERATION,
5201 "glFramebufferRenderbuffer", "no framebuffer bound");
5202 return;
5204 GLuint service_id = 0;
5205 Renderbuffer* renderbuffer = NULL;
5206 if (client_renderbuffer_id) {
5207 renderbuffer = GetRenderbuffer(client_renderbuffer_id);
5208 if (!renderbuffer) {
5209 LOCAL_SET_GL_ERROR(
5210 GL_INVALID_OPERATION,
5211 "glFramebufferRenderbuffer", "unknown renderbuffer");
5212 return;
5214 service_id = renderbuffer->service_id();
5216 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glFramebufferRenderbuffer");
5217 glFramebufferRenderbufferEXT(
5218 target, attachment, renderbuffertarget, service_id);
5219 GLenum error = LOCAL_PEEK_GL_ERROR("glFramebufferRenderbuffer");
5220 if (error == GL_NO_ERROR) {
5221 framebuffer->AttachRenderbuffer(attachment, renderbuffer);
5223 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
5224 framebuffer_state_.clear_state_dirty = true;
5226 OnFboChanged();
5229 void GLES2DecoderImpl::DoDisable(GLenum cap) {
5230 if (SetCapabilityState(cap, false)) {
5231 glDisable(cap);
5235 void GLES2DecoderImpl::DoEnable(GLenum cap) {
5236 if (SetCapabilityState(cap, true)) {
5237 glEnable(cap);
5241 void GLES2DecoderImpl::DoDepthRangef(GLclampf znear, GLclampf zfar) {
5242 state_.z_near = std::min(1.0f, std::max(0.0f, znear));
5243 state_.z_far = std::min(1.0f, std::max(0.0f, zfar));
5244 glDepthRange(znear, zfar);
5247 void GLES2DecoderImpl::DoSampleCoverage(GLclampf value, GLboolean invert) {
5248 state_.sample_coverage_value = std::min(1.0f, std::max(0.0f, value));
5249 state_.sample_coverage_invert = (invert != 0);
5250 glSampleCoverage(state_.sample_coverage_value, invert);
5253 // Assumes framebuffer is complete.
5254 void GLES2DecoderImpl::ClearUnclearedAttachments(
5255 GLenum target, Framebuffer* framebuffer) {
5256 if (target == GL_READ_FRAMEBUFFER_EXT) {
5257 // bind this to the DRAW point, clear then bind back to READ
5258 // TODO(gman): I don't think there is any guarantee that an FBO that
5259 // is complete on the READ attachment will be complete as a DRAW
5260 // attachment.
5261 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
5262 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, framebuffer->service_id());
5264 GLbitfield clear_bits = 0;
5265 if (framebuffer->HasUnclearedColorAttachments()) {
5266 glClearColor(
5267 0.0f, 0.0f, 0.0f,
5268 (GLES2Util::GetChannelsForFormat(
5269 framebuffer->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0.0f :
5270 1.0f);
5271 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
5272 clear_bits |= GL_COLOR_BUFFER_BIT;
5273 if (feature_info_->feature_flags().ext_draw_buffers)
5274 framebuffer->PrepareDrawBuffersForClear();
5277 if (framebuffer->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) ||
5278 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
5279 glClearStencil(0);
5280 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
5281 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
5282 clear_bits |= GL_STENCIL_BUFFER_BIT;
5285 if (framebuffer->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
5286 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
5287 glClearDepth(1.0f);
5288 state_.SetDeviceDepthMask(GL_TRUE);
5289 clear_bits |= GL_DEPTH_BUFFER_BIT;
5292 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
5293 glClear(clear_bits);
5295 if ((clear_bits & GL_COLOR_BUFFER_BIT) != 0 &&
5296 feature_info_->feature_flags().ext_draw_buffers)
5297 framebuffer->RestoreDrawBuffersAfterClear();
5299 framebuffer_manager()->MarkAttachmentsAsCleared(
5300 framebuffer, renderbuffer_manager(), texture_manager());
5302 RestoreClearState();
5304 if (target == GL_READ_FRAMEBUFFER_EXT) {
5305 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, framebuffer->service_id());
5306 Framebuffer* draw_framebuffer =
5307 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
5308 GLuint service_id = draw_framebuffer ? draw_framebuffer->service_id() :
5309 GetBackbufferServiceId();
5310 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, service_id);
5314 void GLES2DecoderImpl::RestoreClearState() {
5315 framebuffer_state_.clear_state_dirty = true;
5316 glClearColor(
5317 state_.color_clear_red, state_.color_clear_green, state_.color_clear_blue,
5318 state_.color_clear_alpha);
5319 glClearStencil(state_.stencil_clear);
5320 glClearDepth(state_.depth_clear);
5321 if (state_.enable_flags.scissor_test) {
5322 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
5326 GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
5327 Framebuffer* framebuffer =
5328 GetFramebufferInfoForTarget(target);
5329 if (!framebuffer) {
5330 return GL_FRAMEBUFFER_COMPLETE;
5332 GLenum completeness = framebuffer->IsPossiblyComplete();
5333 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
5334 return completeness;
5336 return framebuffer->GetStatus(texture_manager(), target);
5339 void GLES2DecoderImpl::DoFramebufferTexture2D(
5340 GLenum target, GLenum attachment, GLenum textarget,
5341 GLuint client_texture_id, GLint level) {
5342 DoFramebufferTexture2DCommon(
5343 "glFramebufferTexture2D", target, attachment,
5344 textarget, client_texture_id, level, 0);
5347 void GLES2DecoderImpl::DoFramebufferTexture2DMultisample(
5348 GLenum target, GLenum attachment, GLenum textarget,
5349 GLuint client_texture_id, GLint level, GLsizei samples) {
5350 DoFramebufferTexture2DCommon(
5351 "glFramebufferTexture2DMultisample", target, attachment,
5352 textarget, client_texture_id, level, samples);
5355 void GLES2DecoderImpl::DoFramebufferTexture2DCommon(
5356 const char* name, GLenum target, GLenum attachment, GLenum textarget,
5357 GLuint client_texture_id, GLint level, GLsizei samples) {
5358 if (samples > renderbuffer_manager()->max_samples()) {
5359 LOCAL_SET_GL_ERROR(
5360 GL_INVALID_VALUE,
5361 "glFramebufferTexture2DMultisample", "samples too large");
5362 return;
5364 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5365 if (!framebuffer) {
5366 LOCAL_SET_GL_ERROR(
5367 GL_INVALID_OPERATION,
5368 name, "no framebuffer bound.");
5369 return;
5371 GLuint service_id = 0;
5372 TextureRef* texture_ref = NULL;
5373 if (client_texture_id) {
5374 texture_ref = GetTexture(client_texture_id);
5375 if (!texture_ref) {
5376 LOCAL_SET_GL_ERROR(
5377 GL_INVALID_OPERATION,
5378 name, "unknown texture_ref");
5379 return;
5381 service_id = texture_ref->service_id();
5384 if (!texture_manager()->ValidForTarget(textarget, level, 0, 0, 1)) {
5385 LOCAL_SET_GL_ERROR(
5386 GL_INVALID_VALUE,
5387 name, "level out of range");
5388 return;
5391 if (texture_ref)
5392 DoWillUseTexImageIfNeeded(texture_ref->texture(), textarget);
5394 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(name);
5395 if (0 == samples) {
5396 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
5397 } else {
5398 if (features().use_img_for_multisampled_render_to_texture) {
5399 glFramebufferTexture2DMultisampleIMG(target, attachment, textarget,
5400 service_id, level, samples);
5401 } else {
5402 glFramebufferTexture2DMultisampleEXT(target, attachment, textarget,
5403 service_id, level, samples);
5406 GLenum error = LOCAL_PEEK_GL_ERROR(name);
5407 if (error == GL_NO_ERROR) {
5408 framebuffer->AttachTexture(attachment, texture_ref, textarget, level,
5409 samples);
5411 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
5412 framebuffer_state_.clear_state_dirty = true;
5415 if (texture_ref)
5416 DoDidUseTexImageIfNeeded(texture_ref->texture(), textarget);
5418 OnFboChanged();
5421 void GLES2DecoderImpl::DoFramebufferTextureLayer(
5422 GLenum target, GLenum attachment, GLuint client_texture_id,
5423 GLint level, GLint layer) {
5424 // TODO(zmo): Unsafe ES3 API, missing states update.
5425 GLuint service_id = 0;
5426 TextureRef* texture_ref = NULL;
5427 if (client_texture_id) {
5428 texture_ref = GetTexture(client_texture_id);
5429 if (!texture_ref) {
5430 LOCAL_SET_GL_ERROR(
5431 GL_INVALID_OPERATION,
5432 "glFramebufferTextureLayer", "unknown texture_ref");
5433 return;
5435 service_id = texture_ref->service_id();
5437 glFramebufferTextureLayer(target, attachment, service_id, level, layer);
5440 void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
5441 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
5442 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5443 if (!framebuffer) {
5444 LOCAL_SET_GL_ERROR(
5445 GL_INVALID_OPERATION,
5446 "glGetFramebufferAttachmentParameteriv", "no framebuffer bound");
5447 return;
5449 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
5450 const Framebuffer::Attachment* attachment_object =
5451 framebuffer->GetAttachment(attachment);
5452 *params = attachment_object ? attachment_object->object_name() : 0;
5453 } else {
5454 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT &&
5455 features().use_img_for_multisampled_render_to_texture) {
5456 pname = GL_TEXTURE_SAMPLES_IMG;
5458 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
5462 void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
5463 GLenum target, GLenum pname, GLint* params) {
5464 Renderbuffer* renderbuffer =
5465 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5466 if (!renderbuffer) {
5467 LOCAL_SET_GL_ERROR(
5468 GL_INVALID_OPERATION,
5469 "glGetRenderbufferParameteriv", "no renderbuffer bound");
5470 return;
5473 EnsureRenderbufferBound();
5474 switch (pname) {
5475 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5476 *params = renderbuffer->internal_format();
5477 break;
5478 case GL_RENDERBUFFER_WIDTH:
5479 *params = renderbuffer->width();
5480 break;
5481 case GL_RENDERBUFFER_HEIGHT:
5482 *params = renderbuffer->height();
5483 break;
5484 case GL_RENDERBUFFER_SAMPLES_EXT:
5485 if (features().use_img_for_multisampled_render_to_texture) {
5486 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_IMG,
5487 params);
5488 } else {
5489 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_EXT,
5490 params);
5492 default:
5493 glGetRenderbufferParameterivEXT(target, pname, params);
5494 break;
5498 void GLES2DecoderImpl::DoBlitFramebufferCHROMIUM(
5499 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
5500 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
5501 GLbitfield mask, GLenum filter) {
5502 DCHECK(!ShouldDeferReads() && !ShouldDeferDraws());
5504 if (!CheckBoundFramebuffersValid("glBlitFramebufferCHROMIUM")) {
5505 return;
5508 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
5509 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
5510 BlitFramebufferHelper(
5511 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5512 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST,
5513 state_.enable_flags.scissor_test);
5516 void GLES2DecoderImpl::EnsureRenderbufferBound() {
5517 if (!state_.bound_renderbuffer_valid) {
5518 state_.bound_renderbuffer_valid = true;
5519 glBindRenderbufferEXT(GL_RENDERBUFFER,
5520 state_.bound_renderbuffer.get()
5521 ? state_.bound_renderbuffer->service_id()
5522 : 0);
5526 void GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(
5527 const FeatureInfo* feature_info,
5528 GLenum target,
5529 GLsizei samples,
5530 GLenum internal_format,
5531 GLsizei width,
5532 GLsizei height) {
5533 // TODO(sievers): This could be resolved at the GL binding level, but the
5534 // binding process is currently a bit too 'brute force'.
5535 if (feature_info->gl_version_info().is_angle) {
5536 glRenderbufferStorageMultisampleANGLE(
5537 target, samples, internal_format, width, height);
5538 } else if (feature_info->feature_flags().use_core_framebuffer_multisample) {
5539 glRenderbufferStorageMultisample(
5540 target, samples, internal_format, width, height);
5541 } else {
5542 glRenderbufferStorageMultisampleEXT(
5543 target, samples, internal_format, width, height);
5547 void GLES2DecoderImpl::BlitFramebufferHelper(GLint srcX0,
5548 GLint srcY0,
5549 GLint srcX1,
5550 GLint srcY1,
5551 GLint dstX0,
5552 GLint dstY0,
5553 GLint dstX1,
5554 GLint dstY1,
5555 GLbitfield mask,
5556 GLenum filter) {
5557 // TODO(sievers): This could be resolved at the GL binding level, but the
5558 // binding process is currently a bit too 'brute force'.
5559 if (feature_info_->gl_version_info().is_angle) {
5560 glBlitFramebufferANGLE(
5561 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5562 } else if (feature_info_->feature_flags().use_core_framebuffer_multisample) {
5563 glBlitFramebuffer(
5564 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5565 } else {
5566 glBlitFramebufferEXT(
5567 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5571 bool GLES2DecoderImpl::ValidateRenderbufferStorageMultisample(
5572 GLsizei samples,
5573 GLenum internalformat,
5574 GLsizei width,
5575 GLsizei height) {
5576 if (samples > renderbuffer_manager()->max_samples()) {
5577 LOCAL_SET_GL_ERROR(
5578 GL_INVALID_VALUE,
5579 "glRenderbufferStorageMultisample", "samples too large");
5580 return false;
5583 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
5584 height > renderbuffer_manager()->max_renderbuffer_size()) {
5585 LOCAL_SET_GL_ERROR(
5586 GL_INVALID_VALUE,
5587 "glRenderbufferStorageMultisample", "dimensions too large");
5588 return false;
5591 uint32 estimated_size = 0;
5592 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
5593 width, height, samples, internalformat, &estimated_size)) {
5594 LOCAL_SET_GL_ERROR(
5595 GL_OUT_OF_MEMORY,
5596 "glRenderbufferStorageMultisample", "dimensions too large");
5597 return false;
5600 if (!EnsureGPUMemoryAvailable(estimated_size)) {
5601 LOCAL_SET_GL_ERROR(
5602 GL_OUT_OF_MEMORY,
5603 "glRenderbufferStorageMultisample", "out of memory");
5604 return false;
5607 return true;
5610 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleCHROMIUM(
5611 GLenum target, GLsizei samples, GLenum internalformat,
5612 GLsizei width, GLsizei height) {
5613 Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5614 if (!renderbuffer) {
5615 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
5616 "glRenderbufferStorageMultisampleCHROMIUM",
5617 "no renderbuffer bound");
5618 return;
5621 if (!ValidateRenderbufferStorageMultisample(
5622 samples, internalformat, width, height)) {
5623 return;
5626 EnsureRenderbufferBound();
5627 GLenum impl_format =
5628 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5629 internalformat);
5630 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(
5631 "glRenderbufferStorageMultisampleCHROMIUM");
5632 RenderbufferStorageMultisampleHelper(
5633 feature_info_.get(), target, samples, impl_format, width, height);
5634 GLenum error =
5635 LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleCHROMIUM");
5636 if (error == GL_NO_ERROR) {
5638 if (workarounds().validate_multisample_buffer_allocation) {
5639 if (!VerifyMultisampleRenderbufferIntegrity(
5640 renderbuffer->service_id(), impl_format)) {
5641 LOCAL_SET_GL_ERROR(
5642 GL_OUT_OF_MEMORY,
5643 "glRenderbufferStorageMultisampleCHROMIUM", "out of memory");
5644 return;
5648 // TODO(gman): If renderbuffers tracked which framebuffers they were
5649 // attached to we could just mark those framebuffers as not complete.
5650 framebuffer_manager()->IncFramebufferStateChangeCount();
5651 renderbuffer_manager()->SetInfo(
5652 renderbuffer, samples, internalformat, width, height);
5656 // This is the handler for multisampled_render_to_texture extensions.
5657 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleEXT(
5658 GLenum target, GLsizei samples, GLenum internalformat,
5659 GLsizei width, GLsizei height) {
5660 Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5661 if (!renderbuffer) {
5662 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
5663 "glRenderbufferStorageMultisampleEXT",
5664 "no renderbuffer bound");
5665 return;
5668 if (!ValidateRenderbufferStorageMultisample(
5669 samples, internalformat, width, height)) {
5670 return;
5673 EnsureRenderbufferBound();
5674 GLenum impl_format =
5675 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5676 internalformat);
5677 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorageMultisampleEXT");
5678 if (features().use_img_for_multisampled_render_to_texture) {
5679 glRenderbufferStorageMultisampleIMG(
5680 target, samples, impl_format, width, height);
5681 } else {
5682 glRenderbufferStorageMultisampleEXT(
5683 target, samples, impl_format, width, height);
5685 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleEXT");
5686 if (error == GL_NO_ERROR) {
5687 // TODO(gman): If renderbuffers tracked which framebuffers they were
5688 // attached to we could just mark those framebuffers as not complete.
5689 framebuffer_manager()->IncFramebufferStateChangeCount();
5690 renderbuffer_manager()->SetInfo(
5691 renderbuffer, samples, internalformat, width, height);
5695 // This function validates the allocation of a multisampled renderbuffer
5696 // by clearing it to a key color, blitting the contents to a texture, and
5697 // reading back the color to ensure it matches the key.
5698 bool GLES2DecoderImpl::VerifyMultisampleRenderbufferIntegrity(
5699 GLuint renderbuffer, GLenum format) {
5701 // Only validate color buffers.
5702 // These formats have been selected because they are very common or are known
5703 // to be used by the WebGL backbuffer. If problems are observed with other
5704 // color formats they can be added here.
5705 switch(format) {
5706 case GL_RGB:
5707 case GL_RGB8:
5708 case GL_RGBA:
5709 case GL_RGBA8:
5710 break;
5711 default:
5712 return true;
5715 GLint draw_framebuffer, read_framebuffer;
5717 // Cache framebuffer and texture bindings.
5718 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &draw_framebuffer);
5719 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &read_framebuffer);
5721 if (!validation_texture_) {
5722 GLint bound_texture;
5723 glGetIntegerv(GL_TEXTURE_BINDING_2D, &bound_texture);
5725 // Create additional resources needed for the verification.
5726 glGenTextures(1, &validation_texture_);
5727 glGenFramebuffersEXT(1, &validation_fbo_multisample_);
5728 glGenFramebuffersEXT(1, &validation_fbo_);
5730 // Texture only needs to be 1x1.
5731 glBindTexture(GL_TEXTURE_2D, validation_texture_);
5732 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB,
5733 GL_UNSIGNED_BYTE, NULL);
5735 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
5736 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5737 GL_TEXTURE_2D, validation_texture_, 0);
5739 glBindTexture(GL_TEXTURE_2D, bound_texture);
5742 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
5743 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5744 GL_RENDERBUFFER, renderbuffer);
5746 // Cache current state and reset it to the values we require.
5747 GLboolean scissor_enabled = false;
5748 glGetBooleanv(GL_SCISSOR_TEST, &scissor_enabled);
5749 if (scissor_enabled)
5750 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
5752 GLboolean color_mask[4] = {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE};
5753 glGetBooleanv(GL_COLOR_WRITEMASK, color_mask);
5754 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
5756 GLfloat clear_color[4] = {0.0f, 0.0f, 0.0f, 0.0f};
5757 glGetFloatv(GL_COLOR_CLEAR_VALUE, clear_color);
5758 glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
5760 // Clear the buffer to the desired key color.
5761 glClear(GL_COLOR_BUFFER_BIT);
5763 // Blit from the multisample buffer to a standard texture.
5764 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, validation_fbo_multisample_);
5765 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, validation_fbo_);
5767 BlitFramebufferHelper(
5768 0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
5770 // Read a pixel from the buffer.
5771 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
5773 unsigned char pixel[3] = {0, 0, 0};
5774 glReadPixels(0, 0, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &pixel);
5776 // Detach the renderbuffer.
5777 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
5778 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5779 GL_RENDERBUFFER, 0);
5781 // Restore cached state.
5782 if (scissor_enabled)
5783 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
5785 state_.SetDeviceColorMask(
5786 color_mask[0], color_mask[1], color_mask[2], color_mask[3]);
5787 glClearColor(clear_color[0], clear_color[1], clear_color[2], clear_color[3]);
5788 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, draw_framebuffer);
5789 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, read_framebuffer);
5791 // Return true if the pixel matched the desired key color.
5792 return (pixel[0] == 0xFF &&
5793 pixel[1] == 0x00 &&
5794 pixel[2] == 0xFF);
5797 void GLES2DecoderImpl::DoRenderbufferStorage(
5798 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
5799 Renderbuffer* renderbuffer =
5800 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5801 if (!renderbuffer) {
5802 LOCAL_SET_GL_ERROR(
5803 GL_INVALID_OPERATION,
5804 "glRenderbufferStorage", "no renderbuffer bound");
5805 return;
5808 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
5809 height > renderbuffer_manager()->max_renderbuffer_size()) {
5810 LOCAL_SET_GL_ERROR(
5811 GL_INVALID_VALUE, "glRenderbufferStorage", "dimensions too large");
5812 return;
5815 uint32 estimated_size = 0;
5816 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
5817 width, height, 1, internalformat, &estimated_size)) {
5818 LOCAL_SET_GL_ERROR(
5819 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "dimensions too large");
5820 return;
5823 if (!EnsureGPUMemoryAvailable(estimated_size)) {
5824 LOCAL_SET_GL_ERROR(
5825 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "out of memory");
5826 return;
5829 EnsureRenderbufferBound();
5830 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorage");
5831 glRenderbufferStorageEXT(
5832 target,
5833 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5834 internalformat),
5835 width,
5836 height);
5837 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorage");
5838 if (error == GL_NO_ERROR) {
5839 // TODO(gman): If tetxures tracked which framebuffers they were attached to
5840 // we could just mark those framebuffers as not complete.
5841 framebuffer_manager()->IncFramebufferStateChangeCount();
5842 renderbuffer_manager()->SetInfo(
5843 renderbuffer, 1, internalformat, width, height);
5847 void GLES2DecoderImpl::DoLinkProgram(GLuint program_id) {
5848 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
5849 Program* program = GetProgramInfoNotShader(
5850 program_id, "glLinkProgram");
5851 if (!program) {
5852 return;
5855 LogClientServiceForInfo(program, program_id, "glLinkProgram");
5856 if (program->Link(shader_manager(),
5857 workarounds().count_all_in_varyings_packing ?
5858 Program::kCountAll : Program::kCountOnlyStaticallyUsed,
5859 shader_cache_callback_)) {
5860 if (program == state_.current_program.get()) {
5861 if (workarounds().use_current_program_after_successful_link)
5862 glUseProgram(program->service_id());
5863 if (workarounds().clear_uniforms_before_first_program_use)
5864 program_manager()->ClearUniforms(program);
5868 // LinkProgram can be very slow. Exit command processing to allow for
5869 // context preemption and GPU watchdog checks.
5870 ExitCommandProcessingEarly();
5873 void GLES2DecoderImpl::DoSamplerParameterfv(
5874 GLuint sampler, GLenum pname, const GLfloat* params) {
5875 DCHECK(params);
5876 glSamplerParameterf(sampler, pname, params[0]);
5879 void GLES2DecoderImpl::DoSamplerParameteriv(
5880 GLuint sampler, GLenum pname, const GLint* params) {
5881 DCHECK(params);
5882 glSamplerParameteri(sampler, pname, params[0]);
5885 void GLES2DecoderImpl::DoTexParameterf(
5886 GLenum target, GLenum pname, GLfloat param) {
5887 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5888 &state_, target);
5889 if (!texture) {
5890 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterf", "unknown texture");
5891 return;
5894 texture_manager()->SetParameterf(
5895 "glTexParameterf", GetErrorState(), texture, pname, param);
5898 void GLES2DecoderImpl::DoTexParameteri(
5899 GLenum target, GLenum pname, GLint param) {
5900 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5901 &state_, target);
5902 if (!texture) {
5903 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameteri", "unknown texture");
5904 return;
5907 texture_manager()->SetParameteri(
5908 "glTexParameteri", GetErrorState(), texture, pname, param);
5911 void GLES2DecoderImpl::DoTexParameterfv(
5912 GLenum target, GLenum pname, const GLfloat* params) {
5913 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5914 &state_, target);
5915 if (!texture) {
5916 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterfv", "unknown texture");
5917 return;
5920 texture_manager()->SetParameterf(
5921 "glTexParameterfv", GetErrorState(), texture, pname, *params);
5924 void GLES2DecoderImpl::DoTexParameteriv(
5925 GLenum target, GLenum pname, const GLint* params) {
5926 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5927 &state_, target);
5928 if (!texture) {
5929 LOCAL_SET_GL_ERROR(
5930 GL_INVALID_VALUE, "glTexParameteriv", "unknown texture");
5931 return;
5934 texture_manager()->SetParameteri(
5935 "glTexParameteriv", GetErrorState(), texture, pname, *params);
5938 bool GLES2DecoderImpl::CheckCurrentValuebuffer(const char* function_name) {
5939 if (!state_.bound_valuebuffer.get()) {
5940 // There is no valuebuffer bound
5941 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
5942 "no valuebuffer in use");
5943 return false;
5945 return true;
5948 bool GLES2DecoderImpl::CheckCurrentValuebufferForSubscription(
5949 GLenum subscription,
5950 const char* function_name) {
5951 if (!CheckCurrentValuebuffer(function_name)) {
5952 return false;
5954 if (!state_.bound_valuebuffer.get()->IsSubscribed(subscription)) {
5955 // The valuebuffer is not subscribed to the target
5956 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
5957 "valuebuffer is not subscribed");
5958 return false;
5960 return true;
5963 bool GLES2DecoderImpl::CheckSubscriptionTarget(GLint location,
5964 GLenum subscription,
5965 const char* function_name) {
5966 if (!CheckCurrentProgramForUniform(location, function_name)) {
5967 return false;
5969 GLint real_location = -1;
5970 GLint array_index = -1;
5971 const Program::UniformInfo* info =
5972 state_.current_program->GetUniformInfoByFakeLocation(
5973 location, &real_location, &array_index);
5974 if (!info) {
5975 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, "unknown location");
5976 return false;
5978 if ((ValuebufferManager::ApiTypeForSubscriptionTarget(subscription) &
5979 info->accepts_api_type) == 0) {
5980 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
5981 "wrong type for subscription");
5982 return false;
5984 return true;
5987 bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
5988 if (!state_.current_program.get()) {
5989 // The program does not exist.
5990 LOCAL_SET_GL_ERROR(
5991 GL_INVALID_OPERATION, function_name, "no program in use");
5992 return false;
5994 if (!state_.current_program->InUse()) {
5995 LOCAL_SET_GL_ERROR(
5996 GL_INVALID_OPERATION, function_name, "program not linked");
5997 return false;
5999 return true;
6002 bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
6003 GLint location, const char* function_name) {
6004 if (!CheckCurrentProgram(function_name)) {
6005 return false;
6007 return location != -1;
6010 bool GLES2DecoderImpl::CheckDrawingFeedbackLoops() {
6011 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
6012 if (!framebuffer)
6013 return false;
6014 const Framebuffer::Attachment* attachment =
6015 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
6016 if (!attachment)
6017 return false;
6019 DCHECK(state_.current_program.get());
6020 const Program::SamplerIndices& sampler_indices =
6021 state_.current_program->sampler_indices();
6022 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6023 const Program::UniformInfo* uniform_info =
6024 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6025 DCHECK(uniform_info);
6026 if (uniform_info->type != GL_SAMPLER_2D)
6027 continue;
6028 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6029 GLuint texture_unit_index = uniform_info->texture_units[jj];
6030 if (texture_unit_index >= state_.texture_units.size())
6031 continue;
6032 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6033 TextureRef* texture_ref =
6034 texture_unit.GetInfoForSamplerType(GL_SAMPLER_2D).get();
6035 if (attachment->IsTexture(texture_ref))
6036 return true;
6039 return false;
6042 bool GLES2DecoderImpl::CheckUniformForApiType(
6043 const Program::UniformInfo* info,
6044 const char* function_name,
6045 Program::UniformApiType api_type) {
6046 DCHECK(info);
6047 if ((api_type & info->accepts_api_type) == 0) {
6048 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
6049 "wrong uniform function for type");
6050 return false;
6052 return true;
6055 bool GLES2DecoderImpl::PrepForSetUniformByLocation(
6056 GLint fake_location,
6057 const char* function_name,
6058 Program::UniformApiType api_type,
6059 GLint* real_location,
6060 GLenum* type,
6061 GLsizei* count) {
6062 DCHECK(type);
6063 DCHECK(count);
6064 DCHECK(real_location);
6066 if (!CheckCurrentProgramForUniform(fake_location, function_name)) {
6067 return false;
6069 GLint array_index = -1;
6070 const Program::UniformInfo* info =
6071 state_.current_program->GetUniformInfoByFakeLocation(
6072 fake_location, real_location, &array_index);
6073 if (!info) {
6074 LOCAL_SET_GL_ERROR(
6075 GL_INVALID_OPERATION, function_name, "unknown location");
6076 return false;
6078 if (!CheckUniformForApiType(info, function_name, api_type)) {
6079 return false;
6081 if (*count > 1 && !info->is_array) {
6082 LOCAL_SET_GL_ERROR(
6083 GL_INVALID_OPERATION, function_name, "count > 1 for non-array");
6084 return false;
6086 *count = std::min(info->size - array_index, *count);
6087 if (*count <= 0) {
6088 return false;
6090 *type = info->type;
6091 return true;
6094 void GLES2DecoderImpl::DoUniform1i(GLint fake_location, GLint v0) {
6095 GLenum type = 0;
6096 GLsizei count = 1;
6097 GLint real_location = -1;
6098 if (!PrepForSetUniformByLocation(fake_location,
6099 "glUniform1i",
6100 Program::kUniform1i,
6101 &real_location,
6102 &type,
6103 &count)) {
6104 return;
6106 if (!state_.current_program->SetSamplers(
6107 state_.texture_units.size(), fake_location, 1, &v0)) {
6108 LOCAL_SET_GL_ERROR(
6109 GL_INVALID_VALUE, "glUniform1i", "texture unit out of range");
6110 return;
6112 glUniform1i(real_location, v0);
6115 void GLES2DecoderImpl::DoUniform1iv(
6116 GLint fake_location, GLsizei count, const GLint *value) {
6117 GLenum type = 0;
6118 GLint real_location = -1;
6119 if (!PrepForSetUniformByLocation(fake_location,
6120 "glUniform1iv",
6121 Program::kUniform1i,
6122 &real_location,
6123 &type,
6124 &count)) {
6125 return;
6127 if (type == GL_SAMPLER_2D || type == GL_SAMPLER_2D_RECT_ARB ||
6128 type == GL_SAMPLER_CUBE || type == GL_SAMPLER_EXTERNAL_OES) {
6129 if (!state_.current_program->SetSamplers(
6130 state_.texture_units.size(), fake_location, count, value)) {
6131 LOCAL_SET_GL_ERROR(
6132 GL_INVALID_VALUE, "glUniform1iv", "texture unit out of range");
6133 return;
6136 glUniform1iv(real_location, count, value);
6139 void GLES2DecoderImpl::DoUniform1fv(
6140 GLint fake_location, GLsizei count, const GLfloat* value) {
6141 GLenum type = 0;
6142 GLint real_location = -1;
6143 if (!PrepForSetUniformByLocation(fake_location,
6144 "glUniform1fv",
6145 Program::kUniform1f,
6146 &real_location,
6147 &type,
6148 &count)) {
6149 return;
6151 if (type == GL_BOOL) {
6152 scoped_ptr<GLint[]> temp(new GLint[count]);
6153 for (GLsizei ii = 0; ii < count; ++ii) {
6154 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6156 DoUniform1iv(real_location, count, temp.get());
6157 } else {
6158 glUniform1fv(real_location, count, value);
6162 void GLES2DecoderImpl::DoUniform2fv(
6163 GLint fake_location, GLsizei count, const GLfloat* value) {
6164 GLenum type = 0;
6165 GLint real_location = -1;
6166 if (!PrepForSetUniformByLocation(fake_location,
6167 "glUniform2fv",
6168 Program::kUniform2f,
6169 &real_location,
6170 &type,
6171 &count)) {
6172 return;
6174 if (type == GL_BOOL_VEC2) {
6175 GLsizei num_values = count * 2;
6176 scoped_ptr<GLint[]> temp(new GLint[num_values]);
6177 for (GLsizei ii = 0; ii < num_values; ++ii) {
6178 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6180 glUniform2iv(real_location, count, temp.get());
6181 } else {
6182 glUniform2fv(real_location, count, value);
6186 void GLES2DecoderImpl::DoUniform3fv(
6187 GLint fake_location, GLsizei count, const GLfloat* value) {
6188 GLenum type = 0;
6189 GLint real_location = -1;
6190 if (!PrepForSetUniformByLocation(fake_location,
6191 "glUniform3fv",
6192 Program::kUniform3f,
6193 &real_location,
6194 &type,
6195 &count)) {
6196 return;
6198 if (type == GL_BOOL_VEC3) {
6199 GLsizei num_values = count * 3;
6200 scoped_ptr<GLint[]> temp(new GLint[num_values]);
6201 for (GLsizei ii = 0; ii < num_values; ++ii) {
6202 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6204 glUniform3iv(real_location, count, temp.get());
6205 } else {
6206 glUniform3fv(real_location, count, value);
6210 void GLES2DecoderImpl::DoUniform4fv(
6211 GLint fake_location, GLsizei count, const GLfloat* value) {
6212 GLenum type = 0;
6213 GLint real_location = -1;
6214 if (!PrepForSetUniformByLocation(fake_location,
6215 "glUniform4fv",
6216 Program::kUniform4f,
6217 &real_location,
6218 &type,
6219 &count)) {
6220 return;
6222 if (type == GL_BOOL_VEC4) {
6223 GLsizei num_values = count * 4;
6224 scoped_ptr<GLint[]> temp(new GLint[num_values]);
6225 for (GLsizei ii = 0; ii < num_values; ++ii) {
6226 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6228 glUniform4iv(real_location, count, temp.get());
6229 } else {
6230 glUniform4fv(real_location, count, value);
6234 void GLES2DecoderImpl::DoUniform2iv(
6235 GLint fake_location, GLsizei count, const GLint* value) {
6236 GLenum type = 0;
6237 GLint real_location = -1;
6238 if (!PrepForSetUniformByLocation(fake_location,
6239 "glUniform2iv",
6240 Program::kUniform2i,
6241 &real_location,
6242 &type,
6243 &count)) {
6244 return;
6246 glUniform2iv(real_location, count, value);
6249 void GLES2DecoderImpl::DoUniform3iv(
6250 GLint fake_location, GLsizei count, const GLint* value) {
6251 GLenum type = 0;
6252 GLint real_location = -1;
6253 if (!PrepForSetUniformByLocation(fake_location,
6254 "glUniform3iv",
6255 Program::kUniform3i,
6256 &real_location,
6257 &type,
6258 &count)) {
6259 return;
6261 glUniform3iv(real_location, count, value);
6264 void GLES2DecoderImpl::DoUniform4iv(
6265 GLint fake_location, GLsizei count, const GLint* value) {
6266 GLenum type = 0;
6267 GLint real_location = -1;
6268 if (!PrepForSetUniformByLocation(fake_location,
6269 "glUniform4iv",
6270 Program::kUniform4i,
6271 &real_location,
6272 &type,
6273 &count)) {
6274 return;
6276 glUniform4iv(real_location, count, value);
6279 void GLES2DecoderImpl::DoUniformMatrix2fv(
6280 GLint fake_location, GLsizei count, GLboolean transpose,
6281 const GLfloat* value) {
6282 GLenum type = 0;
6283 GLint real_location = -1;
6284 if (!PrepForSetUniformByLocation(fake_location,
6285 "glUniformMatrix2fv",
6286 Program::kUniformMatrix2f,
6287 &real_location,
6288 &type,
6289 &count)) {
6290 return;
6292 glUniformMatrix2fv(real_location, count, transpose, value);
6295 void GLES2DecoderImpl::DoUniformMatrix3fv(
6296 GLint fake_location, GLsizei count, GLboolean transpose,
6297 const GLfloat* value) {
6298 GLenum type = 0;
6299 GLint real_location = -1;
6300 if (!PrepForSetUniformByLocation(fake_location,
6301 "glUniformMatrix3fv",
6302 Program::kUniformMatrix3f,
6303 &real_location,
6304 &type,
6305 &count)) {
6306 return;
6308 glUniformMatrix3fv(real_location, count, transpose, value);
6311 void GLES2DecoderImpl::DoUniformMatrix4fv(
6312 GLint fake_location, GLsizei count, GLboolean transpose,
6313 const GLfloat* value) {
6314 GLenum type = 0;
6315 GLint real_location = -1;
6316 if (!PrepForSetUniformByLocation(fake_location,
6317 "glUniformMatrix4fv",
6318 Program::kUniformMatrix4f,
6319 &real_location,
6320 &type,
6321 &count)) {
6322 return;
6324 glUniformMatrix4fv(real_location, count, transpose, value);
6327 void GLES2DecoderImpl::DoUseProgram(GLuint program_id) {
6328 GLuint service_id = 0;
6329 Program* program = NULL;
6330 if (program_id) {
6331 program = GetProgramInfoNotShader(program_id, "glUseProgram");
6332 if (!program) {
6333 return;
6335 if (!program->IsValid()) {
6336 // Program was not linked successfully. (ie, glLinkProgram)
6337 LOCAL_SET_GL_ERROR(
6338 GL_INVALID_OPERATION, "glUseProgram", "program not linked");
6339 return;
6341 service_id = program->service_id();
6343 if (state_.current_program.get()) {
6344 program_manager()->UnuseProgram(shader_manager(),
6345 state_.current_program.get());
6347 state_.current_program = program;
6348 LogClientServiceMapping("glUseProgram", program_id, service_id);
6349 glUseProgram(service_id);
6350 if (state_.current_program.get()) {
6351 program_manager()->UseProgram(state_.current_program.get());
6352 if (workarounds().clear_uniforms_before_first_program_use)
6353 program_manager()->ClearUniforms(program);
6357 void GLES2DecoderImpl::RenderWarning(
6358 const char* filename, int line, const std::string& msg) {
6359 logger_.LogMessage(filename, line, std::string("RENDER WARNING: ") + msg);
6362 void GLES2DecoderImpl::PerformanceWarning(
6363 const char* filename, int line, const std::string& msg) {
6364 logger_.LogMessage(filename, line,
6365 std::string("PERFORMANCE WARNING: ") + msg);
6368 void GLES2DecoderImpl::DoWillUseTexImageIfNeeded(
6369 Texture* texture, GLenum textarget) {
6370 // Image is already in use if texture is attached to a framebuffer.
6371 if (texture && !texture->IsAttachedToFramebuffer()) {
6372 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6373 if (image) {
6374 ScopedGLErrorSuppressor suppressor(
6375 "GLES2DecoderImpl::DoWillUseTexImageIfNeeded",
6376 GetErrorState());
6377 glBindTexture(textarget, texture->service_id());
6378 image->WillUseTexImage();
6379 RestoreCurrentTextureBindings(&state_, textarget);
6384 void GLES2DecoderImpl::DoDidUseTexImageIfNeeded(
6385 Texture* texture, GLenum textarget) {
6386 // Image is still in use if texture is attached to a framebuffer.
6387 if (texture && !texture->IsAttachedToFramebuffer()) {
6388 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6389 if (image) {
6390 ScopedGLErrorSuppressor suppressor(
6391 "GLES2DecoderImpl::DoDidUseTexImageIfNeeded",
6392 GetErrorState());
6393 glBindTexture(textarget, texture->service_id());
6394 image->DidUseTexImage();
6395 RestoreCurrentTextureBindings(&state_, textarget);
6400 bool GLES2DecoderImpl::PrepareTexturesForRender() {
6401 DCHECK(state_.current_program.get());
6402 if (!texture_manager()->HaveUnrenderableTextures() &&
6403 !texture_manager()->HaveImages()) {
6404 return true;
6407 bool textures_set = false;
6408 const Program::SamplerIndices& sampler_indices =
6409 state_.current_program->sampler_indices();
6410 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6411 const Program::UniformInfo* uniform_info =
6412 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6413 DCHECK(uniform_info);
6414 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6415 GLuint texture_unit_index = uniform_info->texture_units[jj];
6416 if (texture_unit_index < state_.texture_units.size()) {
6417 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6418 TextureRef* texture_ref =
6419 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6420 GLenum textarget = GetBindTargetForSamplerType(uniform_info->type);
6421 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
6422 textures_set = true;
6423 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6424 glBindTexture(
6425 textarget,
6426 texture_manager()->black_texture_id(uniform_info->type));
6427 if (!texture_ref) {
6428 LOCAL_RENDER_WARNING(
6429 std::string("there is no texture bound to the unit ") +
6430 base::IntToString(texture_unit_index));
6431 } else {
6432 LOCAL_RENDER_WARNING(
6433 std::string("texture bound to texture unit ") +
6434 base::IntToString(texture_unit_index) +
6435 " is not renderable. It maybe non-power-of-2 and have"
6436 " incompatible texture filtering.");
6438 continue;
6441 if (textarget != GL_TEXTURE_CUBE_MAP) {
6442 Texture* texture = texture_ref->texture();
6443 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6444 if (image && !texture->IsAttachedToFramebuffer()) {
6445 ScopedGLErrorSuppressor suppressor(
6446 "GLES2DecoderImpl::PrepareTexturesForRender", GetErrorState());
6447 textures_set = true;
6448 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6449 image->WillUseTexImage();
6450 continue;
6454 // else: should this be an error?
6457 return !textures_set;
6460 void GLES2DecoderImpl::RestoreStateForTextures() {
6461 DCHECK(state_.current_program.get());
6462 const Program::SamplerIndices& sampler_indices =
6463 state_.current_program->sampler_indices();
6464 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6465 const Program::UniformInfo* uniform_info =
6466 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6467 DCHECK(uniform_info);
6468 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6469 GLuint texture_unit_index = uniform_info->texture_units[jj];
6470 if (texture_unit_index < state_.texture_units.size()) {
6471 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6472 TextureRef* texture_ref =
6473 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6474 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
6475 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6476 // Get the texture_ref info that was previously bound here.
6477 texture_ref = texture_unit.bind_target == GL_TEXTURE_2D
6478 ? texture_unit.bound_texture_2d.get()
6479 : texture_unit.bound_texture_cube_map.get();
6480 glBindTexture(texture_unit.bind_target,
6481 texture_ref ? texture_ref->service_id() : 0);
6482 continue;
6485 if (texture_unit.bind_target != GL_TEXTURE_CUBE_MAP) {
6486 Texture* texture = texture_ref->texture();
6487 gfx::GLImage* image =
6488 texture->GetLevelImage(texture_unit.bind_target, 0);
6489 if (image && !texture->IsAttachedToFramebuffer()) {
6490 ScopedGLErrorSuppressor suppressor(
6491 "GLES2DecoderImpl::RestoreStateForTextures", GetErrorState());
6492 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6493 image->DidUseTexImage();
6494 continue;
6500 // Set the active texture back to whatever the user had it as.
6501 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
6504 bool GLES2DecoderImpl::ClearUnclearedTextures() {
6505 // Only check if there are some uncleared textures.
6506 if (!texture_manager()->HaveUnsafeTextures()) {
6507 return true;
6510 // 1: Check all textures we are about to render with.
6511 if (state_.current_program.get()) {
6512 const Program::SamplerIndices& sampler_indices =
6513 state_.current_program->sampler_indices();
6514 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6515 const Program::UniformInfo* uniform_info =
6516 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6517 DCHECK(uniform_info);
6518 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6519 GLuint texture_unit_index = uniform_info->texture_units[jj];
6520 if (texture_unit_index < state_.texture_units.size()) {
6521 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6522 TextureRef* texture_ref =
6523 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6524 if (texture_ref && !texture_ref->texture()->SafeToRenderFrom()) {
6525 if (!texture_manager()->ClearRenderableLevels(this, texture_ref)) {
6526 return false;
6533 return true;
6536 bool GLES2DecoderImpl::IsDrawValid(
6537 const char* function_name, GLuint max_vertex_accessed, bool instanced,
6538 GLsizei primcount) {
6539 DCHECK(instanced || primcount == 1);
6541 // NOTE: We specifically do not check current_program->IsValid() because
6542 // it could never be invalid since glUseProgram would have failed. While
6543 // glLinkProgram could later mark the program as invalid the previous
6544 // valid program will still function if it is still the current program.
6545 if (!state_.current_program.get()) {
6546 // The program does not exist.
6547 // But GL says no ERROR.
6548 LOCAL_RENDER_WARNING("Drawing with no current shader program.");
6549 return false;
6552 if (CheckDrawingFeedbackLoops()) {
6553 LOCAL_SET_GL_ERROR(
6554 GL_INVALID_OPERATION, function_name,
6555 "Source and destination textures of the draw are the same.");
6556 return false;
6559 return state_.vertex_attrib_manager
6560 ->ValidateBindings(function_name,
6561 this,
6562 feature_info_.get(),
6563 state_.current_program.get(),
6564 max_vertex_accessed,
6565 instanced,
6566 primcount);
6569 bool GLES2DecoderImpl::SimulateAttrib0(
6570 const char* function_name, GLuint max_vertex_accessed, bool* simulated) {
6571 DCHECK(simulated);
6572 *simulated = false;
6574 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
6575 return true;
6577 const VertexAttrib* attrib =
6578 state_.vertex_attrib_manager->GetVertexAttrib(0);
6579 // If it's enabled or it's not used then we don't need to do anything.
6580 bool attrib_0_used =
6581 state_.current_program->GetAttribInfoByLocation(0) != NULL;
6582 if (attrib->enabled() && attrib_0_used) {
6583 return true;
6586 // Make a buffer with a single repeated vec4 value enough to
6587 // simulate the constant value that is supposed to be here.
6588 // This is required to emulate GLES2 on GL.
6589 GLuint num_vertices = max_vertex_accessed + 1;
6590 uint32 size_needed = 0;
6592 if (num_vertices == 0 ||
6593 !SafeMultiplyUint32(num_vertices, sizeof(Vec4), &size_needed) ||
6594 size_needed > 0x7FFFFFFFU) {
6595 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6596 return false;
6599 LOCAL_PERFORMANCE_WARNING(
6600 "Attribute 0 is disabled. This has signficant performance penalty");
6602 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
6603 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
6605 bool new_buffer = static_cast<GLsizei>(size_needed) > attrib_0_size_;
6606 if (new_buffer) {
6607 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
6608 GLenum error = glGetError();
6609 if (error != GL_NO_ERROR) {
6610 LOCAL_SET_GL_ERROR(
6611 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6612 return false;
6616 const Vec4& value = state_.attrib_values[0];
6617 if (new_buffer ||
6618 (attrib_0_used &&
6619 (!attrib_0_buffer_matches_value_ ||
6620 (value.v[0] != attrib_0_value_.v[0] ||
6621 value.v[1] != attrib_0_value_.v[1] ||
6622 value.v[2] != attrib_0_value_.v[2] ||
6623 value.v[3] != attrib_0_value_.v[3])))) {
6624 std::vector<Vec4> temp(num_vertices, value);
6625 glBufferSubData(GL_ARRAY_BUFFER, 0, size_needed, &temp[0].v[0]);
6626 attrib_0_buffer_matches_value_ = true;
6627 attrib_0_value_ = value;
6628 attrib_0_size_ = size_needed;
6631 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
6633 if (attrib->divisor())
6634 glVertexAttribDivisorANGLE(0, 0);
6636 *simulated = true;
6637 return true;
6640 void GLES2DecoderImpl::RestoreStateForAttrib(
6641 GLuint attrib_index, bool restore_array_binding) {
6642 const VertexAttrib* attrib =
6643 state_.vertex_attrib_manager->GetVertexAttrib(attrib_index);
6644 if (restore_array_binding) {
6645 const void* ptr = reinterpret_cast<const void*>(attrib->offset());
6646 Buffer* buffer = attrib->buffer();
6647 glBindBuffer(GL_ARRAY_BUFFER, buffer ? buffer->service_id() : 0);
6648 glVertexAttribPointer(
6649 attrib_index, attrib->size(), attrib->type(), attrib->normalized(),
6650 attrib->gl_stride(), ptr);
6652 if (attrib->divisor())
6653 glVertexAttribDivisorANGLE(attrib_index, attrib->divisor());
6654 glBindBuffer(
6655 GL_ARRAY_BUFFER, state_.bound_array_buffer.get() ?
6656 state_.bound_array_buffer->service_id() : 0);
6658 // Never touch vertex attribute 0's state (in particular, never
6659 // disable it) when running on desktop GL because it will never be
6660 // re-enabled.
6661 if (attrib_index != 0 ||
6662 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
6663 if (attrib->enabled()) {
6664 glEnableVertexAttribArray(attrib_index);
6665 } else {
6666 glDisableVertexAttribArray(attrib_index);
6671 bool GLES2DecoderImpl::SimulateFixedAttribs(
6672 const char* function_name,
6673 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount) {
6674 DCHECK(simulated);
6675 *simulated = false;
6676 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
6677 return true;
6679 if (!state_.vertex_attrib_manager->HaveFixedAttribs()) {
6680 return true;
6683 LOCAL_PERFORMANCE_WARNING(
6684 "GL_FIXED attributes have a signficant performance penalty");
6686 // NOTE: we could be smart and try to check if a buffer is used
6687 // twice in 2 different attribs, find the overlapping parts and therefore
6688 // duplicate the minimum amount of data but this whole code path is not meant
6689 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
6690 // tests so we just add to the buffer attrib used.
6692 GLuint elements_needed = 0;
6693 const VertexAttribManager::VertexAttribList& enabled_attribs =
6694 state_.vertex_attrib_manager->GetEnabledVertexAttribs();
6695 for (VertexAttribManager::VertexAttribList::const_iterator it =
6696 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
6697 const VertexAttrib* attrib = *it;
6698 const Program::VertexAttrib* attrib_info =
6699 state_.current_program->GetAttribInfoByLocation(attrib->index());
6700 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
6701 max_vertex_accessed);
6702 GLuint num_vertices = max_accessed + 1;
6703 if (num_vertices == 0) {
6704 LOCAL_SET_GL_ERROR(
6705 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6706 return false;
6708 if (attrib_info &&
6709 attrib->CanAccess(max_accessed) &&
6710 attrib->type() == GL_FIXED) {
6711 uint32 elements_used = 0;
6712 if (!SafeMultiplyUint32(num_vertices, attrib->size(), &elements_used) ||
6713 !SafeAddUint32(elements_needed, elements_used, &elements_needed)) {
6714 LOCAL_SET_GL_ERROR(
6715 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
6716 return false;
6721 const uint32 kSizeOfFloat = sizeof(float); // NOLINT
6722 uint32 size_needed = 0;
6723 if (!SafeMultiplyUint32(elements_needed, kSizeOfFloat, &size_needed) ||
6724 size_needed > 0x7FFFFFFFU) {
6725 LOCAL_SET_GL_ERROR(
6726 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
6727 return false;
6730 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
6732 glBindBuffer(GL_ARRAY_BUFFER, fixed_attrib_buffer_id_);
6733 if (static_cast<GLsizei>(size_needed) > fixed_attrib_buffer_size_) {
6734 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
6735 GLenum error = glGetError();
6736 if (error != GL_NO_ERROR) {
6737 LOCAL_SET_GL_ERROR(
6738 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
6739 return false;
6743 // Copy the elements and convert to float
6744 GLintptr offset = 0;
6745 for (VertexAttribManager::VertexAttribList::const_iterator it =
6746 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
6747 const VertexAttrib* attrib = *it;
6748 const Program::VertexAttrib* attrib_info =
6749 state_.current_program->GetAttribInfoByLocation(attrib->index());
6750 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
6751 max_vertex_accessed);
6752 GLuint num_vertices = max_accessed + 1;
6753 if (num_vertices == 0) {
6754 LOCAL_SET_GL_ERROR(
6755 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6756 return false;
6758 if (attrib_info &&
6759 attrib->CanAccess(max_accessed) &&
6760 attrib->type() == GL_FIXED) {
6761 int num_elements = attrib->size() * num_vertices;
6762 const int src_size = num_elements * sizeof(int32);
6763 const int dst_size = num_elements * sizeof(float);
6764 scoped_ptr<float[]> data(new float[num_elements]);
6765 const int32* src = reinterpret_cast<const int32 *>(
6766 attrib->buffer()->GetRange(attrib->offset(), src_size));
6767 const int32* end = src + num_elements;
6768 float* dst = data.get();
6769 while (src != end) {
6770 *dst++ = static_cast<float>(*src++) / 65536.0f;
6772 glBufferSubData(GL_ARRAY_BUFFER, offset, dst_size, data.get());
6773 glVertexAttribPointer(
6774 attrib->index(), attrib->size(), GL_FLOAT, false, 0,
6775 reinterpret_cast<GLvoid*>(offset));
6776 offset += dst_size;
6779 *simulated = true;
6780 return true;
6783 void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
6784 // There's no need to call glVertexAttribPointer because we shadow all the
6785 // settings and passing GL_FIXED to it will not work.
6786 glBindBuffer(
6787 GL_ARRAY_BUFFER,
6788 state_.bound_array_buffer.get() ? state_.bound_array_buffer->service_id()
6789 : 0);
6792 error::Error GLES2DecoderImpl::DoDrawArrays(
6793 const char* function_name,
6794 bool instanced,
6795 GLenum mode,
6796 GLint first,
6797 GLsizei count,
6798 GLsizei primcount) {
6799 error::Error error = WillAccessBoundFramebufferForDraw();
6800 if (error != error::kNoError)
6801 return error;
6802 if (!validators_->draw_mode.IsValid(mode)) {
6803 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
6804 return error::kNoError;
6806 if (count < 0) {
6807 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
6808 return error::kNoError;
6810 if (primcount < 0) {
6811 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
6812 return error::kNoError;
6814 if (!CheckBoundFramebuffersValid(function_name)) {
6815 return error::kNoError;
6817 // We have to check this here because the prototype for glDrawArrays
6818 // is GLint not GLsizei.
6819 if (first < 0) {
6820 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "first < 0");
6821 return error::kNoError;
6824 if (count == 0 || primcount == 0) {
6825 LOCAL_RENDER_WARNING("Render count or primcount is 0.");
6826 return error::kNoError;
6829 GLuint max_vertex_accessed = first + count - 1;
6830 if (IsDrawValid(function_name, max_vertex_accessed, instanced, primcount)) {
6831 if (!ClearUnclearedTextures()) {
6832 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
6833 return error::kNoError;
6835 bool simulated_attrib_0 = false;
6836 if (!SimulateAttrib0(
6837 function_name, max_vertex_accessed, &simulated_attrib_0)) {
6838 return error::kNoError;
6840 bool simulated_fixed_attribs = false;
6841 if (SimulateFixedAttribs(
6842 function_name, max_vertex_accessed, &simulated_fixed_attribs,
6843 primcount)) {
6844 bool textures_set = !PrepareTexturesForRender();
6845 ApplyDirtyState();
6846 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
6847 if (!instanced) {
6848 glDrawArrays(mode, first, count);
6849 } else {
6850 glDrawArraysInstancedANGLE(mode, first, count, primcount);
6852 if (textures_set) {
6853 RestoreStateForTextures();
6855 if (simulated_fixed_attribs) {
6856 RestoreStateForSimulatedFixedAttribs();
6859 if (simulated_attrib_0) {
6860 // We don't have to restore attrib 0 generic data at the end of this
6861 // function even if it is simulated. This is because we will simulate
6862 // it in each draw call, and attrib 0 generic data queries use cached
6863 // values instead of passing down to the underlying driver.
6864 RestoreStateForAttrib(0, false);
6867 return error::kNoError;
6870 error::Error GLES2DecoderImpl::HandleDrawArrays(uint32 immediate_data_size,
6871 const void* cmd_data) {
6872 const cmds::DrawArrays& c = *static_cast<const cmds::DrawArrays*>(cmd_data);
6873 return DoDrawArrays("glDrawArrays",
6874 false,
6875 static_cast<GLenum>(c.mode),
6876 static_cast<GLint>(c.first),
6877 static_cast<GLsizei>(c.count),
6881 error::Error GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
6882 uint32 immediate_data_size,
6883 const void* cmd_data) {
6884 const gles2::cmds::DrawArraysInstancedANGLE& c =
6885 *static_cast<const gles2::cmds::DrawArraysInstancedANGLE*>(cmd_data);
6886 if (!features().angle_instanced_arrays) {
6887 LOCAL_SET_GL_ERROR(
6888 GL_INVALID_OPERATION,
6889 "glDrawArraysInstancedANGLE", "function not available");
6890 return error::kNoError;
6892 return DoDrawArrays("glDrawArraysIntancedANGLE",
6893 true,
6894 static_cast<GLenum>(c.mode),
6895 static_cast<GLint>(c.first),
6896 static_cast<GLsizei>(c.count),
6897 static_cast<GLsizei>(c.primcount));
6900 error::Error GLES2DecoderImpl::DoDrawElements(
6901 const char* function_name,
6902 bool instanced,
6903 GLenum mode,
6904 GLsizei count,
6905 GLenum type,
6906 int32 offset,
6907 GLsizei primcount) {
6908 error::Error error = WillAccessBoundFramebufferForDraw();
6909 if (error != error::kNoError)
6910 return error;
6911 if (!state_.vertex_attrib_manager->element_array_buffer()) {
6912 LOCAL_SET_GL_ERROR(
6913 GL_INVALID_OPERATION, function_name, "No element array buffer bound");
6914 return error::kNoError;
6917 if (count < 0) {
6918 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
6919 return error::kNoError;
6921 if (offset < 0) {
6922 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "offset < 0");
6923 return error::kNoError;
6925 if (!validators_->draw_mode.IsValid(mode)) {
6926 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
6927 return error::kNoError;
6929 if (!validators_->index_type.IsValid(type)) {
6930 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, type, "type");
6931 return error::kNoError;
6933 if (primcount < 0) {
6934 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
6935 return error::kNoError;
6938 if (!CheckBoundFramebuffersValid(function_name)) {
6939 return error::kNoError;
6942 if (count == 0 || primcount == 0) {
6943 return error::kNoError;
6946 GLuint max_vertex_accessed;
6947 Buffer* element_array_buffer =
6948 state_.vertex_attrib_manager->element_array_buffer();
6950 if (!element_array_buffer->GetMaxValueForRange(
6951 offset, count, type, &max_vertex_accessed)) {
6952 LOCAL_SET_GL_ERROR(
6953 GL_INVALID_OPERATION, function_name, "range out of bounds for buffer");
6954 return error::kNoError;
6957 if (IsDrawValid(function_name, max_vertex_accessed, instanced, primcount)) {
6958 if (!ClearUnclearedTextures()) {
6959 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
6960 return error::kNoError;
6962 bool simulated_attrib_0 = false;
6963 if (!SimulateAttrib0(
6964 function_name, max_vertex_accessed, &simulated_attrib_0)) {
6965 return error::kNoError;
6967 bool simulated_fixed_attribs = false;
6968 if (SimulateFixedAttribs(
6969 function_name, max_vertex_accessed, &simulated_fixed_attribs,
6970 primcount)) {
6971 bool textures_set = !PrepareTexturesForRender();
6972 ApplyDirtyState();
6973 // TODO(gman): Refactor to hide these details in BufferManager or
6974 // VertexAttribManager.
6975 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
6976 bool used_client_side_array = false;
6977 if (element_array_buffer->IsClientSideArray()) {
6978 used_client_side_array = true;
6979 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
6980 indices = element_array_buffer->GetRange(offset, 0);
6983 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
6984 if (!instanced) {
6985 glDrawElements(mode, count, type, indices);
6986 } else {
6987 glDrawElementsInstancedANGLE(mode, count, type, indices, primcount);
6990 if (used_client_side_array) {
6991 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
6992 element_array_buffer->service_id());
6995 if (textures_set) {
6996 RestoreStateForTextures();
6998 if (simulated_fixed_attribs) {
6999 RestoreStateForSimulatedFixedAttribs();
7002 if (simulated_attrib_0) {
7003 // We don't have to restore attrib 0 generic data at the end of this
7004 // function even if it is simulated. This is because we will simulate
7005 // it in each draw call, and attrib 0 generic data queries use cached
7006 // values instead of passing down to the underlying driver.
7007 RestoreStateForAttrib(0, false);
7010 return error::kNoError;
7013 error::Error GLES2DecoderImpl::HandleDrawElements(uint32 immediate_data_size,
7014 const void* cmd_data) {
7015 const gles2::cmds::DrawElements& c =
7016 *static_cast<const gles2::cmds::DrawElements*>(cmd_data);
7017 return DoDrawElements("glDrawElements",
7018 false,
7019 static_cast<GLenum>(c.mode),
7020 static_cast<GLsizei>(c.count),
7021 static_cast<GLenum>(c.type),
7022 static_cast<int32>(c.index_offset),
7026 error::Error GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
7027 uint32 immediate_data_size,
7028 const void* cmd_data) {
7029 const gles2::cmds::DrawElementsInstancedANGLE& c =
7030 *static_cast<const gles2::cmds::DrawElementsInstancedANGLE*>(cmd_data);
7031 if (!features().angle_instanced_arrays) {
7032 LOCAL_SET_GL_ERROR(
7033 GL_INVALID_OPERATION,
7034 "glDrawElementsInstancedANGLE", "function not available");
7035 return error::kNoError;
7037 return DoDrawElements("glDrawElementsInstancedANGLE",
7038 true,
7039 static_cast<GLenum>(c.mode),
7040 static_cast<GLsizei>(c.count),
7041 static_cast<GLenum>(c.type),
7042 static_cast<int32>(c.index_offset),
7043 static_cast<GLsizei>(c.primcount));
7046 GLuint GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
7047 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
7048 GLuint max_vertex_accessed = 0;
7049 Buffer* buffer = GetBuffer(buffer_id);
7050 if (!buffer) {
7051 // TODO(gman): Should this be a GL error or a command buffer error?
7052 LOCAL_SET_GL_ERROR(
7053 GL_INVALID_VALUE, "GetMaxValueInBufferCHROMIUM", "unknown buffer");
7054 } else {
7055 if (!buffer->GetMaxValueForRange(
7056 offset, count, type, &max_vertex_accessed)) {
7057 // TODO(gman): Should this be a GL error or a command buffer error?
7058 LOCAL_SET_GL_ERROR(
7059 GL_INVALID_OPERATION,
7060 "GetMaxValueInBufferCHROMIUM", "range out of bounds for buffer");
7063 return max_vertex_accessed;
7066 void GLES2DecoderImpl::DoShaderSource(
7067 GLuint client_id, GLsizei count, const char** data, const GLint* length) {
7068 std::string str;
7069 for (GLsizei ii = 0; ii < count; ++ii) {
7070 if (length && length[ii] > 0)
7071 str.append(data[ii], length[ii]);
7072 else
7073 str.append(data[ii]);
7075 Shader* shader = GetShaderInfoNotProgram(client_id, "glShaderSource");
7076 if (!shader) {
7077 return;
7079 // Note: We don't actually call glShaderSource here. We wait until
7080 // we actually compile the shader.
7081 shader->set_source(str);
7084 void GLES2DecoderImpl::DoTransformFeedbackVaryings(
7085 GLuint client_program_id, GLsizei count, const char* const* varyings,
7086 GLenum buffer_mode) {
7087 Program* program = GetProgramInfoNotShader(
7088 client_program_id, "glTransformFeedbackVaryings");
7089 if (!program) {
7090 return;
7092 glTransformFeedbackVaryings(
7093 program->service_id(), count, varyings, buffer_mode);
7096 void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
7097 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
7098 Shader* shader = GetShaderInfoNotProgram(client_id, "glCompileShader");
7099 if (!shader) {
7100 return;
7103 scoped_refptr<ShaderTranslatorInterface> translator;
7104 if (use_shader_translator_) {
7105 translator = shader->shader_type() == GL_VERTEX_SHADER ?
7106 vertex_translator_ : fragment_translator_;
7109 const Shader::TranslatedShaderSourceType source_type =
7110 feature_info_->feature_flags().angle_translated_shader_source ?
7111 Shader::kANGLE : Shader::kGL;
7112 shader->RequestCompile(translator, source_type);
7115 void GLES2DecoderImpl::DoGetShaderiv(
7116 GLuint shader_id, GLenum pname, GLint* params) {
7117 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderiv");
7118 if (!shader) {
7119 return;
7122 // Compile now for statuses that require it.
7123 switch (pname) {
7124 case GL_COMPILE_STATUS:
7125 case GL_INFO_LOG_LENGTH:
7126 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
7127 shader->DoCompile();
7128 break;
7130 default:
7131 break;
7134 switch (pname) {
7135 case GL_SHADER_SOURCE_LENGTH:
7136 *params = shader->source().size();
7137 if (*params)
7138 ++(*params);
7139 return;
7140 case GL_COMPILE_STATUS:
7141 *params = compile_shader_always_succeeds_ ? true : shader->valid();
7142 return;
7143 case GL_INFO_LOG_LENGTH:
7144 *params = shader->log_info().size();
7145 if (*params)
7146 ++(*params);
7147 return;
7148 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
7149 *params = shader->translated_source().size();
7150 if (*params)
7151 ++(*params);
7152 return;
7153 default:
7154 break;
7156 glGetShaderiv(shader->service_id(), pname, params);
7159 error::Error GLES2DecoderImpl::HandleGetShaderSource(uint32 immediate_data_size,
7160 const void* cmd_data) {
7161 const gles2::cmds::GetShaderSource& c =
7162 *static_cast<const gles2::cmds::GetShaderSource*>(cmd_data);
7163 GLuint shader_id = c.shader;
7164 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
7165 Bucket* bucket = CreateBucket(bucket_id);
7166 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderSource");
7167 if (!shader || shader->source().empty()) {
7168 bucket->SetSize(0);
7169 return error::kNoError;
7171 bucket->SetFromString(shader->source().c_str());
7172 return error::kNoError;
7175 error::Error GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
7176 uint32 immediate_data_size,
7177 const void* cmd_data) {
7178 const gles2::cmds::GetTranslatedShaderSourceANGLE& c =
7179 *static_cast<const gles2::cmds::GetTranslatedShaderSourceANGLE*>(
7180 cmd_data);
7181 GLuint shader_id = c.shader;
7182 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
7183 Bucket* bucket = CreateBucket(bucket_id);
7184 Shader* shader = GetShaderInfoNotProgram(
7185 shader_id, "glGetTranslatedShaderSourceANGLE");
7186 if (!shader) {
7187 bucket->SetSize(0);
7188 return error::kNoError;
7191 // Make sure translator has been utilized in compile.
7192 shader->DoCompile();
7194 bucket->SetFromString(shader->translated_source().c_str());
7195 return error::kNoError;
7198 error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
7199 uint32 immediate_data_size,
7200 const void* cmd_data) {
7201 const gles2::cmds::GetProgramInfoLog& c =
7202 *static_cast<const gles2::cmds::GetProgramInfoLog*>(cmd_data);
7203 GLuint program_id = c.program;
7204 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
7205 Bucket* bucket = CreateBucket(bucket_id);
7206 Program* program = GetProgramInfoNotShader(
7207 program_id, "glGetProgramInfoLog");
7208 if (!program || !program->log_info()) {
7209 bucket->SetFromString("");
7210 return error::kNoError;
7212 bucket->SetFromString(program->log_info()->c_str());
7213 return error::kNoError;
7216 error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
7217 uint32 immediate_data_size,
7218 const void* cmd_data) {
7219 const gles2::cmds::GetShaderInfoLog& c =
7220 *static_cast<const gles2::cmds::GetShaderInfoLog*>(cmd_data);
7221 GLuint shader_id = c.shader;
7222 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
7223 Bucket* bucket = CreateBucket(bucket_id);
7224 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderInfoLog");
7225 if (!shader) {
7226 bucket->SetFromString("");
7227 return error::kNoError;
7230 // Shader must be compiled in order to get the info log.
7231 shader->DoCompile();
7233 bucket->SetFromString(shader->log_info().c_str());
7234 return error::kNoError;
7237 bool GLES2DecoderImpl::DoIsEnabled(GLenum cap) {
7238 return state_.GetEnabled(cap);
7241 bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
7242 const Buffer* buffer = GetBuffer(client_id);
7243 return buffer && buffer->IsValid() && !buffer->IsDeleted();
7246 bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
7247 const Framebuffer* framebuffer =
7248 GetFramebuffer(client_id);
7249 return framebuffer && framebuffer->IsValid() && !framebuffer->IsDeleted();
7252 bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
7253 // IsProgram is true for programs as soon as they are created, until they are
7254 // deleted and no longer in use.
7255 const Program* program = GetProgram(client_id);
7256 return program != NULL && !program->IsDeleted();
7259 bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
7260 const Renderbuffer* renderbuffer =
7261 GetRenderbuffer(client_id);
7262 return renderbuffer && renderbuffer->IsValid() && !renderbuffer->IsDeleted();
7265 bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
7266 // IsShader is true for shaders as soon as they are created, until they
7267 // are deleted and not attached to any programs.
7268 const Shader* shader = GetShader(client_id);
7269 return shader != NULL && !shader->IsDeleted();
7272 bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
7273 const TextureRef* texture_ref = GetTexture(client_id);
7274 return texture_ref && texture_ref->texture()->IsValid();
7277 void GLES2DecoderImpl::DoAttachShader(
7278 GLuint program_client_id, GLint shader_client_id) {
7279 Program* program = GetProgramInfoNotShader(
7280 program_client_id, "glAttachShader");
7281 if (!program) {
7282 return;
7284 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glAttachShader");
7285 if (!shader) {
7286 return;
7288 if (!program->AttachShader(shader_manager(), shader)) {
7289 LOCAL_SET_GL_ERROR(
7290 GL_INVALID_OPERATION,
7291 "glAttachShader",
7292 "can not attach more than one shader of the same type.");
7293 return;
7295 glAttachShader(program->service_id(), shader->service_id());
7298 void GLES2DecoderImpl::DoDetachShader(
7299 GLuint program_client_id, GLint shader_client_id) {
7300 Program* program = GetProgramInfoNotShader(
7301 program_client_id, "glDetachShader");
7302 if (!program) {
7303 return;
7305 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glDetachShader");
7306 if (!shader) {
7307 return;
7309 if (!program->DetachShader(shader_manager(), shader)) {
7310 LOCAL_SET_GL_ERROR(
7311 GL_INVALID_OPERATION,
7312 "glDetachShader", "shader not attached to program");
7313 return;
7315 glDetachShader(program->service_id(), shader->service_id());
7318 void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
7319 Program* program = GetProgramInfoNotShader(
7320 program_client_id, "glValidateProgram");
7321 if (!program) {
7322 return;
7324 program->Validate();
7327 void GLES2DecoderImpl::GetVertexAttribHelper(
7328 const VertexAttrib* attrib, GLenum pname, GLint* params) {
7329 switch (pname) {
7330 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
7331 Buffer* buffer = attrib->buffer();
7332 if (buffer && !buffer->IsDeleted()) {
7333 GLuint client_id;
7334 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
7335 *params = client_id;
7337 break;
7339 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
7340 *params = attrib->enabled();
7341 break;
7342 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
7343 *params = attrib->size();
7344 break;
7345 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
7346 *params = attrib->gl_stride();
7347 break;
7348 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
7349 *params = attrib->type();
7350 break;
7351 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
7352 *params = attrib->normalized();
7353 break;
7354 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE:
7355 *params = attrib->divisor();
7356 break;
7357 default:
7358 NOTREACHED();
7359 break;
7363 void GLES2DecoderImpl::DoGetTexParameterfv(
7364 GLenum target, GLenum pname, GLfloat* params) {
7365 InitTextureMaxAnisotropyIfNeeded(target, pname);
7366 glGetTexParameterfv(target, pname, params);
7369 void GLES2DecoderImpl::DoGetTexParameteriv(
7370 GLenum target, GLenum pname, GLint* params) {
7371 InitTextureMaxAnisotropyIfNeeded(target, pname);
7372 glGetTexParameteriv(target, pname, params);
7375 void GLES2DecoderImpl::InitTextureMaxAnisotropyIfNeeded(
7376 GLenum target, GLenum pname) {
7377 if (!workarounds().init_texture_max_anisotropy)
7378 return;
7379 if (pname != GL_TEXTURE_MAX_ANISOTROPY_EXT ||
7380 !validators_->texture_parameter.IsValid(pname)) {
7381 return;
7384 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
7385 &state_, target);
7386 if (!texture_ref) {
7387 LOCAL_SET_GL_ERROR(
7388 GL_INVALID_OPERATION,
7389 "glGetTexParamter{fi}v", "unknown texture for target");
7390 return;
7392 Texture* texture = texture_ref->texture();
7393 texture->InitTextureMaxAnisotropyIfNeeded(target);
7396 void GLES2DecoderImpl::DoGetVertexAttribfv(
7397 GLuint index, GLenum pname, GLfloat* params) {
7398 VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(index);
7399 if (!attrib) {
7400 LOCAL_SET_GL_ERROR(
7401 GL_INVALID_VALUE, "glGetVertexAttribfv", "index out of range");
7402 return;
7404 switch (pname) {
7405 case GL_CURRENT_VERTEX_ATTRIB: {
7406 const Vec4& value = state_.attrib_values[index];
7407 params[0] = value.v[0];
7408 params[1] = value.v[1];
7409 params[2] = value.v[2];
7410 params[3] = value.v[3];
7411 break;
7413 default: {
7414 GLint value = 0;
7415 GetVertexAttribHelper(attrib, pname, &value);
7416 *params = static_cast<GLfloat>(value);
7417 break;
7422 void GLES2DecoderImpl::DoGetVertexAttribiv(
7423 GLuint index, GLenum pname, GLint* params) {
7424 VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(index);
7425 if (!attrib) {
7426 LOCAL_SET_GL_ERROR(
7427 GL_INVALID_VALUE, "glGetVertexAttribiv", "index out of range");
7428 return;
7430 switch (pname) {
7431 case GL_CURRENT_VERTEX_ATTRIB: {
7432 const Vec4& value = state_.attrib_values[index];
7433 params[0] = static_cast<GLint>(value.v[0]);
7434 params[1] = static_cast<GLint>(value.v[1]);
7435 params[2] = static_cast<GLint>(value.v[2]);
7436 params[3] = static_cast<GLint>(value.v[3]);
7437 break;
7439 default:
7440 GetVertexAttribHelper(attrib, pname, params);
7441 break;
7445 bool GLES2DecoderImpl::SetVertexAttribValue(
7446 const char* function_name, GLuint index, const GLfloat* value) {
7447 if (index >= state_.attrib_values.size()) {
7448 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "index out of range");
7449 return false;
7451 Vec4& v = state_.attrib_values[index];
7452 v.v[0] = value[0];
7453 v.v[1] = value[1];
7454 v.v[2] = value[2];
7455 v.v[3] = value[3];
7456 return true;
7459 void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
7460 GLfloat v[4] = { v0, 0.0f, 0.0f, 1.0f, };
7461 if (SetVertexAttribValue("glVertexAttrib1f", index, v)) {
7462 glVertexAttrib1f(index, v0);
7466 void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
7467 GLfloat v[4] = { v0, v1, 0.0f, 1.0f, };
7468 if (SetVertexAttribValue("glVertexAttrib2f", index, v)) {
7469 glVertexAttrib2f(index, v0, v1);
7473 void GLES2DecoderImpl::DoVertexAttrib3f(
7474 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
7475 GLfloat v[4] = { v0, v1, v2, 1.0f, };
7476 if (SetVertexAttribValue("glVertexAttrib3f", index, v)) {
7477 glVertexAttrib3f(index, v0, v1, v2);
7481 void GLES2DecoderImpl::DoVertexAttrib4f(
7482 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
7483 GLfloat v[4] = { v0, v1, v2, v3, };
7484 if (SetVertexAttribValue("glVertexAttrib4f", index, v)) {
7485 glVertexAttrib4f(index, v0, v1, v2, v3);
7489 void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
7490 GLfloat t[4] = { v[0], 0.0f, 0.0f, 1.0f, };
7491 if (SetVertexAttribValue("glVertexAttrib1fv", index, t)) {
7492 glVertexAttrib1fv(index, v);
7496 void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
7497 GLfloat t[4] = { v[0], v[1], 0.0f, 1.0f, };
7498 if (SetVertexAttribValue("glVertexAttrib2fv", index, t)) {
7499 glVertexAttrib2fv(index, v);
7503 void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
7504 GLfloat t[4] = { v[0], v[1], v[2], 1.0f, };
7505 if (SetVertexAttribValue("glVertexAttrib3fv", index, t)) {
7506 glVertexAttrib3fv(index, v);
7510 void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
7511 if (SetVertexAttribValue("glVertexAttrib4fv", index, v)) {
7512 glVertexAttrib4fv(index, v);
7516 error::Error GLES2DecoderImpl::HandleVertexAttribIPointer(
7517 uint32 immediate_data_size,
7518 const void* cmd_data) {
7519 // TODO(zmo): Unsafe ES3 API, missing states update.
7520 if (!unsafe_es3_apis_enabled())
7521 return error::kUnknownCommand;
7522 const gles2::cmds::VertexAttribIPointer& c =
7523 *static_cast<const gles2::cmds::VertexAttribIPointer*>(cmd_data);
7524 GLuint indx = c.indx;
7525 GLint size = c.size;
7526 GLenum type = c.type;
7527 GLsizei stride = c.stride;
7528 GLsizei offset = c.offset;
7529 const void* ptr = reinterpret_cast<const void*>(offset);
7530 glVertexAttribIPointer(indx, size, type, stride, ptr);
7531 return error::kNoError;
7534 error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
7535 uint32 immediate_data_size,
7536 const void* cmd_data) {
7537 const gles2::cmds::VertexAttribPointer& c =
7538 *static_cast<const gles2::cmds::VertexAttribPointer*>(cmd_data);
7540 if (!state_.bound_array_buffer.get() ||
7541 state_.bound_array_buffer->IsDeleted()) {
7542 if (state_.vertex_attrib_manager.get() ==
7543 state_.default_vertex_attrib_manager.get()) {
7544 LOCAL_SET_GL_ERROR(
7545 GL_INVALID_VALUE, "glVertexAttribPointer", "no array buffer bound");
7546 return error::kNoError;
7547 } else if (c.offset != 0) {
7548 LOCAL_SET_GL_ERROR(
7549 GL_INVALID_VALUE,
7550 "glVertexAttribPointer", "client side arrays are not allowed");
7551 return error::kNoError;
7555 GLuint indx = c.indx;
7556 GLint size = c.size;
7557 GLenum type = c.type;
7558 GLboolean normalized = static_cast<GLboolean>(c.normalized);
7559 GLsizei stride = c.stride;
7560 GLsizei offset = c.offset;
7561 const void* ptr = reinterpret_cast<const void*>(offset);
7562 if (!validators_->vertex_attrib_type.IsValid(type)) {
7563 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribPointer", type, "type");
7564 return error::kNoError;
7566 if (!validators_->vertex_attrib_size.IsValid(size)) {
7567 LOCAL_SET_GL_ERROR(
7568 GL_INVALID_VALUE, "glVertexAttribPointer", "size GL_INVALID_VALUE");
7569 return error::kNoError;
7571 if (indx >= group_->max_vertex_attribs()) {
7572 LOCAL_SET_GL_ERROR(
7573 GL_INVALID_VALUE, "glVertexAttribPointer", "index out of range");
7574 return error::kNoError;
7576 if (stride < 0) {
7577 LOCAL_SET_GL_ERROR(
7578 GL_INVALID_VALUE, "glVertexAttribPointer", "stride < 0");
7579 return error::kNoError;
7581 if (stride > 255) {
7582 LOCAL_SET_GL_ERROR(
7583 GL_INVALID_VALUE, "glVertexAttribPointer", "stride > 255");
7584 return error::kNoError;
7586 if (offset < 0) {
7587 LOCAL_SET_GL_ERROR(
7588 GL_INVALID_VALUE, "glVertexAttribPointer", "offset < 0");
7589 return error::kNoError;
7591 GLsizei component_size =
7592 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
7593 // component_size must be a power of two to use & as optimized modulo.
7594 DCHECK(GLES2Util::IsPOT(component_size));
7595 if (offset & (component_size - 1)) {
7596 LOCAL_SET_GL_ERROR(
7597 GL_INVALID_OPERATION,
7598 "glVertexAttribPointer", "offset not valid for type");
7599 return error::kNoError;
7601 if (stride & (component_size - 1)) {
7602 LOCAL_SET_GL_ERROR(
7603 GL_INVALID_OPERATION,
7604 "glVertexAttribPointer", "stride not valid for type");
7605 return error::kNoError;
7607 state_.vertex_attrib_manager
7608 ->SetAttribInfo(indx,
7609 state_.bound_array_buffer.get(),
7610 size,
7611 type,
7612 normalized,
7613 stride,
7614 stride != 0 ? stride : component_size * size,
7615 offset);
7616 if (type != GL_FIXED) {
7617 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
7619 return error::kNoError;
7622 void GLES2DecoderImpl::DoViewport(GLint x, GLint y, GLsizei width,
7623 GLsizei height) {
7624 state_.viewport_x = x;
7625 state_.viewport_y = y;
7626 state_.viewport_width = std::min(width, viewport_max_width_);
7627 state_.viewport_height = std::min(height, viewport_max_height_);
7628 glViewport(x, y, width, height);
7631 error::Error GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
7632 uint32 immediate_data_size,
7633 const void* cmd_data) {
7634 const gles2::cmds::VertexAttribDivisorANGLE& c =
7635 *static_cast<const gles2::cmds::VertexAttribDivisorANGLE*>(cmd_data);
7636 if (!features().angle_instanced_arrays) {
7637 LOCAL_SET_GL_ERROR(
7638 GL_INVALID_OPERATION,
7639 "glVertexAttribDivisorANGLE", "function not available");
7640 return error::kNoError;
7642 GLuint index = c.index;
7643 GLuint divisor = c.divisor;
7644 if (index >= group_->max_vertex_attribs()) {
7645 LOCAL_SET_GL_ERROR(
7646 GL_INVALID_VALUE,
7647 "glVertexAttribDivisorANGLE", "index out of range");
7648 return error::kNoError;
7651 state_.vertex_attrib_manager->SetDivisor(
7652 index,
7653 divisor);
7654 glVertexAttribDivisorANGLE(index, divisor);
7655 return error::kNoError;
7658 template <typename pixel_data_type>
7659 static void WriteAlphaData(
7660 void *pixels, uint32 row_count, uint32 channel_count,
7661 uint32 alpha_channel_index, uint32 unpadded_row_size,
7662 uint32 padded_row_size, pixel_data_type alpha_value) {
7663 DCHECK_GT(channel_count, 0U);
7664 DCHECK_EQ(unpadded_row_size % sizeof(pixel_data_type), 0U);
7665 uint32 unpadded_row_size_in_elements =
7666 unpadded_row_size / sizeof(pixel_data_type);
7667 DCHECK_EQ(padded_row_size % sizeof(pixel_data_type), 0U);
7668 uint32 padded_row_size_in_elements =
7669 padded_row_size / sizeof(pixel_data_type);
7670 pixel_data_type* dst =
7671 static_cast<pixel_data_type*>(pixels) + alpha_channel_index;
7672 for (uint32 yy = 0; yy < row_count; ++yy) {
7673 pixel_data_type* end = dst + unpadded_row_size_in_elements;
7674 for (pixel_data_type* d = dst; d < end; d += channel_count) {
7675 *d = alpha_value;
7677 dst += padded_row_size_in_elements;
7681 void GLES2DecoderImpl::FinishReadPixels(
7682 const cmds::ReadPixels& c,
7683 GLuint buffer) {
7684 TRACE_EVENT0("gpu", "GLES2DecoderImpl::FinishReadPixels");
7685 GLsizei width = c.width;
7686 GLsizei height = c.height;
7687 GLenum format = c.format;
7688 GLenum type = c.type;
7689 typedef cmds::ReadPixels::Result Result;
7690 uint32 pixels_size;
7691 Result* result = NULL;
7692 if (c.result_shm_id != 0) {
7693 result = GetSharedMemoryAs<Result*>(
7694 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7695 if (!result) {
7696 if (buffer != 0) {
7697 glDeleteBuffersARB(1, &buffer);
7699 return;
7702 GLES2Util::ComputeImageDataSizes(
7703 width, height, 1, format, type, state_.pack_alignment, &pixels_size,
7704 NULL, NULL);
7705 void* pixels = GetSharedMemoryAs<void*>(
7706 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
7707 if (!pixels) {
7708 if (buffer != 0) {
7709 glDeleteBuffersARB(1, &buffer);
7711 return;
7714 if (buffer != 0) {
7715 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
7716 void* data;
7717 if (features().map_buffer_range) {
7718 data = glMapBufferRange(
7719 GL_PIXEL_PACK_BUFFER_ARB, 0, pixels_size, GL_MAP_READ_BIT);
7720 } else {
7721 data = glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
7723 if (!data) {
7724 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glMapBuffer",
7725 "Unable to map memory for readback.");
7726 return;
7728 memcpy(pixels, data, pixels_size);
7729 // GL_PIXEL_PACK_BUFFER_ARB is currently unused, so we don't
7730 // have to restore the state.
7731 glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB);
7732 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
7733 glDeleteBuffersARB(1, &buffer);
7736 if (result != NULL) {
7737 *result = true;
7740 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
7741 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
7742 if ((channels_exist & 0x0008) == 0 &&
7743 workarounds().clear_alpha_in_readpixels) {
7744 // Set the alpha to 255 because some drivers are buggy in this regard.
7745 uint32 temp_size;
7747 uint32 unpadded_row_size;
7748 uint32 padded_row_size;
7749 if (!GLES2Util::ComputeImageDataSizes(
7750 width, 2, 1, format, type, state_.pack_alignment, &temp_size,
7751 &unpadded_row_size, &padded_row_size)) {
7752 return;
7755 uint32 channel_count = 0;
7756 uint32 alpha_channel = 0;
7757 switch (format) {
7758 case GL_RGBA:
7759 case GL_BGRA_EXT:
7760 channel_count = 4;
7761 alpha_channel = 3;
7762 break;
7763 case GL_ALPHA:
7764 channel_count = 1;
7765 alpha_channel = 0;
7766 break;
7769 if (channel_count > 0) {
7770 switch (type) {
7771 case GL_UNSIGNED_BYTE:
7772 WriteAlphaData<uint8>(
7773 pixels, height, channel_count, alpha_channel, unpadded_row_size,
7774 padded_row_size, 0xFF);
7775 break;
7776 case GL_FLOAT:
7777 WriteAlphaData<float>(
7778 pixels, height, channel_count, alpha_channel, unpadded_row_size,
7779 padded_row_size, 1.0f);
7780 break;
7781 case GL_HALF_FLOAT:
7782 WriteAlphaData<uint16>(
7783 pixels, height, channel_count, alpha_channel, unpadded_row_size,
7784 padded_row_size, 0x3C00);
7785 break;
7791 error::Error GLES2DecoderImpl::HandleReadPixels(uint32 immediate_data_size,
7792 const void* cmd_data) {
7793 const gles2::cmds::ReadPixels& c =
7794 *static_cast<const gles2::cmds::ReadPixels*>(cmd_data);
7795 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleReadPixels");
7796 error::Error fbo_error = WillAccessBoundFramebufferForRead();
7797 if (fbo_error != error::kNoError)
7798 return fbo_error;
7799 GLint x = c.x;
7800 GLint y = c.y;
7801 GLsizei width = c.width;
7802 GLsizei height = c.height;
7803 GLenum format = c.format;
7804 GLenum type = c.type;
7805 GLboolean async = static_cast<GLboolean>(c.async);
7806 if (width < 0 || height < 0) {
7807 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glReadPixels", "dimensions < 0");
7808 return error::kNoError;
7810 typedef cmds::ReadPixels::Result Result;
7811 uint32 pixels_size;
7812 if (!GLES2Util::ComputeImageDataSizes(
7813 width, height, 1, format, type, state_.pack_alignment, &pixels_size,
7814 NULL, NULL)) {
7815 return error::kOutOfBounds;
7817 void* pixels = GetSharedMemoryAs<void*>(
7818 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
7819 if (!pixels) {
7820 return error::kOutOfBounds;
7822 Result* result = NULL;
7823 if (c.result_shm_id != 0) {
7824 result = GetSharedMemoryAs<Result*>(
7825 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7826 if (!result) {
7827 return error::kOutOfBounds;
7831 if (!validators_->read_pixel_format.IsValid(format)) {
7832 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", format, "format");
7833 return error::kNoError;
7835 if (!validators_->read_pixel_type.IsValid(type)) {
7836 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", type, "type");
7837 return error::kNoError;
7839 if ((format != GL_RGBA && format != GL_BGRA_EXT && format != GL_RGB &&
7840 format != GL_ALPHA) || type != GL_UNSIGNED_BYTE) {
7841 // format and type are acceptable enums but not guaranteed to be supported
7842 // for this framebuffer. Have to ask gl if they are valid.
7843 GLint preferred_format = 0;
7844 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &preferred_format);
7845 GLint preferred_type = 0;
7846 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &preferred_type);
7847 if (format != static_cast<GLenum>(preferred_format) ||
7848 type != static_cast<GLenum>(preferred_type)) {
7849 LOCAL_SET_GL_ERROR(
7850 GL_INVALID_OPERATION, "glReadPixels", "format and type incompatible "
7851 "with the current read framebuffer");
7852 return error::kNoError;
7855 if (width == 0 || height == 0) {
7856 return error::kNoError;
7859 // Get the size of the current fbo or backbuffer.
7860 gfx::Size max_size = GetBoundReadFrameBufferSize();
7862 int32 max_x;
7863 int32 max_y;
7864 if (!SafeAddInt32(x, width, &max_x) || !SafeAddInt32(y, height, &max_y)) {
7865 LOCAL_SET_GL_ERROR(
7866 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
7867 return error::kNoError;
7870 if (!CheckBoundReadFramebufferColorAttachment("glReadPixels")) {
7871 return error::kNoError;
7874 if (!CheckBoundFramebuffersValid("glReadPixels")) {
7875 return error::kNoError;
7878 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixels");
7880 ScopedResolvedFrameBufferBinder binder(this, false, true);
7882 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
7883 // The user requested an out of range area. Get the results 1 line
7884 // at a time.
7885 uint32 temp_size;
7886 uint32 unpadded_row_size;
7887 uint32 padded_row_size;
7888 if (!GLES2Util::ComputeImageDataSizes(
7889 width, 2, 1, format, type, state_.pack_alignment, &temp_size,
7890 &unpadded_row_size, &padded_row_size)) {
7891 LOCAL_SET_GL_ERROR(
7892 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
7893 return error::kNoError;
7896 GLint dest_x_offset = std::max(-x, 0);
7897 uint32 dest_row_offset;
7898 if (!GLES2Util::ComputeImageDataSizes(
7899 dest_x_offset, 1, 1, format, type, state_.pack_alignment,
7900 &dest_row_offset, NULL, NULL)) {
7901 LOCAL_SET_GL_ERROR(
7902 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
7903 return error::kNoError;
7906 // Copy each row into the larger dest rect.
7907 int8* dst = static_cast<int8*>(pixels);
7908 GLint read_x = std::max(0, x);
7909 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
7910 GLint read_width = read_end_x - read_x;
7911 for (GLint yy = 0; yy < height; ++yy) {
7912 GLint ry = y + yy;
7914 // Clear the row.
7915 memset(dst, 0, unpadded_row_size);
7917 // If the row is in range, copy it.
7918 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
7919 glReadPixels(
7920 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
7922 dst += padded_row_size;
7924 } else {
7925 if (async && features().use_async_readpixels) {
7926 GLuint buffer = 0;
7927 glGenBuffersARB(1, &buffer);
7928 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
7929 // For ANGLE client version 2, GL_STREAM_READ is not available.
7930 const GLenum usage_hint = feature_info_->gl_version_info().is_angle ?
7931 GL_STATIC_DRAW : GL_STREAM_READ;
7932 glBufferData(GL_PIXEL_PACK_BUFFER_ARB, pixels_size, NULL, usage_hint);
7933 GLenum error = glGetError();
7934 if (error == GL_NO_ERROR) {
7935 glReadPixels(x, y, width, height, format, type, 0);
7936 pending_readpixel_fences_.push(linked_ptr<FenceCallback>(
7937 new FenceCallback()));
7938 WaitForReadPixels(base::Bind(
7939 &GLES2DecoderImpl::FinishReadPixels,
7940 base::internal::SupportsWeakPtrBase::StaticAsWeakPtr
7941 <GLES2DecoderImpl>(this),
7942 c, buffer));
7943 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
7944 return error::kNoError;
7945 } else {
7946 // On error, unbind pack buffer and fall through to sync readpixels
7947 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
7948 glDeleteBuffersARB(1, &buffer);
7951 glReadPixels(x, y, width, height, format, type, pixels);
7953 GLenum error = LOCAL_PEEK_GL_ERROR("glReadPixels");
7954 if (error == GL_NO_ERROR) {
7955 if (result != NULL) {
7956 *result = true;
7958 FinishReadPixels(c, 0);
7961 return error::kNoError;
7964 error::Error GLES2DecoderImpl::HandlePixelStorei(uint32 immediate_data_size,
7965 const void* cmd_data) {
7966 const gles2::cmds::PixelStorei& c =
7967 *static_cast<const gles2::cmds::PixelStorei*>(cmd_data);
7968 GLenum pname = c.pname;
7969 GLenum param = c.param;
7970 if (!validators_->pixel_store.IsValid(pname)) {
7971 LOCAL_SET_GL_ERROR_INVALID_ENUM("glPixelStorei", pname, "pname");
7972 return error::kNoError;
7974 switch (pname) {
7975 case GL_PACK_ALIGNMENT:
7976 case GL_UNPACK_ALIGNMENT:
7977 if (!validators_->pixel_store_alignment.IsValid(param)) {
7978 LOCAL_SET_GL_ERROR(
7979 GL_INVALID_VALUE, "glPixelStorei", "param GL_INVALID_VALUE");
7980 return error::kNoError;
7982 break;
7983 case GL_UNPACK_FLIP_Y_CHROMIUM:
7984 unpack_flip_y_ = (param != 0);
7985 return error::kNoError;
7986 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
7987 unpack_premultiply_alpha_ = (param != 0);
7988 return error::kNoError;
7989 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM:
7990 unpack_unpremultiply_alpha_ = (param != 0);
7991 return error::kNoError;
7992 default:
7993 break;
7995 glPixelStorei(pname, param);
7996 switch (pname) {
7997 case GL_PACK_ALIGNMENT:
7998 state_.pack_alignment = param;
7999 break;
8000 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
8001 state_.pack_reverse_row_order = (param != 0);
8002 break;
8003 case GL_UNPACK_ALIGNMENT:
8004 state_.unpack_alignment = param;
8005 break;
8006 default:
8007 // Validation should have prevented us from getting here.
8008 NOTREACHED();
8009 break;
8011 return error::kNoError;
8014 error::Error GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
8015 uint32 immediate_data_size,
8016 const void* cmd_data) {
8017 const gles2::cmds::PostSubBufferCHROMIUM& c =
8018 *static_cast<const gles2::cmds::PostSubBufferCHROMIUM*>(cmd_data);
8019 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
8021 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
8023 if (!supports_post_sub_buffer_) {
8024 LOCAL_SET_GL_ERROR(
8025 GL_INVALID_OPERATION,
8026 "glPostSubBufferCHROMIUM", "command not supported by surface");
8027 return error::kNoError;
8029 bool is_tracing;
8030 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
8031 &is_tracing);
8032 if (is_tracing) {
8033 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
8034 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
8035 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
8036 is_offscreen ? offscreen_size_ : surface_->GetSize());
8038 if (surface_->PostSubBuffer(c.x, c.y, c.width, c.height)) {
8039 return error::kNoError;
8040 } else {
8041 LOG(ERROR) << "Context lost because PostSubBuffer failed.";
8042 return error::kLostContext;
8046 error::Error GLES2DecoderImpl::HandleScheduleOverlayPlaneCHROMIUM(
8047 uint32 immediate_data_size,
8048 const void* cmd_data) {
8049 const gles2::cmds::ScheduleOverlayPlaneCHROMIUM& c =
8050 *static_cast<const gles2::cmds::ScheduleOverlayPlaneCHROMIUM*>(cmd_data);
8051 TextureRef* ref = texture_manager()->GetTexture(c.overlay_texture_id);
8052 if (!ref) {
8053 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
8054 "glScheduleOverlayPlaneCHROMIUM",
8055 "unknown texture");
8056 return error::kNoError;
8058 gfx::GLImage* image =
8059 ref->texture()->GetLevelImage(ref->texture()->target(), 0);
8060 if (!image) {
8061 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
8062 "glScheduleOverlayPlaneCHROMIUM",
8063 "unsupported texture format");
8064 return error::kNoError;
8066 gfx::OverlayTransform transform = GetGFXOverlayTransform(c.plane_transform);
8067 if (transform == gfx::OVERLAY_TRANSFORM_INVALID) {
8068 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM,
8069 "glScheduleOverlayPlaneCHROMIUM",
8070 "invalid transform enum");
8071 return error::kNoError;
8073 if (!surface_->ScheduleOverlayPlane(
8074 c.plane_z_order,
8075 transform,
8076 image,
8077 gfx::Rect(c.bounds_x, c.bounds_y, c.bounds_width, c.bounds_height),
8078 gfx::RectF(c.uv_x, c.uv_y, c.uv_width, c.uv_height))) {
8079 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
8080 "glScheduleOverlayPlaneCHROMIUM",
8081 "failed to schedule overlay");
8083 return error::kNoError;
8086 error::Error GLES2DecoderImpl::GetAttribLocationHelper(
8087 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
8088 const std::string& name_str) {
8089 if (!StringIsValidForGLES(name_str.c_str())) {
8090 LOCAL_SET_GL_ERROR(
8091 GL_INVALID_VALUE, "glGetAttribLocation", "Invalid character");
8092 return error::kNoError;
8094 Program* program = GetProgramInfoNotShader(
8095 client_id, "glGetAttribLocation");
8096 if (!program) {
8097 return error::kNoError;
8099 if (!program->IsValid()) {
8100 LOCAL_SET_GL_ERROR(
8101 GL_INVALID_OPERATION, "glGetAttribLocation", "program not linked");
8102 return error::kNoError;
8104 GLint* location = GetSharedMemoryAs<GLint*>(
8105 location_shm_id, location_shm_offset, sizeof(GLint));
8106 if (!location) {
8107 return error::kOutOfBounds;
8109 // Require the client to init this incase the context is lost and we are no
8110 // longer executing commands.
8111 if (*location != -1) {
8112 return error::kGenericError;
8114 *location = program->GetAttribLocation(name_str);
8115 return error::kNoError;
8118 error::Error GLES2DecoderImpl::HandleGetAttribLocation(
8119 uint32 immediate_data_size,
8120 const void* cmd_data) {
8121 const gles2::cmds::GetAttribLocation& c =
8122 *static_cast<const gles2::cmds::GetAttribLocation*>(cmd_data);
8123 Bucket* bucket = GetBucket(c.name_bucket_id);
8124 if (!bucket) {
8125 return error::kInvalidArguments;
8127 std::string name_str;
8128 if (!bucket->GetAsString(&name_str)) {
8129 return error::kInvalidArguments;
8131 return GetAttribLocationHelper(
8132 c.program, c.location_shm_id, c.location_shm_offset, name_str);
8135 error::Error GLES2DecoderImpl::GetUniformLocationHelper(
8136 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
8137 const std::string& name_str) {
8138 if (!StringIsValidForGLES(name_str.c_str())) {
8139 LOCAL_SET_GL_ERROR(
8140 GL_INVALID_VALUE, "glGetUniformLocation", "Invalid character");
8141 return error::kNoError;
8143 Program* program = GetProgramInfoNotShader(
8144 client_id, "glGetUniformLocation");
8145 if (!program) {
8146 return error::kNoError;
8148 if (!program->IsValid()) {
8149 LOCAL_SET_GL_ERROR(
8150 GL_INVALID_OPERATION, "glGetUniformLocation", "program not linked");
8151 return error::kNoError;
8153 GLint* location = GetSharedMemoryAs<GLint*>(
8154 location_shm_id, location_shm_offset, sizeof(GLint));
8155 if (!location) {
8156 return error::kOutOfBounds;
8158 // Require the client to init this incase the context is lost an we are no
8159 // longer executing commands.
8160 if (*location != -1) {
8161 return error::kGenericError;
8163 *location = program->GetUniformFakeLocation(name_str);
8164 return error::kNoError;
8167 error::Error GLES2DecoderImpl::HandleGetUniformLocation(
8168 uint32 immediate_data_size,
8169 const void* cmd_data) {
8170 const gles2::cmds::GetUniformLocation& c =
8171 *static_cast<const gles2::cmds::GetUniformLocation*>(cmd_data);
8172 Bucket* bucket = GetBucket(c.name_bucket_id);
8173 if (!bucket) {
8174 return error::kInvalidArguments;
8176 std::string name_str;
8177 if (!bucket->GetAsString(&name_str)) {
8178 return error::kInvalidArguments;
8180 return GetUniformLocationHelper(
8181 c.program, c.location_shm_id, c.location_shm_offset, name_str);
8184 error::Error GLES2DecoderImpl::HandleGetUniformIndices(
8185 uint32 immediate_data_size,
8186 const void* cmd_data) {
8187 if (!unsafe_es3_apis_enabled())
8188 return error::kUnknownCommand;
8189 const gles2::cmds::GetUniformIndices& c =
8190 *static_cast<const gles2::cmds::GetUniformIndices*>(cmd_data);
8191 Bucket* bucket = GetBucket(c.names_bucket_id);
8192 if (!bucket) {
8193 return error::kInvalidArguments;
8195 GLsizei count = 0;
8196 std::vector<char*> names;
8197 std::vector<GLint> len;
8198 if (!bucket->GetAsStrings(&count, &names, &len) || count <= 0) {
8199 return error::kInvalidArguments;
8201 typedef cmds::GetUniformIndices::Result Result;
8202 Result* result = GetSharedMemoryAs<Result*>(
8203 c.indices_shm_id, c.indices_shm_offset,
8204 Result::ComputeSize(static_cast<size_t>(count)));
8205 GLuint* indices = result ? result->GetData() : NULL;
8206 if (indices == NULL) {
8207 return error::kOutOfBounds;
8209 // Check that the client initialized the result.
8210 if (result->size != 0) {
8211 return error::kInvalidArguments;
8213 Program* program = GetProgramInfoNotShader(c.program, "glGetUniformIndices");
8214 if (!program) {
8215 return error::kNoError;
8217 GLuint service_id = program->service_id();
8218 GLint link_status = GL_FALSE;
8219 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
8220 if (link_status != GL_TRUE) {
8221 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
8222 "glGetUniformIndices", "program not linked");
8223 return error::kNoError;
8225 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetUniformIndices");
8226 glGetUniformIndices(service_id, count, &names[0], indices);
8227 GLenum error = glGetError();
8228 if (error == GL_NO_ERROR) {
8229 result->SetNumResults(count);
8230 } else {
8231 LOCAL_SET_GL_ERROR(error, "GetUniformIndices", "");
8233 return error::kNoError;
8236 error::Error GLES2DecoderImpl::GetFragDataLocationHelper(
8237 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
8238 const std::string& name_str) {
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 Program* program = GetProgramInfoNotShader(
8250 client_id, "glGetFragDataLocation");
8251 if (!program) {
8252 return error::kNoError;
8254 *location = glGetFragDataLocation(program->service_id(), name_str.c_str());
8255 return error::kNoError;
8258 error::Error GLES2DecoderImpl::HandleGetFragDataLocation(
8259 uint32 immediate_data_size,
8260 const void* cmd_data) {
8261 if (!unsafe_es3_apis_enabled())
8262 return error::kUnknownCommand;
8263 const gles2::cmds::GetFragDataLocation& c =
8264 *static_cast<const gles2::cmds::GetFragDataLocation*>(cmd_data);
8265 Bucket* bucket = GetBucket(c.name_bucket_id);
8266 if (!bucket) {
8267 return error::kInvalidArguments;
8269 std::string name_str;
8270 if (!bucket->GetAsString(&name_str)) {
8271 return error::kInvalidArguments;
8273 return GetFragDataLocationHelper(
8274 c.program, c.location_shm_id, c.location_shm_offset, name_str);
8277 error::Error GLES2DecoderImpl::HandleGetUniformBlockIndex(
8278 uint32 immediate_data_size, const void* cmd_data) {
8279 if (!unsafe_es3_apis_enabled())
8280 return error::kUnknownCommand;
8281 const gles2::cmds::GetUniformBlockIndex& c =
8282 *static_cast<const gles2::cmds::GetUniformBlockIndex*>(cmd_data);
8283 Bucket* bucket = GetBucket(c.name_bucket_id);
8284 if (!bucket) {
8285 return error::kInvalidArguments;
8287 std::string name_str;
8288 if (!bucket->GetAsString(&name_str)) {
8289 return error::kInvalidArguments;
8291 GLuint* index = GetSharedMemoryAs<GLuint*>(
8292 c.index_shm_id, c.index_shm_offset, sizeof(GLuint));
8293 if (!index) {
8294 return error::kOutOfBounds;
8296 // Require the client to init this in case the context is lost and we are no
8297 // longer executing commands.
8298 if (*index != GL_INVALID_INDEX) {
8299 return error::kGenericError;
8301 Program* program = GetProgramInfoNotShader(
8302 c.program, "glGetUniformBlockIndex");
8303 if (!program) {
8304 return error::kNoError;
8306 *index = glGetUniformBlockIndex(program->service_id(), name_str.c_str());
8307 return error::kNoError;
8310 error::Error GLES2DecoderImpl::HandleGetString(uint32 immediate_data_size,
8311 const void* cmd_data) {
8312 const gles2::cmds::GetString& c =
8313 *static_cast<const gles2::cmds::GetString*>(cmd_data);
8314 GLenum name = static_cast<GLenum>(c.name);
8315 if (!validators_->string_type.IsValid(name)) {
8316 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetString", name, "name");
8317 return error::kNoError;
8319 const char* str = reinterpret_cast<const char*>(glGetString(name));
8320 std::string extensions;
8321 switch (name) {
8322 case GL_VERSION:
8323 str = "OpenGL ES 2.0 Chromium";
8324 break;
8325 case GL_SHADING_LANGUAGE_VERSION:
8326 str = "OpenGL ES GLSL ES 1.0 Chromium";
8327 break;
8328 case GL_RENDERER:
8329 case GL_VENDOR:
8330 // Return the unmasked VENDOR/RENDERER string for WebGL contexts.
8331 // They are used by WEBGL_debug_renderer_info.
8332 if (!force_webgl_glsl_validation_)
8333 str = "Chromium";
8334 break;
8335 case GL_EXTENSIONS:
8337 // For WebGL contexts, strip out the OES derivatives and
8338 // EXT frag depth extensions if they have not been enabled.
8339 if (force_webgl_glsl_validation_) {
8340 extensions = feature_info_->extensions();
8341 if (!derivatives_explicitly_enabled_) {
8342 size_t offset = extensions.find(kOESDerivativeExtension);
8343 if (std::string::npos != offset) {
8344 extensions.replace(offset, arraysize(kOESDerivativeExtension),
8345 std::string());
8348 if (!frag_depth_explicitly_enabled_) {
8349 size_t offset = extensions.find(kEXTFragDepthExtension);
8350 if (std::string::npos != offset) {
8351 extensions.replace(offset, arraysize(kEXTFragDepthExtension),
8352 std::string());
8355 if (!draw_buffers_explicitly_enabled_) {
8356 size_t offset = extensions.find(kEXTDrawBuffersExtension);
8357 if (std::string::npos != offset) {
8358 extensions.replace(offset, arraysize(kEXTDrawBuffersExtension),
8359 std::string());
8362 if (!shader_texture_lod_explicitly_enabled_) {
8363 size_t offset = extensions.find(kEXTShaderTextureLodExtension);
8364 if (std::string::npos != offset) {
8365 extensions.replace(offset,
8366 arraysize(kEXTShaderTextureLodExtension),
8367 std::string());
8370 } else {
8371 extensions = feature_info_->extensions().c_str();
8373 if (supports_post_sub_buffer_)
8374 extensions += " GL_CHROMIUM_post_sub_buffer";
8375 str = extensions.c_str();
8377 break;
8378 default:
8379 break;
8381 Bucket* bucket = CreateBucket(c.bucket_id);
8382 bucket->SetFromString(str);
8383 return error::kNoError;
8386 error::Error GLES2DecoderImpl::HandleBufferData(uint32 immediate_data_size,
8387 const void* cmd_data) {
8388 const gles2::cmds::BufferData& c =
8389 *static_cast<const gles2::cmds::BufferData*>(cmd_data);
8390 GLenum target = static_cast<GLenum>(c.target);
8391 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
8392 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
8393 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
8394 GLenum usage = static_cast<GLenum>(c.usage);
8395 const void* data = NULL;
8396 if (data_shm_id != 0 || data_shm_offset != 0) {
8397 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
8398 if (!data) {
8399 return error::kOutOfBounds;
8402 buffer_manager()->ValidateAndDoBufferData(&state_, target, size, data, usage);
8403 return error::kNoError;
8406 void GLES2DecoderImpl::DoBufferSubData(
8407 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
8408 // Just delegate it. Some validation is actually done before this.
8409 buffer_manager()->ValidateAndDoBufferSubData(
8410 &state_, target, offset, size, data);
8413 bool GLES2DecoderImpl::ClearLevel(
8414 Texture* texture,
8415 unsigned target,
8416 int level,
8417 unsigned internal_format,
8418 unsigned format,
8419 unsigned type,
8420 int width,
8421 int height,
8422 bool is_texture_immutable) {
8423 uint32 channels = GLES2Util::GetChannelsForFormat(format);
8424 if (feature_info_->feature_flags().angle_depth_texture &&
8425 (channels & GLES2Util::kDepth) != 0) {
8426 // It's a depth format and ANGLE doesn't allow texImage2D or texSubImage2D
8427 // on depth formats.
8428 GLuint fb = 0;
8429 glGenFramebuffersEXT(1, &fb);
8430 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb);
8432 bool have_stencil = (channels & GLES2Util::kStencil) != 0;
8433 GLenum attachment = have_stencil ? GL_DEPTH_STENCIL_ATTACHMENT :
8434 GL_DEPTH_ATTACHMENT;
8436 glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, attachment, target,
8437 texture->service_id(), level);
8438 // ANGLE promises a depth only attachment ok.
8439 if (glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT) !=
8440 GL_FRAMEBUFFER_COMPLETE) {
8441 return false;
8443 glClearStencil(0);
8444 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
8445 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
8446 glClearDepth(1.0f);
8447 state_.SetDeviceDepthMask(GL_TRUE);
8448 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
8449 glClear(GL_DEPTH_BUFFER_BIT | (have_stencil ? GL_STENCIL_BUFFER_BIT : 0));
8451 RestoreClearState();
8453 glDeleteFramebuffersEXT(1, &fb);
8454 Framebuffer* framebuffer =
8455 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
8456 GLuint fb_service_id =
8457 framebuffer ? framebuffer->service_id() : GetBackbufferServiceId();
8458 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb_service_id);
8459 return true;
8462 static const uint32 kMaxZeroSize = 1024 * 1024 * 4;
8464 uint32 size;
8465 uint32 padded_row_size;
8466 if (!GLES2Util::ComputeImageDataSizes(
8467 width, height, 1, format, type, state_.unpack_alignment, &size,
8468 NULL, &padded_row_size)) {
8469 return false;
8472 TRACE_EVENT1("gpu", "GLES2DecoderImpl::ClearLevel", "size", size);
8474 int tile_height;
8476 if (size > kMaxZeroSize) {
8477 if (kMaxZeroSize < padded_row_size) {
8478 // That'd be an awfully large texture.
8479 return false;
8481 // We should never have a large total size with a zero row size.
8482 DCHECK_GT(padded_row_size, 0U);
8483 tile_height = kMaxZeroSize / padded_row_size;
8484 if (!GLES2Util::ComputeImageDataSizes(
8485 width, tile_height, 1, format, type, state_.unpack_alignment, &size,
8486 NULL, NULL)) {
8487 return false;
8489 } else {
8490 tile_height = height;
8493 // Assumes the size has already been checked.
8494 scoped_ptr<char[]> zero(new char[size]);
8495 memset(zero.get(), 0, size);
8496 glBindTexture(texture->target(), texture->service_id());
8498 bool has_images = texture->HasImages();
8499 GLint y = 0;
8500 while (y < height) {
8501 GLint h = y + tile_height > height ? height - y : tile_height;
8502 if (is_texture_immutable || h != height || has_images) {
8503 glTexSubImage2D(target, level, 0, y, width, h, format, type, zero.get());
8504 } else {
8505 glTexImage2D(
8506 target, level, internal_format, width, h, 0, format, type,
8507 zero.get());
8509 y += tile_height;
8511 TextureRef* bound_texture =
8512 texture_manager()->GetTextureInfoForTarget(&state_, texture->target());
8513 glBindTexture(texture->target(),
8514 bound_texture ? bound_texture->service_id() : 0);
8515 return true;
8518 namespace {
8520 const int kS3TCBlockWidth = 4;
8521 const int kS3TCBlockHeight = 4;
8522 const int kS3TCDXT1BlockSize = 8;
8523 const int kS3TCDXT3AndDXT5BlockSize = 16;
8525 bool IsValidDXTSize(GLint level, GLsizei size) {
8526 return (size == 1) ||
8527 (size == 2) || !(size % kS3TCBlockWidth);
8530 bool IsValidPVRTCSize(GLint level, GLsizei size) {
8531 return GLES2Util::IsPOT(size);
8534 } // anonymous namespace.
8536 bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
8537 const char* function_name,
8538 GLsizei width, GLsizei height, GLenum format, size_t size) {
8539 unsigned int bytes_required = 0;
8541 switch (format) {
8542 case GL_ATC_RGB_AMD:
8543 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
8544 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
8545 case GL_ETC1_RGB8_OES: {
8546 int num_blocks_across =
8547 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
8548 int num_blocks_down =
8549 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
8550 int num_blocks = num_blocks_across * num_blocks_down;
8551 bytes_required = num_blocks * kS3TCDXT1BlockSize;
8552 break;
8554 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
8555 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
8556 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
8557 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
8558 int num_blocks_across =
8559 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
8560 int num_blocks_down =
8561 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
8562 int num_blocks = num_blocks_across * num_blocks_down;
8563 bytes_required = num_blocks * kS3TCDXT3AndDXT5BlockSize;
8564 break;
8566 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
8567 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG: {
8568 bytes_required = (std::max(width, 8) * std::max(height, 8) * 4 + 7)/8;
8569 break;
8571 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
8572 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
8573 bytes_required = (std::max(width, 16) * std::max(height, 8) * 2 + 7)/8;
8574 break;
8576 default:
8577 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, format, "format");
8578 return false;
8581 if (size != bytes_required) {
8582 LOCAL_SET_GL_ERROR(
8583 GL_INVALID_VALUE, function_name, "size is not correct for dimensions");
8584 return false;
8587 return true;
8590 bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
8591 const char* function_name,
8592 GLint level, GLsizei width, GLsizei height, GLenum format) {
8593 switch (format) {
8594 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
8595 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
8596 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
8597 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
8598 if (!IsValidDXTSize(level, width) || !IsValidDXTSize(level, height)) {
8599 LOCAL_SET_GL_ERROR(
8600 GL_INVALID_OPERATION, function_name,
8601 "width or height invalid for level");
8602 return false;
8604 return true;
8606 case GL_ATC_RGB_AMD:
8607 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
8608 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
8609 case GL_ETC1_RGB8_OES: {
8610 if (width <= 0 || height <= 0) {
8611 LOCAL_SET_GL_ERROR(
8612 GL_INVALID_OPERATION, function_name,
8613 "width or height invalid for level");
8614 return false;
8616 return true;
8618 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
8619 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
8620 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
8621 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
8622 if (!IsValidPVRTCSize(level, width) ||
8623 !IsValidPVRTCSize(level, height)) {
8624 LOCAL_SET_GL_ERROR(
8625 GL_INVALID_OPERATION, function_name,
8626 "width or height invalid for level");
8627 return false;
8629 return true;
8631 default:
8632 return false;
8636 bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
8637 const char* function_name,
8638 GLenum target, GLint level, GLint xoffset, GLint yoffset,
8639 GLsizei width, GLsizei height, GLenum format,
8640 Texture* texture) {
8641 if (xoffset < 0 || yoffset < 0) {
8642 LOCAL_SET_GL_ERROR(
8643 GL_INVALID_VALUE, function_name, "xoffset or yoffset < 0");
8644 return false;
8647 switch (format) {
8648 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
8649 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
8650 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
8651 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
8652 const int kBlockWidth = 4;
8653 const int kBlockHeight = 4;
8654 if ((xoffset % kBlockWidth) || (yoffset % kBlockHeight)) {
8655 LOCAL_SET_GL_ERROR(
8656 GL_INVALID_OPERATION, function_name,
8657 "xoffset or yoffset not multiple of 4");
8658 return false;
8660 GLsizei tex_width = 0;
8661 GLsizei tex_height = 0;
8662 if (!texture->GetLevelSize(target, level, &tex_width, &tex_height) ||
8663 width - xoffset > tex_width ||
8664 height - yoffset > tex_height) {
8665 LOCAL_SET_GL_ERROR(
8666 GL_INVALID_OPERATION, function_name, "dimensions out of range");
8667 return false;
8669 return ValidateCompressedTexDimensions(
8670 function_name, level, width, height, format);
8672 case GL_ATC_RGB_AMD:
8673 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
8674 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD: {
8675 LOCAL_SET_GL_ERROR(
8676 GL_INVALID_OPERATION, function_name,
8677 "not supported for ATC textures");
8678 return false;
8680 case GL_ETC1_RGB8_OES: {
8681 LOCAL_SET_GL_ERROR(
8682 GL_INVALID_OPERATION, function_name,
8683 "not supported for ECT1_RGB8_OES textures");
8684 return false;
8686 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
8687 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
8688 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
8689 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
8690 if ((xoffset != 0) || (yoffset != 0)) {
8691 LOCAL_SET_GL_ERROR(
8692 GL_INVALID_OPERATION, function_name,
8693 "xoffset and yoffset must be zero");
8694 return false;
8696 GLsizei tex_width = 0;
8697 GLsizei tex_height = 0;
8698 if (!texture->GetLevelSize(target, level, &tex_width, &tex_height) ||
8699 width != tex_width ||
8700 height != tex_height) {
8701 LOCAL_SET_GL_ERROR(
8702 GL_INVALID_OPERATION, function_name,
8703 "dimensions must match existing texture level dimensions");
8704 return false;
8706 return ValidateCompressedTexDimensions(
8707 function_name, level, width, height, format);
8709 default:
8710 return false;
8714 error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
8715 GLenum target,
8716 GLint level,
8717 GLenum internal_format,
8718 GLsizei width,
8719 GLsizei height,
8720 GLint border,
8721 GLsizei image_size,
8722 const void* data) {
8723 // TODO(gman): Validate image_size is correct for width, height and format.
8724 if (!validators_->texture_target.IsValid(target)) {
8725 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8726 "glCompressedTexImage2D", target, "target");
8727 return error::kNoError;
8729 if (!validators_->compressed_texture_format.IsValid(
8730 internal_format)) {
8731 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8732 "glCompressedTexImage2D", internal_format, "internal_format");
8733 return error::kNoError;
8735 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
8736 border != 0) {
8737 LOCAL_SET_GL_ERROR(
8738 GL_INVALID_VALUE,
8739 "glCompressedTexImage2D", "dimensions out of range");
8740 return error::kNoError;
8742 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8743 &state_, target);
8744 if (!texture_ref) {
8745 LOCAL_SET_GL_ERROR(
8746 GL_INVALID_VALUE,
8747 "glCompressedTexImage2D", "unknown texture target");
8748 return error::kNoError;
8750 Texture* texture = texture_ref->texture();
8751 if (texture->IsImmutable()) {
8752 LOCAL_SET_GL_ERROR(
8753 GL_INVALID_OPERATION,
8754 "glCompressedTexImage2D", "texture is immutable");
8755 return error::kNoError;
8758 if (!ValidateCompressedTexDimensions(
8759 "glCompressedTexImage2D", level, width, height, internal_format) ||
8760 !ValidateCompressedTexFuncData(
8761 "glCompressedTexImage2D", width, height, internal_format, image_size)) {
8762 return error::kNoError;
8765 if (!EnsureGPUMemoryAvailable(image_size)) {
8766 LOCAL_SET_GL_ERROR(
8767 GL_OUT_OF_MEMORY, "glCompressedTexImage2D", "out of memory");
8768 return error::kNoError;
8771 if (texture->IsAttachedToFramebuffer()) {
8772 framebuffer_state_.clear_state_dirty = true;
8775 scoped_ptr<int8[]> zero;
8776 if (!data) {
8777 zero.reset(new int8[image_size]);
8778 memset(zero.get(), 0, image_size);
8779 data = zero.get();
8781 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage2D");
8782 glCompressedTexImage2D(
8783 target, level, internal_format, width, height, border, image_size, data);
8784 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedTexImage2D");
8785 if (error == GL_NO_ERROR) {
8786 texture_manager()->SetLevelInfo(
8787 texture_ref, target, level, internal_format,
8788 width, height, 1, border, 0, 0, true);
8791 // This may be a slow command. Exit command processing to allow for
8792 // context preemption and GPU watchdog checks.
8793 ExitCommandProcessingEarly();
8794 return error::kNoError;
8797 error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
8798 uint32 immediate_data_size,
8799 const void* cmd_data) {
8800 const gles2::cmds::CompressedTexImage2D& c =
8801 *static_cast<const gles2::cmds::CompressedTexImage2D*>(cmd_data);
8802 GLenum target = static_cast<GLenum>(c.target);
8803 GLint level = static_cast<GLint>(c.level);
8804 GLenum internal_format = static_cast<GLenum>(c.internalformat);
8805 GLsizei width = static_cast<GLsizei>(c.width);
8806 GLsizei height = static_cast<GLsizei>(c.height);
8807 GLint border = static_cast<GLint>(c.border);
8808 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
8809 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
8810 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
8811 const void* data = NULL;
8812 if (data_shm_id != 0 || data_shm_offset != 0) {
8813 data = GetSharedMemoryAs<const void*>(
8814 data_shm_id, data_shm_offset, image_size);
8815 if (!data) {
8816 return error::kOutOfBounds;
8819 return DoCompressedTexImage2D(
8820 target, level, internal_format, width, height, border, image_size, data);
8823 error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
8824 uint32 immediate_data_size,
8825 const void* cmd_data) {
8826 const gles2::cmds::CompressedTexImage2DBucket& c =
8827 *static_cast<const gles2::cmds::CompressedTexImage2DBucket*>(cmd_data);
8828 GLenum target = static_cast<GLenum>(c.target);
8829 GLint level = static_cast<GLint>(c.level);
8830 GLenum internal_format = static_cast<GLenum>(c.internalformat);
8831 GLsizei width = static_cast<GLsizei>(c.width);
8832 GLsizei height = static_cast<GLsizei>(c.height);
8833 GLint border = static_cast<GLint>(c.border);
8834 Bucket* bucket = GetBucket(c.bucket_id);
8835 if (!bucket) {
8836 return error::kInvalidArguments;
8838 uint32 data_size = bucket->size();
8839 GLsizei imageSize = data_size;
8840 const void* data = bucket->GetData(0, data_size);
8841 if (!data) {
8842 return error::kInvalidArguments;
8844 return DoCompressedTexImage2D(
8845 target, level, internal_format, width, height, border,
8846 imageSize, data);
8849 error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
8850 uint32 immediate_data_size,
8851 const void* cmd_data) {
8852 const gles2::cmds::CompressedTexSubImage2DBucket& c =
8853 *static_cast<const gles2::cmds::CompressedTexSubImage2DBucket*>(cmd_data);
8854 GLenum target = static_cast<GLenum>(c.target);
8855 GLint level = static_cast<GLint>(c.level);
8856 GLint xoffset = static_cast<GLint>(c.xoffset);
8857 GLint yoffset = static_cast<GLint>(c.yoffset);
8858 GLsizei width = static_cast<GLsizei>(c.width);
8859 GLsizei height = static_cast<GLsizei>(c.height);
8860 GLenum format = static_cast<GLenum>(c.format);
8861 Bucket* bucket = GetBucket(c.bucket_id);
8862 if (!bucket) {
8863 return error::kInvalidArguments;
8865 uint32 data_size = bucket->size();
8866 GLsizei imageSize = data_size;
8867 const void* data = bucket->GetData(0, data_size);
8868 if (!data) {
8869 return error::kInvalidArguments;
8871 if (!validators_->texture_target.IsValid(target)) {
8872 LOCAL_SET_GL_ERROR(
8873 GL_INVALID_ENUM, "glCompressedTexSubImage2D", "target");
8874 return error::kNoError;
8876 if (!validators_->compressed_texture_format.IsValid(format)) {
8877 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8878 "glCompressedTexSubImage2D", format, "format");
8879 return error::kNoError;
8881 if (width < 0) {
8882 LOCAL_SET_GL_ERROR(
8883 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "width < 0");
8884 return error::kNoError;
8886 if (height < 0) {
8887 LOCAL_SET_GL_ERROR(
8888 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "height < 0");
8889 return error::kNoError;
8891 if (imageSize < 0) {
8892 LOCAL_SET_GL_ERROR(
8893 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "imageSize < 0");
8894 return error::kNoError;
8896 DoCompressedTexSubImage2D(
8897 target, level, xoffset, yoffset, width, height, format, imageSize, data);
8898 return error::kNoError;
8901 error::Error GLES2DecoderImpl::HandleTexImage2D(uint32 immediate_data_size,
8902 const void* cmd_data) {
8903 const gles2::cmds::TexImage2D& c =
8904 *static_cast<const gles2::cmds::TexImage2D*>(cmd_data);
8905 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage2D",
8906 "width", c.width, "height", c.height);
8907 // Set as failed for now, but if it successed, this will be set to not failed.
8908 texture_state_.tex_image_2d_failed = true;
8909 GLenum target = static_cast<GLenum>(c.target);
8910 GLint level = static_cast<GLint>(c.level);
8911 // TODO(kloveless): Change TexImage2D command to use unsigned integer
8912 // for internalformat.
8913 GLenum internal_format = static_cast<GLenum>(c.internalformat);
8914 GLsizei width = static_cast<GLsizei>(c.width);
8915 GLsizei height = static_cast<GLsizei>(c.height);
8916 GLint border = static_cast<GLint>(c.border);
8917 GLenum format = static_cast<GLenum>(c.format);
8918 GLenum type = static_cast<GLenum>(c.type);
8919 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
8920 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
8921 uint32 pixels_size;
8922 if (!GLES2Util::ComputeImageDataSizes(
8923 width, height, 1, format, type, state_.unpack_alignment, &pixels_size,
8924 NULL, NULL)) {
8925 return error::kOutOfBounds;
8927 const void* pixels = NULL;
8928 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
8929 pixels = GetSharedMemoryAs<const void*>(
8930 pixels_shm_id, pixels_shm_offset, pixels_size);
8931 if (!pixels) {
8932 return error::kOutOfBounds;
8936 TextureManager::DoTextImage2DArguments args = {
8937 target, level, internal_format, width, height, border, format, type,
8938 pixels, pixels_size};
8939 texture_manager()->ValidateAndDoTexImage2D(
8940 &texture_state_, &state_, &framebuffer_state_, args);
8942 // This may be a slow command. Exit command processing to allow for
8943 // context preemption and GPU watchdog checks.
8944 ExitCommandProcessingEarly();
8945 return error::kNoError;
8948 error::Error GLES2DecoderImpl::HandleTexImage3D(uint32 immediate_data_size,
8949 const void* cmd_data) {
8950 // TODO(zmo): Unsafe ES3 API.
8951 if (!unsafe_es3_apis_enabled())
8952 return error::kUnknownCommand;
8954 const gles2::cmds::TexImage3D& c =
8955 *static_cast<const gles2::cmds::TexImage3D*>(cmd_data);
8956 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage3D",
8957 "widthXheight", c.width * c.height, "depth", c.depth);
8958 GLenum target = static_cast<GLenum>(c.target);
8959 GLint level = static_cast<GLint>(c.level);
8960 GLenum internal_format = static_cast<GLenum>(c.internalformat);
8961 GLsizei width = static_cast<GLsizei>(c.width);
8962 GLsizei height = static_cast<GLsizei>(c.height);
8963 GLsizei depth = static_cast<GLsizei>(c.depth);
8964 GLint border = static_cast<GLint>(c.border);
8965 GLenum format = static_cast<GLenum>(c.format);
8966 GLenum type = static_cast<GLenum>(c.type);
8967 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
8968 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
8969 uint32 pixels_size;
8970 if (!GLES2Util::ComputeImageDataSizes(
8971 width, height, depth, format, type, state_.unpack_alignment, &pixels_size,
8972 NULL, NULL)) {
8973 return error::kOutOfBounds;
8975 const void* pixels = NULL;
8976 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
8977 pixels = GetSharedMemoryAs<const void*>(
8978 pixels_shm_id, pixels_shm_offset, pixels_size);
8979 if (!pixels) {
8980 return error::kOutOfBounds;
8984 glTexImage3D(target, level, internal_format, width, height, depth, border,
8985 format, type, pixels);
8987 // This may be a slow command. Exit command processing to allow for
8988 // context preemption and GPU watchdog checks.
8989 ExitCommandProcessingEarly();
8990 return error::kNoError;
8993 void GLES2DecoderImpl::DoCompressedTexSubImage2D(
8994 GLenum target,
8995 GLint level,
8996 GLint xoffset,
8997 GLint yoffset,
8998 GLsizei width,
8999 GLsizei height,
9000 GLenum format,
9001 GLsizei image_size,
9002 const void * data) {
9003 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9004 &state_, target);
9005 if (!texture_ref) {
9006 LOCAL_SET_GL_ERROR(
9007 GL_INVALID_OPERATION,
9008 "glCompressedTexSubImage2D", "unknown texture for target");
9009 return;
9011 Texture* texture = texture_ref->texture();
9012 GLenum type = 0;
9013 GLenum internal_format = 0;
9014 if (!texture->GetLevelType(target, level, &type, &internal_format)) {
9015 LOCAL_SET_GL_ERROR(
9016 GL_INVALID_OPERATION,
9017 "glCompressedTexSubImage2D", "level does not exist.");
9018 return;
9020 if (internal_format != format) {
9021 LOCAL_SET_GL_ERROR(
9022 GL_INVALID_OPERATION,
9023 "glCompressedTexSubImage2D", "format does not match internal format.");
9024 return;
9026 if (!texture->ValidForTexture(
9027 target, level, xoffset, yoffset, width, height, type)) {
9028 LOCAL_SET_GL_ERROR(
9029 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "bad dimensions.");
9030 return;
9033 if (!ValidateCompressedTexFuncData(
9034 "glCompressedTexSubImage2D", width, height, format, image_size) ||
9035 !ValidateCompressedTexSubDimensions(
9036 "glCompressedTexSubImage2D",
9037 target, level, xoffset, yoffset, width, height, format, texture)) {
9038 return;
9042 // Note: There is no need to deal with texture cleared tracking here
9043 // because the validation above means you can only get here if the level
9044 // is already a matching compressed format and in that case
9045 // CompressedTexImage2D already cleared the texture.
9046 glCompressedTexSubImage2D(
9047 target, level, xoffset, yoffset, width, height, format, image_size, data);
9049 // This may be a slow command. Exit command processing to allow for
9050 // context preemption and GPU watchdog checks.
9051 ExitCommandProcessingEarly();
9054 static void Clip(
9055 GLint start, GLint range, GLint sourceRange,
9056 GLint* out_start, GLint* out_range) {
9057 DCHECK(out_start);
9058 DCHECK(out_range);
9059 if (start < 0) {
9060 range += start;
9061 start = 0;
9063 GLint end = start + range;
9064 if (end > sourceRange) {
9065 range -= end - sourceRange;
9067 *out_start = start;
9068 *out_range = range;
9071 void GLES2DecoderImpl::DoCopyTexImage2D(
9072 GLenum target,
9073 GLint level,
9074 GLenum internal_format,
9075 GLint x,
9076 GLint y,
9077 GLsizei width,
9078 GLsizei height,
9079 GLint border) {
9080 DCHECK(!ShouldDeferReads());
9081 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9082 &state_, target);
9083 if (!texture_ref) {
9084 LOCAL_SET_GL_ERROR(
9085 GL_INVALID_OPERATION,
9086 "glCopyTexImage2D", "unknown texture for target");
9087 return;
9089 Texture* texture = texture_ref->texture();
9090 if (texture->IsImmutable()) {
9091 LOCAL_SET_GL_ERROR(
9092 GL_INVALID_OPERATION, "glCopyTexImage2D", "texture is immutable");
9093 return;
9095 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
9096 border != 0) {
9097 LOCAL_SET_GL_ERROR(
9098 GL_INVALID_VALUE, "glCopyTexImage2D", "dimensions out of range");
9099 return;
9101 if (!texture_manager()->ValidateFormatAndTypeCombination(
9102 state_.GetErrorState(), "glCopyTexImage2D", internal_format,
9103 GL_UNSIGNED_BYTE)) {
9104 return;
9107 // Check we have compatible formats.
9108 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
9109 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
9110 uint32 channels_needed = GLES2Util::GetChannelsForFormat(internal_format);
9112 if ((channels_needed & channels_exist) != channels_needed) {
9113 LOCAL_SET_GL_ERROR(
9114 GL_INVALID_OPERATION, "glCopyTexImage2D", "incompatible format");
9115 return;
9118 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
9119 LOCAL_SET_GL_ERROR(
9120 GL_INVALID_OPERATION,
9121 "glCopyTexImage2D", "can not be used with depth or stencil textures");
9122 return;
9125 uint32 estimated_size = 0;
9126 if (!GLES2Util::ComputeImageDataSizes(
9127 width, height, 1, internal_format, GL_UNSIGNED_BYTE,
9128 state_.unpack_alignment, &estimated_size, NULL, NULL)) {
9129 LOCAL_SET_GL_ERROR(
9130 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too large");
9131 return;
9134 if (!EnsureGPUMemoryAvailable(estimated_size)) {
9135 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexImage2D", "out of memory");
9136 return;
9139 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexImage2D")) {
9140 return;
9143 if (FormsTextureCopyingFeedbackLoop(texture_ref, level)) {
9144 LOCAL_SET_GL_ERROR(
9145 GL_INVALID_OPERATION,
9146 "glCopyTexImage2D", "source and destination textures are the same");
9147 return;
9150 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
9151 return;
9154 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTexImage2D");
9155 ScopedResolvedFrameBufferBinder binder(this, false, true);
9156 gfx::Size size = GetBoundReadFrameBufferSize();
9158 if (texture->IsAttachedToFramebuffer()) {
9159 framebuffer_state_.clear_state_dirty = true;
9162 // Clip to size to source dimensions
9163 GLint copyX = 0;
9164 GLint copyY = 0;
9165 GLint copyWidth = 0;
9166 GLint copyHeight = 0;
9167 Clip(x, width, size.width(), &copyX, &copyWidth);
9168 Clip(y, height, size.height(), &copyY, &copyHeight);
9170 if (copyX != x ||
9171 copyY != y ||
9172 copyWidth != width ||
9173 copyHeight != height) {
9174 // some part was clipped so clear the texture.
9175 if (!ClearLevel(texture, target, level, internal_format, internal_format,
9176 GL_UNSIGNED_BYTE, width, height, texture->IsImmutable())) {
9177 LOCAL_SET_GL_ERROR(
9178 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too big");
9179 return;
9181 if (copyHeight > 0 && copyWidth > 0) {
9182 GLint dx = copyX - x;
9183 GLint dy = copyY - y;
9184 GLint destX = dx;
9185 GLint destY = dy;
9186 ScopedModifyPixels modify(texture_ref);
9187 glCopyTexSubImage2D(target, level,
9188 destX, destY, copyX, copyY,
9189 copyWidth, copyHeight);
9191 } else {
9192 ScopedModifyPixels modify(texture_ref);
9193 glCopyTexImage2D(target, level, internal_format,
9194 copyX, copyY, copyWidth, copyHeight, border);
9196 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTexImage2D");
9197 if (error == GL_NO_ERROR) {
9198 texture_manager()->SetLevelInfo(
9199 texture_ref, target, level, internal_format, width, height, 1,
9200 border, internal_format, GL_UNSIGNED_BYTE, true);
9203 // This may be a slow command. Exit command processing to allow for
9204 // context preemption and GPU watchdog checks.
9205 ExitCommandProcessingEarly();
9208 void GLES2DecoderImpl::DoCopyTexSubImage2D(
9209 GLenum target,
9210 GLint level,
9211 GLint xoffset,
9212 GLint yoffset,
9213 GLint x,
9214 GLint y,
9215 GLsizei width,
9216 GLsizei height) {
9217 DCHECK(!ShouldDeferReads());
9218 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9219 &state_, target);
9220 if (!texture_ref) {
9221 LOCAL_SET_GL_ERROR(
9222 GL_INVALID_OPERATION,
9223 "glCopyTexSubImage2D", "unknown texture for target");
9224 return;
9226 Texture* texture = texture_ref->texture();
9227 GLenum type = 0;
9228 GLenum format = 0;
9229 if (!texture->GetLevelType(target, level, &type, &format) ||
9230 !texture->ValidForTexture(
9231 target, level, xoffset, yoffset, width, height, type)) {
9232 LOCAL_SET_GL_ERROR(
9233 GL_INVALID_VALUE, "glCopyTexSubImage2D", "bad dimensions.");
9234 return;
9236 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
9237 LOCAL_SET_GL_ERROR(
9238 GL_INVALID_OPERATION,
9239 "glCopyTexSubImage2D", "async upload pending for texture");
9240 return;
9243 // Check we have compatible formats.
9244 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
9245 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
9246 uint32 channels_needed = GLES2Util::GetChannelsForFormat(format);
9248 if (!channels_needed ||
9249 (channels_needed & channels_exist) != channels_needed) {
9250 LOCAL_SET_GL_ERROR(
9251 GL_INVALID_OPERATION, "glCopyTexSubImage2D", "incompatible format");
9252 return;
9255 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
9256 LOCAL_SET_GL_ERROR(
9257 GL_INVALID_OPERATION,
9258 "glCopySubImage2D", "can not be used with depth or stencil textures");
9259 return;
9262 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexSubImage2D")) {
9263 return;
9266 if (FormsTextureCopyingFeedbackLoop(texture_ref, level)) {
9267 LOCAL_SET_GL_ERROR(
9268 GL_INVALID_OPERATION,
9269 "glCopyTexSubImage2D", "source and destination textures are the same");
9270 return;
9273 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
9274 return;
9277 ScopedResolvedFrameBufferBinder binder(this, false, true);
9278 gfx::Size size = GetBoundReadFrameBufferSize();
9279 GLint copyX = 0;
9280 GLint copyY = 0;
9281 GLint copyWidth = 0;
9282 GLint copyHeight = 0;
9283 Clip(x, width, size.width(), &copyX, &copyWidth);
9284 Clip(y, height, size.height(), &copyY, &copyHeight);
9286 if (xoffset != 0 || yoffset != 0 || width != size.width() ||
9287 height != size.height()) {
9288 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target,
9289 level)) {
9290 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexSubImage2D",
9291 "dimensions too big");
9292 return;
9294 } else {
9295 // Write all pixels in below.
9296 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
9299 if (copyX != x ||
9300 copyY != y ||
9301 copyWidth != width ||
9302 copyHeight != height) {
9303 // some part was clipped so clear the sub rect.
9304 uint32 pixels_size = 0;
9305 if (!GLES2Util::ComputeImageDataSizes(
9306 width, height, 1, format, type, state_.unpack_alignment, &pixels_size,
9307 NULL, NULL)) {
9308 LOCAL_SET_GL_ERROR(
9309 GL_INVALID_VALUE, "glCopyTexSubImage2D", "dimensions too large");
9310 return;
9312 scoped_ptr<char[]> zero(new char[pixels_size]);
9313 memset(zero.get(), 0, pixels_size);
9314 ScopedModifyPixels modify(texture_ref);
9315 glTexSubImage2D(
9316 target, level, xoffset, yoffset, width, height,
9317 format, type, zero.get());
9320 if (copyHeight > 0 && copyWidth > 0) {
9321 GLint dx = copyX - x;
9322 GLint dy = copyY - y;
9323 GLint destX = xoffset + dx;
9324 GLint destY = yoffset + dy;
9325 ScopedModifyPixels modify(texture_ref);
9326 glCopyTexSubImage2D(target, level,
9327 destX, destY, copyX, copyY,
9328 copyWidth, copyHeight);
9331 // This may be a slow command. Exit command processing to allow for
9332 // context preemption and GPU watchdog checks.
9333 ExitCommandProcessingEarly();
9336 bool GLES2DecoderImpl::ValidateTexSubImage2D(
9337 error::Error* error,
9338 const char* function_name,
9339 GLenum target,
9340 GLint level,
9341 GLint xoffset,
9342 GLint yoffset,
9343 GLsizei width,
9344 GLsizei height,
9345 GLenum format,
9346 GLenum type,
9347 const void * data) {
9348 (*error) = error::kNoError;
9349 if (!validators_->texture_target.IsValid(target)) {
9350 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
9351 return false;
9353 if (width < 0) {
9354 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "width < 0");
9355 return false;
9357 if (height < 0) {
9358 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "height < 0");
9359 return false;
9361 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9362 &state_, target);
9363 if (!texture_ref) {
9364 LOCAL_SET_GL_ERROR(
9365 GL_INVALID_OPERATION,
9366 function_name, "unknown texture for target");
9367 return false;
9369 Texture* texture = texture_ref->texture();
9370 GLenum current_type = 0;
9371 GLenum internal_format = 0;
9372 if (!texture->GetLevelType(target, level, &current_type, &internal_format)) {
9373 LOCAL_SET_GL_ERROR(
9374 GL_INVALID_OPERATION, function_name, "level does not exist.");
9375 return false;
9377 if (!texture_manager()->ValidateTextureParameters(state_.GetErrorState(),
9378 function_name, format, type, internal_format, level)) {
9379 return false;
9381 if (type != current_type) {
9382 LOCAL_SET_GL_ERROR(
9383 GL_INVALID_OPERATION,
9384 function_name, "type does not match type of texture.");
9385 return false;
9387 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
9388 LOCAL_SET_GL_ERROR(
9389 GL_INVALID_OPERATION,
9390 function_name, "async upload pending for texture");
9391 return false;
9393 if (!texture->ValidForTexture(
9394 target, level, xoffset, yoffset, width, height, type)) {
9395 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "bad dimensions.");
9396 return false;
9398 if ((GLES2Util::GetChannelsForFormat(format) &
9399 (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
9400 LOCAL_SET_GL_ERROR(
9401 GL_INVALID_OPERATION,
9402 function_name, "can not supply data for depth or stencil textures");
9403 return false;
9405 if (data == NULL) {
9406 (*error) = error::kOutOfBounds;
9407 return false;
9409 return true;
9412 error::Error GLES2DecoderImpl::DoTexSubImage2D(
9413 GLenum target,
9414 GLint level,
9415 GLint xoffset,
9416 GLint yoffset,
9417 GLsizei width,
9418 GLsizei height,
9419 GLenum format,
9420 GLenum type,
9421 const void * data) {
9422 error::Error error = error::kNoError;
9423 if (!ValidateTexSubImage2D(&error, "glTexSubImage2D", target, level,
9424 xoffset, yoffset, width, height, format, type, data)) {
9425 return error;
9427 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9428 &state_, target);
9429 Texture* texture = texture_ref->texture();
9430 GLsizei tex_width = 0;
9431 GLsizei tex_height = 0;
9432 bool ok = texture->GetLevelSize(target, level, &tex_width, &tex_height);
9433 DCHECK(ok);
9434 if (xoffset != 0 || yoffset != 0 ||
9435 width != tex_width || height != tex_height) {
9436 if (!texture_manager()->ClearTextureLevel(this, texture_ref,
9437 target, level)) {
9438 LOCAL_SET_GL_ERROR(
9439 GL_OUT_OF_MEMORY, "glTexSubImage2D", "dimensions too big");
9440 return error::kNoError;
9442 ScopedTextureUploadTimer timer(&texture_state_);
9443 glTexSubImage2D(
9444 target, level, xoffset, yoffset, width, height, format, type, data);
9445 return error::kNoError;
9448 if (!texture_state_.texsubimage2d_faster_than_teximage2d &&
9449 !texture->IsImmutable() &&
9450 !texture->HasImages()) {
9451 ScopedTextureUploadTimer timer(&texture_state_);
9452 GLenum internal_format;
9453 GLenum tex_type;
9454 texture->GetLevelType(target, level, &tex_type, &internal_format);
9455 // NOTE: In OpenGL ES 2.0 border is always zero. If that changes we'll need
9456 // to look it up.
9457 glTexImage2D(
9458 target, level, internal_format, width, height, 0, format, type, data);
9459 } else {
9460 ScopedTextureUploadTimer timer(&texture_state_);
9461 glTexSubImage2D(
9462 target, level, xoffset, yoffset, width, height, format, type, data);
9464 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
9466 // This may be a slow command. Exit command processing to allow for
9467 // context preemption and GPU watchdog checks.
9468 ExitCommandProcessingEarly();
9469 return error::kNoError;
9472 error::Error GLES2DecoderImpl::HandleTexSubImage2D(uint32 immediate_data_size,
9473 const void* cmd_data) {
9474 const gles2::cmds::TexSubImage2D& c =
9475 *static_cast<const gles2::cmds::TexSubImage2D*>(cmd_data);
9476 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage2D",
9477 "width", c.width, "height", c.height);
9478 GLboolean internal = static_cast<GLboolean>(c.internal);
9479 if (internal == GL_TRUE && texture_state_.tex_image_2d_failed)
9480 return error::kNoError;
9482 GLenum target = static_cast<GLenum>(c.target);
9483 GLint level = static_cast<GLint>(c.level);
9484 GLint xoffset = static_cast<GLint>(c.xoffset);
9485 GLint yoffset = static_cast<GLint>(c.yoffset);
9486 GLsizei width = static_cast<GLsizei>(c.width);
9487 GLsizei height = static_cast<GLsizei>(c.height);
9488 GLenum format = static_cast<GLenum>(c.format);
9489 GLenum type = static_cast<GLenum>(c.type);
9490 uint32 data_size;
9491 if (!GLES2Util::ComputeImageDataSizes(
9492 width, height, 1, format, type, state_.unpack_alignment, &data_size,
9493 NULL, NULL)) {
9494 return error::kOutOfBounds;
9496 const void* pixels = GetSharedMemoryAs<const void*>(
9497 c.pixels_shm_id, c.pixels_shm_offset, data_size);
9498 return DoTexSubImage2D(
9499 target, level, xoffset, yoffset, width, height, format, type, pixels);
9502 // TODO(zmo): Remove the below stub once we add the real function binding.
9503 // Currently it's missing due to a gmock limitation.
9504 static void glTexSubImage3D(
9505 GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
9506 GLsizei height, GLsizei width, GLsizei depth, GLenum format, GLenum type,
9507 const void* pixels) {
9508 NOTIMPLEMENTED();
9511 error::Error GLES2DecoderImpl::HandleTexSubImage3D(uint32 immediate_data_size,
9512 const void* cmd_data) {
9513 // TODO(zmo): Unsafe ES3 API.
9514 if (!unsafe_es3_apis_enabled())
9515 return error::kUnknownCommand;
9517 const gles2::cmds::TexSubImage3D& c =
9518 *static_cast<const gles2::cmds::TexSubImage3D*>(cmd_data);
9519 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage3D",
9520 "widthXheight", c.width * c.height, "depth", c.depth);
9521 GLenum target = static_cast<GLenum>(c.target);
9522 GLint level = static_cast<GLint>(c.level);
9523 GLint xoffset = static_cast<GLint>(c.xoffset);
9524 GLint yoffset = static_cast<GLint>(c.yoffset);
9525 GLint zoffset = static_cast<GLint>(c.zoffset);
9526 GLsizei width = static_cast<GLsizei>(c.width);
9527 GLsizei height = static_cast<GLsizei>(c.height);
9528 GLsizei depth = static_cast<GLsizei>(c.depth);
9529 GLenum format = static_cast<GLenum>(c.format);
9530 GLenum type = static_cast<GLenum>(c.type);
9531 uint32 data_size;
9532 if (!GLES2Util::ComputeImageDataSizes(
9533 width, height, depth, format, type, state_.unpack_alignment, &data_size,
9534 NULL, NULL)) {
9535 return error::kOutOfBounds;
9537 const void* pixels = GetSharedMemoryAs<const void*>(
9538 c.pixels_shm_id, c.pixels_shm_offset, data_size);
9539 glTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height,
9540 depth, format, type, pixels);
9541 return error::kNoError;
9544 error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
9545 uint32 immediate_data_size,
9546 const void* cmd_data) {
9547 const gles2::cmds::GetVertexAttribPointerv& c =
9548 *static_cast<const gles2::cmds::GetVertexAttribPointerv*>(cmd_data);
9549 GLuint index = static_cast<GLuint>(c.index);
9550 GLenum pname = static_cast<GLenum>(c.pname);
9551 typedef cmds::GetVertexAttribPointerv::Result Result;
9552 Result* result = GetSharedMemoryAs<Result*>(
9553 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
9554 if (!result) {
9555 return error::kOutOfBounds;
9557 // Check that the client initialized the result.
9558 if (result->size != 0) {
9559 return error::kInvalidArguments;
9561 if (!validators_->vertex_pointer.IsValid(pname)) {
9562 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9563 "glGetVertexAttribPointerv", pname, "pname");
9564 return error::kNoError;
9566 if (index >= group_->max_vertex_attribs()) {
9567 LOCAL_SET_GL_ERROR(
9568 GL_INVALID_VALUE, "glGetVertexAttribPointerv", "index out of range.");
9569 return error::kNoError;
9571 result->SetNumResults(1);
9572 *result->GetData() =
9573 state_.vertex_attrib_manager->GetVertexAttrib(index)->offset();
9574 return error::kNoError;
9577 bool GLES2DecoderImpl::GetUniformSetup(
9578 GLuint program_id, GLint fake_location,
9579 uint32 shm_id, uint32 shm_offset,
9580 error::Error* error, GLint* real_location,
9581 GLuint* service_id, void** result_pointer, GLenum* result_type) {
9582 DCHECK(error);
9583 DCHECK(service_id);
9584 DCHECK(result_pointer);
9585 DCHECK(result_type);
9586 DCHECK(real_location);
9587 *error = error::kNoError;
9588 // Make sure we have enough room for the result on failure.
9589 SizedResult<GLint>* result;
9590 result = GetSharedMemoryAs<SizedResult<GLint>*>(
9591 shm_id, shm_offset, SizedResult<GLint>::ComputeSize(0));
9592 if (!result) {
9593 *error = error::kOutOfBounds;
9594 return false;
9596 *result_pointer = result;
9597 // Set the result size to 0 so the client does not have to check for success.
9598 result->SetNumResults(0);
9599 Program* program = GetProgramInfoNotShader(program_id, "glGetUniform");
9600 if (!program) {
9601 return false;
9603 if (!program->IsValid()) {
9604 // Program was not linked successfully. (ie, glLinkProgram)
9605 LOCAL_SET_GL_ERROR(
9606 GL_INVALID_OPERATION, "glGetUniform", "program not linked");
9607 return false;
9609 *service_id = program->service_id();
9610 GLint array_index = -1;
9611 const Program::UniformInfo* uniform_info =
9612 program->GetUniformInfoByFakeLocation(
9613 fake_location, real_location, &array_index);
9614 if (!uniform_info) {
9615 // No such location.
9616 LOCAL_SET_GL_ERROR(
9617 GL_INVALID_OPERATION, "glGetUniform", "unknown location");
9618 return false;
9620 GLenum type = uniform_info->type;
9621 GLsizei size = GLES2Util::GetGLDataTypeSizeForUniforms(type);
9622 if (size == 0) {
9623 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glGetUniform", "unknown type");
9624 return false;
9626 result = GetSharedMemoryAs<SizedResult<GLint>*>(
9627 shm_id, shm_offset, SizedResult<GLint>::ComputeSizeFromBytes(size));
9628 if (!result) {
9629 *error = error::kOutOfBounds;
9630 return false;
9632 result->size = size;
9633 *result_type = type;
9634 return true;
9637 error::Error GLES2DecoderImpl::HandleGetUniformiv(uint32 immediate_data_size,
9638 const void* cmd_data) {
9639 const gles2::cmds::GetUniformiv& c =
9640 *static_cast<const gles2::cmds::GetUniformiv*>(cmd_data);
9641 GLuint program = c.program;
9642 GLint fake_location = c.location;
9643 GLuint service_id;
9644 GLenum result_type;
9645 GLint real_location = -1;
9646 Error error;
9647 void* result;
9648 if (GetUniformSetup(
9649 program, fake_location, c.params_shm_id, c.params_shm_offset,
9650 &error, &real_location, &service_id, &result, &result_type)) {
9651 glGetUniformiv(
9652 service_id, real_location,
9653 static_cast<cmds::GetUniformiv::Result*>(result)->GetData());
9655 return error;
9658 error::Error GLES2DecoderImpl::HandleGetUniformfv(uint32 immediate_data_size,
9659 const void* cmd_data) {
9660 const gles2::cmds::GetUniformfv& c =
9661 *static_cast<const gles2::cmds::GetUniformfv*>(cmd_data);
9662 GLuint program = c.program;
9663 GLint fake_location = c.location;
9664 GLuint service_id;
9665 GLint real_location = -1;
9666 Error error;
9667 typedef cmds::GetUniformfv::Result Result;
9668 Result* result;
9669 GLenum result_type;
9670 if (GetUniformSetup(
9671 program, fake_location, c.params_shm_id, c.params_shm_offset,
9672 &error, &real_location, &service_id,
9673 reinterpret_cast<void**>(&result), &result_type)) {
9674 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
9675 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
9676 GLsizei num_values = result->GetNumResults();
9677 scoped_ptr<GLint[]> temp(new GLint[num_values]);
9678 glGetUniformiv(service_id, real_location, temp.get());
9679 GLfloat* dst = result->GetData();
9680 for (GLsizei ii = 0; ii < num_values; ++ii) {
9681 dst[ii] = (temp[ii] != 0);
9683 } else {
9684 glGetUniformfv(service_id, real_location, result->GetData());
9687 return error;
9690 error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
9691 uint32 immediate_data_size,
9692 const void* cmd_data) {
9693 const gles2::cmds::GetShaderPrecisionFormat& c =
9694 *static_cast<const gles2::cmds::GetShaderPrecisionFormat*>(cmd_data);
9695 GLenum shader_type = static_cast<GLenum>(c.shadertype);
9696 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
9697 typedef cmds::GetShaderPrecisionFormat::Result Result;
9698 Result* result = GetSharedMemoryAs<Result*>(
9699 c.result_shm_id, c.result_shm_offset, sizeof(*result));
9700 if (!result) {
9701 return error::kOutOfBounds;
9703 // Check that the client initialized the result.
9704 if (result->success != 0) {
9705 return error::kInvalidArguments;
9707 if (!validators_->shader_type.IsValid(shader_type)) {
9708 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9709 "glGetShaderPrecisionFormat", shader_type, "shader_type");
9710 return error::kNoError;
9712 if (!validators_->shader_precision.IsValid(precision_type)) {
9713 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9714 "glGetShaderPrecisionFormat", precision_type, "precision_type");
9715 return error::kNoError;
9718 result->success = 1; // true
9720 GLint range[2] = { 0, 0 };
9721 GLint precision = 0;
9722 GetShaderPrecisionFormatImpl(shader_type, precision_type, range, &precision);
9724 result->min_range = range[0];
9725 result->max_range = range[1];
9726 result->precision = precision;
9728 return error::kNoError;
9731 error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
9732 uint32 immediate_data_size,
9733 const void* cmd_data) {
9734 const gles2::cmds::GetAttachedShaders& c =
9735 *static_cast<const gles2::cmds::GetAttachedShaders*>(cmd_data);
9736 uint32 result_size = c.result_size;
9737 GLuint program_id = static_cast<GLuint>(c.program);
9738 Program* program = GetProgramInfoNotShader(
9739 program_id, "glGetAttachedShaders");
9740 if (!program) {
9741 return error::kNoError;
9743 typedef cmds::GetAttachedShaders::Result Result;
9744 uint32 max_count = Result::ComputeMaxResults(result_size);
9745 Result* result = GetSharedMemoryAs<Result*>(
9746 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
9747 if (!result) {
9748 return error::kOutOfBounds;
9750 // Check that the client initialized the result.
9751 if (result->size != 0) {
9752 return error::kInvalidArguments;
9754 GLsizei count = 0;
9755 glGetAttachedShaders(
9756 program->service_id(), max_count, &count, result->GetData());
9757 for (GLsizei ii = 0; ii < count; ++ii) {
9758 if (!shader_manager()->GetClientId(result->GetData()[ii],
9759 &result->GetData()[ii])) {
9760 NOTREACHED();
9761 return error::kGenericError;
9764 result->SetNumResults(count);
9765 return error::kNoError;
9768 error::Error GLES2DecoderImpl::HandleGetActiveUniform(
9769 uint32 immediate_data_size,
9770 const void* cmd_data) {
9771 const gles2::cmds::GetActiveUniform& c =
9772 *static_cast<const gles2::cmds::GetActiveUniform*>(cmd_data);
9773 GLuint program_id = c.program;
9774 GLuint index = c.index;
9775 uint32 name_bucket_id = c.name_bucket_id;
9776 typedef cmds::GetActiveUniform::Result Result;
9777 Result* result = GetSharedMemoryAs<Result*>(
9778 c.result_shm_id, c.result_shm_offset, sizeof(*result));
9779 if (!result) {
9780 return error::kOutOfBounds;
9782 // Check that the client initialized the result.
9783 if (result->success != 0) {
9784 return error::kInvalidArguments;
9786 Program* program = GetProgramInfoNotShader(
9787 program_id, "glGetActiveUniform");
9788 if (!program) {
9789 return error::kNoError;
9791 const Program::UniformInfo* uniform_info =
9792 program->GetUniformInfo(index);
9793 if (!uniform_info) {
9794 LOCAL_SET_GL_ERROR(
9795 GL_INVALID_VALUE, "glGetActiveUniform", "index out of range");
9796 return error::kNoError;
9798 result->success = 1; // true.
9799 result->size = uniform_info->size;
9800 result->type = uniform_info->type;
9801 Bucket* bucket = CreateBucket(name_bucket_id);
9802 bucket->SetFromString(uniform_info->name.c_str());
9803 return error::kNoError;
9806 error::Error GLES2DecoderImpl::HandleGetActiveUniformBlockiv(
9807 uint32 immediate_data_size, const void* cmd_data) {
9808 if (!unsafe_es3_apis_enabled())
9809 return error::kUnknownCommand;
9810 const gles2::cmds::GetActiveUniformBlockiv& c =
9811 *static_cast<const gles2::cmds::GetActiveUniformBlockiv*>(cmd_data);
9812 GLuint program_id = c.program;
9813 GLuint index = static_cast<GLuint>(c.index);
9814 GLenum pname = static_cast<GLenum>(c.pname);
9815 Program* program = GetProgramInfoNotShader(
9816 program_id, "glGetActiveUniformBlockiv");
9817 if (!program) {
9818 return error::kNoError;
9820 GLuint service_id = program->service_id();
9821 GLint link_status = GL_FALSE;
9822 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
9823 if (link_status != GL_TRUE) {
9824 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
9825 "glGetActiveActiveUniformBlockiv", "program not linked");
9826 return error::kNoError;
9828 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetActiveUniformBlockiv");
9829 GLsizei num_values = 1;
9830 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES) {
9831 GLint num = 0;
9832 glGetActiveUniformBlockiv(
9833 service_id, index, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &num);
9834 GLenum error = glGetError();
9835 if (error != GL_NO_ERROR) {
9836 // Assume this will the same error if calling with pname.
9837 LOCAL_SET_GL_ERROR(error, "GetActiveUniformBlockiv", "");
9838 return error::kNoError;
9840 num_values = static_cast<GLsizei>(num);
9842 typedef cmds::GetActiveUniformBlockiv::Result Result;
9843 Result* result = GetSharedMemoryAs<Result*>(
9844 c.params_shm_id, c.params_shm_offset, Result::ComputeSize(num_values));
9845 GLint* params = result ? result->GetData() : NULL;
9846 if (params == NULL) {
9847 return error::kOutOfBounds;
9849 // Check that the client initialized the result.
9850 if (result->size != 0) {
9851 return error::kInvalidArguments;
9853 glGetActiveUniformBlockiv(service_id, index, pname, params);
9854 GLenum error = glGetError();
9855 if (error == GL_NO_ERROR) {
9856 result->SetNumResults(num_values);
9857 } else {
9858 LOCAL_SET_GL_ERROR(error, "GetActiveUniformBlockiv", "");
9860 return error::kNoError;
9863 error::Error GLES2DecoderImpl::HandleGetActiveUniformBlockName(
9864 uint32 immediate_data_size, const void* cmd_data) {
9865 if (!unsafe_es3_apis_enabled())
9866 return error::kUnknownCommand;
9867 const gles2::cmds::GetActiveUniformBlockName& c =
9868 *static_cast<const gles2::cmds::GetActiveUniformBlockName*>(cmd_data);
9869 GLuint program_id = c.program;
9870 GLuint index = c.index;
9871 uint32 name_bucket_id = c.name_bucket_id;
9872 typedef cmds::GetActiveUniformBlockName::Result Result;
9873 Result* result = GetSharedMemoryAs<Result*>(
9874 c.result_shm_id, c.result_shm_offset, sizeof(*result));
9875 if (!result) {
9876 return error::kOutOfBounds;
9878 // Check that the client initialized the result.
9879 if (*result != 0) {
9880 return error::kInvalidArguments;
9882 Program* program = GetProgramInfoNotShader(
9883 program_id, "glGetActiveUniformBlockName");
9884 if (!program) {
9885 return error::kNoError;
9887 GLuint service_id = program->service_id();
9888 GLint link_status = GL_FALSE;
9889 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
9890 if (link_status != GL_TRUE) {
9891 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
9892 "glGetActiveActiveUniformBlockName", "program not linked");
9893 return error::kNoError;
9895 GLint max_length = 0;
9896 glGetProgramiv(
9897 service_id, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &max_length);
9898 // Increase one so &buffer[0] is always valid.
9899 GLsizei buf_size = static_cast<GLsizei>(max_length) + 1;
9900 std::vector<char> buffer(buf_size);
9901 GLsizei length = 0;
9902 glGetActiveUniformBlockName(
9903 service_id, index, buf_size, &length, &buffer[0]);
9904 if (length == 0) {
9905 *result = 0;
9906 return error::kNoError;
9908 *result = 1;
9909 Bucket* bucket = CreateBucket(name_bucket_id);
9910 DCHECK_GT(buf_size, length);
9911 DCHECK_EQ(0, buffer[length]);
9912 bucket->SetFromString(&buffer[0]);
9913 return error::kNoError;
9916 error::Error GLES2DecoderImpl::HandleGetActiveUniformsiv(
9917 uint32 immediate_data_size, const void* cmd_data) {
9918 if (!unsafe_es3_apis_enabled())
9919 return error::kUnknownCommand;
9920 const gles2::cmds::GetActiveUniformsiv& c =
9921 *static_cast<const gles2::cmds::GetActiveUniformsiv*>(cmd_data);
9922 GLuint program_id = c.program;
9923 GLenum pname = static_cast<GLenum>(c.pname);
9924 Bucket* bucket = GetBucket(c.indices_bucket_id);
9925 if (!bucket) {
9926 return error::kInvalidArguments;
9928 GLsizei count = static_cast<GLsizei>(bucket->size() / sizeof(GLuint));
9929 const GLuint* indices = bucket->GetDataAs<const GLuint*>(0, bucket->size());
9930 typedef cmds::GetActiveUniformsiv::Result Result;
9931 Result* result = GetSharedMemoryAs<Result*>(
9932 c.params_shm_id, c.params_shm_offset, Result::ComputeSize(count));
9933 GLint* params = result ? result->GetData() : NULL;
9934 if (params == NULL) {
9935 return error::kOutOfBounds;
9937 // Check that the client initialized the result.
9938 if (result->size != 0) {
9939 return error::kInvalidArguments;
9941 Program* program = GetProgramInfoNotShader(
9942 program_id, "glGetActiveUniformsiv");
9943 if (!program) {
9944 return error::kNoError;
9946 GLuint service_id = program->service_id();
9947 GLint link_status = GL_FALSE;
9948 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
9949 if (link_status != GL_TRUE) {
9950 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
9951 "glGetActiveUniformsiv", "program not linked");
9952 return error::kNoError;
9954 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetActiveUniformsiv");
9955 glGetActiveUniformsiv(service_id, count, indices, pname, params);
9956 GLenum error = glGetError();
9957 if (error == GL_NO_ERROR) {
9958 result->SetNumResults(count);
9959 } else {
9960 LOCAL_SET_GL_ERROR(error, "GetActiveUniformsiv", "");
9962 return error::kNoError;
9965 error::Error GLES2DecoderImpl::HandleGetActiveAttrib(uint32 immediate_data_size,
9966 const void* cmd_data) {
9967 const gles2::cmds::GetActiveAttrib& c =
9968 *static_cast<const gles2::cmds::GetActiveAttrib*>(cmd_data);
9969 GLuint program_id = c.program;
9970 GLuint index = c.index;
9971 uint32 name_bucket_id = c.name_bucket_id;
9972 typedef cmds::GetActiveAttrib::Result Result;
9973 Result* result = GetSharedMemoryAs<Result*>(
9974 c.result_shm_id, c.result_shm_offset, sizeof(*result));
9975 if (!result) {
9976 return error::kOutOfBounds;
9978 // Check that the client initialized the result.
9979 if (result->success != 0) {
9980 return error::kInvalidArguments;
9982 Program* program = GetProgramInfoNotShader(
9983 program_id, "glGetActiveAttrib");
9984 if (!program) {
9985 return error::kNoError;
9987 const Program::VertexAttrib* attrib_info =
9988 program->GetAttribInfo(index);
9989 if (!attrib_info) {
9990 LOCAL_SET_GL_ERROR(
9991 GL_INVALID_VALUE, "glGetActiveAttrib", "index out of range");
9992 return error::kNoError;
9994 result->success = 1; // true.
9995 result->size = attrib_info->size;
9996 result->type = attrib_info->type;
9997 Bucket* bucket = CreateBucket(name_bucket_id);
9998 bucket->SetFromString(attrib_info->name.c_str());
9999 return error::kNoError;
10002 error::Error GLES2DecoderImpl::HandleShaderBinary(uint32 immediate_data_size,
10003 const void* cmd_data) {
10004 #if 1 // No binary shader support.
10005 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glShaderBinary", "not supported");
10006 return error::kNoError;
10007 #else
10008 GLsizei n = static_cast<GLsizei>(c.n);
10009 if (n < 0) {
10010 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "n < 0");
10011 return error::kNoError;
10013 GLsizei length = static_cast<GLsizei>(c.length);
10014 if (length < 0) {
10015 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "length < 0");
10016 return error::kNoError;
10018 uint32 data_size;
10019 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
10020 return error::kOutOfBounds;
10022 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
10023 c.shaders_shm_id, c.shaders_shm_offset, data_size);
10024 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
10025 const void* binary = GetSharedMemoryAs<const void*>(
10026 c.binary_shm_id, c.binary_shm_offset, length);
10027 if (shaders == NULL || binary == NULL) {
10028 return error::kOutOfBounds;
10030 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
10031 for (GLsizei ii = 0; ii < n; ++ii) {
10032 Shader* shader = GetShader(shaders[ii]);
10033 if (!shader) {
10034 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "unknown shader");
10035 return error::kNoError;
10037 service_ids[ii] = shader->service_id();
10039 // TODO(gman): call glShaderBinary
10040 return error::kNoError;
10041 #endif
10044 void GLES2DecoderImpl::DoSwapBuffers() {
10045 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
10047 int this_frame_number = frame_number_++;
10048 // TRACE_EVENT for gpu tests:
10049 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffersLatency",
10050 TRACE_EVENT_SCOPE_THREAD,
10051 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
10052 "width", (is_offscreen ? offscreen_size_.width() :
10053 surface_->GetSize().width()));
10054 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoSwapBuffers",
10055 "offscreen", is_offscreen,
10056 "frame", this_frame_number);
10058 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
10061 ScopedGPUTrace scoped_gpu_trace(gpu_tracer_.get(), kTraceDecoder,
10062 "gpu_toplevel", "SwapBuffer");
10064 bool is_tracing;
10065 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
10066 &is_tracing);
10067 if (is_tracing) {
10068 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
10069 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
10070 is_offscreen ? offscreen_size_ : surface_->GetSize());
10073 // If offscreen then don't actually SwapBuffers to the display. Just copy
10074 // the rendered frame to another frame buffer.
10075 if (is_offscreen) {
10076 TRACE_EVENT2("gpu", "Offscreen",
10077 "width", offscreen_size_.width(), "height", offscreen_size_.height());
10078 if (offscreen_size_ != offscreen_saved_color_texture_->size()) {
10079 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
10080 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
10081 // fix this.
10082 if (workarounds().needs_offscreen_buffer_workaround) {
10083 offscreen_saved_frame_buffer_->Create();
10084 glFinish();
10087 // Allocate the offscreen saved color texture.
10088 DCHECK(offscreen_saved_color_format_);
10089 offscreen_saved_color_texture_->AllocateStorage(
10090 offscreen_size_, offscreen_saved_color_format_, false);
10092 offscreen_saved_frame_buffer_->AttachRenderTexture(
10093 offscreen_saved_color_texture_.get());
10094 if (offscreen_size_.width() != 0 && offscreen_size_.height() != 0) {
10095 if (offscreen_saved_frame_buffer_->CheckStatus() !=
10096 GL_FRAMEBUFFER_COMPLETE) {
10097 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
10098 << "because offscreen saved FBO was incomplete.";
10099 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB);
10100 return;
10103 // Clear the offscreen color texture.
10104 // TODO(piman): Is this still necessary?
10106 ScopedFrameBufferBinder binder(this,
10107 offscreen_saved_frame_buffer_->id());
10108 glClearColor(0, 0, 0, 0);
10109 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
10110 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
10111 glClear(GL_COLOR_BUFFER_BIT);
10112 RestoreClearState();
10116 UpdateParentTextureInfo();
10119 if (offscreen_size_.width() == 0 || offscreen_size_.height() == 0)
10120 return;
10121 ScopedGLErrorSuppressor suppressor(
10122 "GLES2DecoderImpl::DoSwapBuffers", GetErrorState());
10124 if (IsOffscreenBufferMultisampled()) {
10125 // For multisampled buffers, resolve the frame buffer.
10126 ScopedResolvedFrameBufferBinder binder(this, true, false);
10127 } else {
10128 ScopedFrameBufferBinder binder(this,
10129 offscreen_target_frame_buffer_->id());
10131 if (offscreen_target_buffer_preserved_) {
10132 // Copy the target frame buffer to the saved offscreen texture.
10133 offscreen_saved_color_texture_->Copy(
10134 offscreen_saved_color_texture_->size(),
10135 offscreen_saved_color_format_);
10136 } else {
10137 // Flip the textures in the parent context via the texture manager.
10138 if (!!offscreen_saved_color_texture_info_.get())
10139 offscreen_saved_color_texture_info_->texture()->
10140 SetServiceId(offscreen_target_color_texture_->id());
10142 offscreen_saved_color_texture_.swap(offscreen_target_color_texture_);
10143 offscreen_target_frame_buffer_->AttachRenderTexture(
10144 offscreen_target_color_texture_.get());
10147 // Ensure the side effects of the copy are visible to the parent
10148 // context. There is no need to do this for ANGLE because it uses a
10149 // single D3D device for all contexts.
10150 if (!feature_info_->gl_version_info().is_angle)
10151 glFlush();
10153 } else {
10154 if (!surface_->SwapBuffers()) {
10155 LOG(ERROR) << "Context lost because SwapBuffers failed.";
10156 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB);
10160 // This may be a slow command. Exit command processing to allow for
10161 // context preemption and GPU watchdog checks.
10162 ExitCommandProcessingEarly();
10165 void GLES2DecoderImpl::DoSwapInterval(int interval)
10167 context_->SetSwapInterval(interval);
10170 error::Error GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
10171 uint32 immediate_data_size,
10172 const void* cmd_data) {
10173 const gles2::cmds::EnableFeatureCHROMIUM& c =
10174 *static_cast<const gles2::cmds::EnableFeatureCHROMIUM*>(cmd_data);
10175 Bucket* bucket = GetBucket(c.bucket_id);
10176 if (!bucket || bucket->size() == 0) {
10177 return error::kInvalidArguments;
10179 typedef cmds::EnableFeatureCHROMIUM::Result Result;
10180 Result* result = GetSharedMemoryAs<Result*>(
10181 c.result_shm_id, c.result_shm_offset, sizeof(*result));
10182 if (!result) {
10183 return error::kOutOfBounds;
10185 // Check that the client initialized the result.
10186 if (*result != 0) {
10187 return error::kInvalidArguments;
10189 std::string feature_str;
10190 if (!bucket->GetAsString(&feature_str)) {
10191 return error::kInvalidArguments;
10194 // TODO(gman): make this some kind of table to function pointer thingy.
10195 if (feature_str.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
10196 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
10197 } else if (feature_str.compare("pepper3d_support_fixed_attribs") == 0) {
10198 buffer_manager()->set_allow_fixed_attribs(true);
10199 // TODO(gman): decide how to remove the need for this const_cast.
10200 // I could make validators_ non const but that seems bad as this is the only
10201 // place it is needed. I could make some special friend class of validators
10202 // just to allow this to set them. That seems silly. I could refactor this
10203 // code to use the extension mechanism or the initialization attributes to
10204 // turn this feature on. Given that the only real point of this is to make
10205 // the conformance tests pass and given that there is lots of real work that
10206 // needs to be done it seems like refactoring for one to one of those
10207 // methods is a very low priority.
10208 const_cast<Validators*>(validators_)->vertex_attrib_type.AddValue(GL_FIXED);
10209 } else if (feature_str.compare("webgl_enable_glsl_webgl_validation") == 0) {
10210 force_webgl_glsl_validation_ = true;
10211 InitializeShaderTranslator();
10212 } else {
10213 return error::kNoError;
10216 *result = 1; // true.
10217 return error::kNoError;
10220 error::Error GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
10221 uint32 immediate_data_size,
10222 const void* cmd_data) {
10223 const gles2::cmds::GetRequestableExtensionsCHROMIUM& c =
10224 *static_cast<const gles2::cmds::GetRequestableExtensionsCHROMIUM*>(
10225 cmd_data);
10226 Bucket* bucket = CreateBucket(c.bucket_id);
10227 scoped_refptr<FeatureInfo> info(new FeatureInfo());
10228 info->Initialize(disallowed_features_);
10229 bucket->SetFromString(info->extensions().c_str());
10230 return error::kNoError;
10233 error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
10234 uint32 immediate_data_size,
10235 const void* cmd_data) {
10236 const gles2::cmds::RequestExtensionCHROMIUM& c =
10237 *static_cast<const gles2::cmds::RequestExtensionCHROMIUM*>(cmd_data);
10238 Bucket* bucket = GetBucket(c.bucket_id);
10239 if (!bucket || bucket->size() == 0) {
10240 return error::kInvalidArguments;
10242 std::string feature_str;
10243 if (!bucket->GetAsString(&feature_str)) {
10244 return error::kInvalidArguments;
10247 bool desire_webgl_glsl_validation =
10248 feature_str.find("GL_CHROMIUM_webglsl") != std::string::npos;
10249 bool desire_standard_derivatives = false;
10250 bool desire_frag_depth = false;
10251 bool desire_draw_buffers = false;
10252 bool desire_shader_texture_lod = false;
10253 if (force_webgl_glsl_validation_) {
10254 desire_standard_derivatives =
10255 feature_str.find("GL_OES_standard_derivatives") != std::string::npos;
10256 desire_frag_depth =
10257 feature_str.find("GL_EXT_frag_depth") != std::string::npos;
10258 desire_draw_buffers =
10259 feature_str.find("GL_EXT_draw_buffers") != std::string::npos;
10260 desire_shader_texture_lod =
10261 feature_str.find("GL_EXT_shader_texture_lod") != std::string::npos;
10264 if (desire_webgl_glsl_validation != force_webgl_glsl_validation_ ||
10265 desire_standard_derivatives != derivatives_explicitly_enabled_ ||
10266 desire_frag_depth != frag_depth_explicitly_enabled_ ||
10267 desire_draw_buffers != draw_buffers_explicitly_enabled_) {
10268 force_webgl_glsl_validation_ |= desire_webgl_glsl_validation;
10269 derivatives_explicitly_enabled_ |= desire_standard_derivatives;
10270 frag_depth_explicitly_enabled_ |= desire_frag_depth;
10271 draw_buffers_explicitly_enabled_ |= desire_draw_buffers;
10272 shader_texture_lod_explicitly_enabled_ |= desire_shader_texture_lod;
10273 InitializeShaderTranslator();
10276 UpdateCapabilities();
10278 return error::kNoError;
10281 error::Error GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
10282 uint32 immediate_data_size,
10283 const void* cmd_data) {
10284 const gles2::cmds::GetProgramInfoCHROMIUM& c =
10285 *static_cast<const gles2::cmds::GetProgramInfoCHROMIUM*>(cmd_data);
10286 GLuint program_id = static_cast<GLuint>(c.program);
10287 uint32 bucket_id = c.bucket_id;
10288 Bucket* bucket = CreateBucket(bucket_id);
10289 bucket->SetSize(sizeof(ProgramInfoHeader)); // in case we fail.
10290 Program* program = NULL;
10291 program = GetProgram(program_id);
10292 if (!program || !program->IsValid()) {
10293 return error::kNoError;
10295 program->GetProgramInfo(program_manager(), bucket);
10296 return error::kNoError;
10299 error::Error GLES2DecoderImpl::HandleGetUniformBlocksCHROMIUM(
10300 uint32 immediate_data_size, const void* cmd_data) {
10301 if (!unsafe_es3_apis_enabled())
10302 return error::kUnknownCommand;
10303 const gles2::cmds::GetUniformBlocksCHROMIUM& c =
10304 *static_cast<const gles2::cmds::GetUniformBlocksCHROMIUM*>(cmd_data);
10305 GLuint program_id = static_cast<GLuint>(c.program);
10306 uint32 bucket_id = c.bucket_id;
10307 Bucket* bucket = CreateBucket(bucket_id);
10308 bucket->SetSize(sizeof(UniformBlocksHeader)); // in case we fail.
10309 Program* program = NULL;
10310 program = GetProgram(program_id);
10311 if (!program || !program->IsValid()) {
10312 return error::kNoError;
10314 program->GetUniformBlocks(bucket);
10315 return error::kNoError;
10318 error::Error GLES2DecoderImpl::HandleGetUniformsES3CHROMIUM(
10319 uint32 immediate_data_size, const void* cmd_data) {
10320 if (!unsafe_es3_apis_enabled())
10321 return error::kUnknownCommand;
10322 const gles2::cmds::GetUniformsES3CHROMIUM& c =
10323 *static_cast<const gles2::cmds::GetUniformsES3CHROMIUM*>(cmd_data);
10324 GLuint program_id = static_cast<GLuint>(c.program);
10325 uint32 bucket_id = c.bucket_id;
10326 Bucket* bucket = CreateBucket(bucket_id);
10327 bucket->SetSize(sizeof(UniformsES3Header)); // in case we fail.
10328 Program* program = NULL;
10329 program = GetProgram(program_id);
10330 if (!program || !program->IsValid()) {
10331 return error::kNoError;
10333 program->GetUniformsES3(bucket);
10334 return error::kNoError;
10337 error::Error GLES2DecoderImpl::HandleGetTransformFeedbackVarying(
10338 uint32 immediate_data_size,
10339 const void* cmd_data) {
10340 if (!unsafe_es3_apis_enabled())
10341 return error::kUnknownCommand;
10342 const gles2::cmds::GetTransformFeedbackVarying& c =
10343 *static_cast<const gles2::cmds::GetTransformFeedbackVarying*>(cmd_data);
10344 GLuint program_id = c.program;
10345 GLuint index = c.index;
10346 uint32 name_bucket_id = c.name_bucket_id;
10347 typedef cmds::GetTransformFeedbackVarying::Result Result;
10348 Result* result = GetSharedMemoryAs<Result*>(
10349 c.result_shm_id, c.result_shm_offset, sizeof(*result));
10350 if (!result) {
10351 return error::kOutOfBounds;
10353 // Check that the client initialized the result.
10354 if (result->success != 0) {
10355 return error::kInvalidArguments;
10357 Program* program = GetProgramInfoNotShader(
10358 program_id, "glGetTransformFeedbackVarying");
10359 if (!program) {
10360 return error::kNoError;
10362 GLuint service_id = program->service_id();
10363 GLint link_status = GL_FALSE;
10364 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
10365 if (link_status != GL_TRUE) {
10366 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10367 "glGetTransformFeedbackVarying", "program not linked");
10368 return error::kNoError;
10370 GLint max_length = 0;
10371 glGetProgramiv(
10372 service_id, GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH, &max_length);
10373 max_length = std::max(1, max_length);
10374 std::vector<char> buffer(max_length);
10375 GLsizei length = 0;
10376 GLsizei size = 0;
10377 GLenum type = 0;
10378 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetTransformFeedbackVarying");
10379 glGetTransformFeedbackVarying(
10380 service_id, index, max_length, &length, &size, &type, &buffer[0]);
10381 GLenum error = glGetError();
10382 if (error != GL_NO_ERROR) {
10383 LOCAL_SET_GL_ERROR(error, "glGetTransformFeedbackVarying", "");
10384 return error::kNoError;
10386 result->success = 1; // true.
10387 result->size = static_cast<int32_t>(size);
10388 result->type = static_cast<uint32_t>(type);
10389 Bucket* bucket = CreateBucket(name_bucket_id);
10390 DCHECK(length >= 0 && length < max_length);
10391 buffer[length] = '\0'; // Just to be safe.
10392 bucket->SetFromString(&buffer[0]);
10393 return error::kNoError;
10396 error::Error GLES2DecoderImpl::HandleGetTransformFeedbackVaryingsCHROMIUM(
10397 uint32 immediate_data_size, const void* cmd_data) {
10398 if (!unsafe_es3_apis_enabled())
10399 return error::kUnknownCommand;
10400 const gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM& c =
10401 *static_cast<const gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM*>(
10402 cmd_data);
10403 GLuint program_id = static_cast<GLuint>(c.program);
10404 uint32 bucket_id = c.bucket_id;
10405 Bucket* bucket = CreateBucket(bucket_id);
10406 bucket->SetSize(sizeof(TransformFeedbackVaryingsHeader)); // in case we fail.
10407 Program* program = NULL;
10408 program = GetProgram(program_id);
10409 if (!program || !program->IsValid()) {
10410 return error::kNoError;
10412 program->GetTransformFeedbackVaryings(bucket);
10413 return error::kNoError;
10416 error::ContextLostReason GLES2DecoderImpl::GetContextLostReason() {
10417 switch (reset_status_) {
10418 case GL_NO_ERROR:
10419 // TODO(kbr): improve the precision of the error code in this case.
10420 // Consider delegating to context for error code if MakeCurrent fails.
10421 return error::kUnknown;
10422 case GL_GUILTY_CONTEXT_RESET_ARB:
10423 return error::kGuilty;
10424 case GL_INNOCENT_CONTEXT_RESET_ARB:
10425 return error::kInnocent;
10426 case GL_UNKNOWN_CONTEXT_RESET_ARB:
10427 return error::kUnknown;
10430 NOTREACHED();
10431 return error::kUnknown;
10434 void GLES2DecoderImpl::MaybeExitOnContextLost() {
10435 // Some D3D drivers cannot recover from device lost in the GPU process
10436 // sandbox. Allow a new GPU process to launch.
10437 if (workarounds().exit_on_context_lost) {
10438 LOG(ERROR) << "Exiting GPU process because some drivers cannot reset"
10439 << " a D3D device in the Chrome GPU process sandbox.";
10440 #if defined(OS_WIN)
10441 base::win::SetShouldCrashOnProcessDetach(false);
10442 #endif
10443 exit(0);
10447 bool GLES2DecoderImpl::WasContextLost() {
10448 if (reset_status_ != GL_NO_ERROR) {
10449 MaybeExitOnContextLost();
10450 return true;
10452 if (IsRobustnessSupported()) {
10453 GLenum status = glGetGraphicsResetStatusARB();
10454 if (status != GL_NO_ERROR) {
10455 // The graphics card was reset. Signal a lost context to the application.
10456 reset_status_ = status;
10457 reset_by_robustness_extension_ = true;
10458 LOG(ERROR) << (surface_->IsOffscreen() ? "Offscreen" : "Onscreen")
10459 << " context lost via ARB/EXT_robustness. Reset status = "
10460 << GLES2Util::GetStringEnum(status);
10461 MaybeExitOnContextLost();
10462 return true;
10465 return false;
10468 bool GLES2DecoderImpl::WasContextLostByRobustnessExtension() {
10469 return WasContextLost() && reset_by_robustness_extension_;
10472 void GLES2DecoderImpl::LoseContext(uint32 reset_status) {
10473 // Only loses the context once.
10474 if (reset_status_ != GL_NO_ERROR) {
10475 return;
10478 if (workarounds().use_virtualized_gl_contexts) {
10479 // If the context is virtual, the real context being guilty does not ensure
10480 // that the virtual context is guilty.
10481 if (reset_status == GL_GUILTY_CONTEXT_RESET_ARB) {
10482 reset_status = GL_UNKNOWN_CONTEXT_RESET_ARB;
10484 } else if (reset_status == GL_UNKNOWN_CONTEXT_RESET_ARB &&
10485 IsRobustnessSupported()) {
10486 // If the reason for the call was a GL error, we can try to determine the
10487 // reset status more accurately.
10488 GLenum driver_status = glGetGraphicsResetStatusARB();
10489 if (driver_status == GL_GUILTY_CONTEXT_RESET_ARB ||
10490 driver_status == GL_INNOCENT_CONTEXT_RESET_ARB) {
10491 reset_status = driver_status;
10495 // Marks this context as lost.
10496 reset_status_ = reset_status;
10497 current_decoder_error_ = error::kLostContext;
10500 error::Error GLES2DecoderImpl::HandleInsertSyncPointCHROMIUM(
10501 uint32 immediate_data_size,
10502 const void* cmd_data) {
10503 return error::kUnknownCommand;
10506 error::Error GLES2DecoderImpl::HandleWaitSyncPointCHROMIUM(
10507 uint32 immediate_data_size,
10508 const void* cmd_data) {
10509 const gles2::cmds::WaitSyncPointCHROMIUM& c =
10510 *static_cast<const gles2::cmds::WaitSyncPointCHROMIUM*>(cmd_data);
10511 uint32 sync_point = c.sync_point;
10512 if (wait_sync_point_callback_.is_null())
10513 return error::kNoError;
10515 return wait_sync_point_callback_.Run(sync_point) ?
10516 error::kNoError : error::kDeferCommandUntilLater;
10519 error::Error GLES2DecoderImpl::HandleDiscardBackbufferCHROMIUM(
10520 uint32 immediate_data_size,
10521 const void* cmd_data) {
10522 if (surface_->DeferDraws())
10523 return error::kDeferCommandUntilLater;
10524 if (!surface_->SetBackbufferAllocation(false))
10525 return error::kLostContext;
10526 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
10527 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
10528 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
10529 return error::kNoError;
10532 bool GLES2DecoderImpl::GenQueriesEXTHelper(
10533 GLsizei n, const GLuint* client_ids) {
10534 for (GLsizei ii = 0; ii < n; ++ii) {
10535 if (query_manager_->GetQuery(client_ids[ii])) {
10536 return false;
10539 query_manager_->GenQueries(n, client_ids);
10540 return true;
10543 void GLES2DecoderImpl::DeleteQueriesEXTHelper(
10544 GLsizei n, const GLuint* client_ids) {
10545 for (GLsizei ii = 0; ii < n; ++ii) {
10546 QueryManager::Query* query = query_manager_->GetQuery(client_ids[ii]);
10547 if (query && !query->IsDeleted()) {
10548 ContextState::QueryMap::iterator it =
10549 state_.current_queries.find(query->target());
10550 if (it != state_.current_queries.end())
10551 state_.current_queries.erase(it);
10553 query->Destroy(true);
10555 query_manager_->RemoveQuery(client_ids[ii]);
10559 bool GLES2DecoderImpl::ProcessPendingQueries(bool did_finish) {
10560 if (query_manager_.get() == NULL) {
10561 return false;
10563 if (!query_manager_->ProcessPendingQueries(did_finish)) {
10564 current_decoder_error_ = error::kOutOfBounds;
10566 return query_manager_->HavePendingQueries();
10569 // Note that if there are no pending readpixels right now,
10570 // this function will call the callback immediately.
10571 void GLES2DecoderImpl::WaitForReadPixels(base::Closure callback) {
10572 if (features().use_async_readpixels && !pending_readpixel_fences_.empty()) {
10573 pending_readpixel_fences_.back()->callbacks.push_back(callback);
10574 } else {
10575 callback.Run();
10579 void GLES2DecoderImpl::ProcessPendingReadPixels() {
10580 while (!pending_readpixel_fences_.empty() &&
10581 pending_readpixel_fences_.front()->fence->HasCompleted()) {
10582 std::vector<base::Closure> callbacks =
10583 pending_readpixel_fences_.front()->callbacks;
10584 pending_readpixel_fences_.pop();
10585 for (size_t i = 0; i < callbacks.size(); i++) {
10586 callbacks[i].Run();
10591 bool GLES2DecoderImpl::HasMoreIdleWork() {
10592 return !pending_readpixel_fences_.empty() ||
10593 async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers();
10596 void GLES2DecoderImpl::PerformIdleWork() {
10597 ProcessPendingReadPixels();
10598 if (!async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers())
10599 return;
10600 async_pixel_transfer_manager_->ProcessMorePendingTransfers();
10601 ProcessFinishedAsyncTransfers();
10604 error::Error GLES2DecoderImpl::HandleBeginQueryEXT(uint32 immediate_data_size,
10605 const void* cmd_data) {
10606 const gles2::cmds::BeginQueryEXT& c =
10607 *static_cast<const gles2::cmds::BeginQueryEXT*>(cmd_data);
10608 GLenum target = static_cast<GLenum>(c.target);
10609 GLuint client_id = static_cast<GLuint>(c.id);
10610 int32 sync_shm_id = static_cast<int32>(c.sync_data_shm_id);
10611 uint32 sync_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
10613 switch (target) {
10614 case GL_COMMANDS_ISSUED_CHROMIUM:
10615 case GL_LATENCY_QUERY_CHROMIUM:
10616 case GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM:
10617 case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM:
10618 case GL_GET_ERROR_QUERY_CHROMIUM:
10619 break;
10620 case GL_COMMANDS_COMPLETED_CHROMIUM:
10621 if (!features().chromium_sync_query) {
10622 LOCAL_SET_GL_ERROR(
10623 GL_INVALID_OPERATION, "glBeginQueryEXT",
10624 "not enabled for commands completed queries");
10625 return error::kNoError;
10627 break;
10628 default:
10629 if (!features().occlusion_query_boolean) {
10630 LOCAL_SET_GL_ERROR(
10631 GL_INVALID_OPERATION, "glBeginQueryEXT",
10632 "not enabled for occlusion queries");
10633 return error::kNoError;
10635 break;
10638 if (state_.current_queries.find(target) != state_.current_queries.end()) {
10639 LOCAL_SET_GL_ERROR(
10640 GL_INVALID_OPERATION, "glBeginQueryEXT", "query already in progress");
10641 return error::kNoError;
10644 if (client_id == 0) {
10645 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glBeginQueryEXT", "id is 0");
10646 return error::kNoError;
10649 QueryManager::Query* query = query_manager_->GetQuery(client_id);
10650 if (!query) {
10651 if (!query_manager_->IsValidQuery(client_id)) {
10652 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10653 "glBeginQueryEXT",
10654 "id not made by glGenQueriesEXT");
10655 return error::kNoError;
10657 query = query_manager_->CreateQuery(
10658 target, client_id, sync_shm_id, sync_shm_offset);
10661 if (query->target() != target) {
10662 LOCAL_SET_GL_ERROR(
10663 GL_INVALID_OPERATION, "glBeginQueryEXT", "target does not match");
10664 return error::kNoError;
10665 } else if (query->shm_id() != sync_shm_id ||
10666 query->shm_offset() != sync_shm_offset) {
10667 DLOG(ERROR) << "Shared memory used by query not the same as before";
10668 return error::kInvalidArguments;
10671 if (!query_manager_->BeginQuery(query)) {
10672 return error::kOutOfBounds;
10675 state_.current_queries[target] = query;
10676 return error::kNoError;
10679 error::Error GLES2DecoderImpl::HandleEndQueryEXT(uint32 immediate_data_size,
10680 const void* cmd_data) {
10681 const gles2::cmds::EndQueryEXT& c =
10682 *static_cast<const gles2::cmds::EndQueryEXT*>(cmd_data);
10683 GLenum target = static_cast<GLenum>(c.target);
10684 uint32 submit_count = static_cast<GLuint>(c.submit_count);
10685 ContextState::QueryMap::iterator it = state_.current_queries.find(target);
10687 if (it == state_.current_queries.end()) {
10688 LOCAL_SET_GL_ERROR(
10689 GL_INVALID_OPERATION, "glEndQueryEXT", "No active query");
10690 return error::kNoError;
10693 QueryManager::Query* query = it->second.get();
10694 if (!query_manager_->EndQuery(query, submit_count)) {
10695 return error::kOutOfBounds;
10698 query_manager_->ProcessPendingTransferQueries();
10700 state_.current_queries.erase(it);
10701 return error::kNoError;
10704 bool GLES2DecoderImpl::GenVertexArraysOESHelper(
10705 GLsizei n, const GLuint* client_ids) {
10706 for (GLsizei ii = 0; ii < n; ++ii) {
10707 if (GetVertexAttribManager(client_ids[ii])) {
10708 return false;
10712 if (!features().native_vertex_array_object) {
10713 // Emulated VAO
10714 for (GLsizei ii = 0; ii < n; ++ii) {
10715 CreateVertexAttribManager(client_ids[ii], 0, true);
10717 } else {
10718 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
10720 glGenVertexArraysOES(n, service_ids.get());
10721 for (GLsizei ii = 0; ii < n; ++ii) {
10722 CreateVertexAttribManager(client_ids[ii], service_ids[ii], true);
10726 return true;
10729 void GLES2DecoderImpl::DeleteVertexArraysOESHelper(
10730 GLsizei n, const GLuint* client_ids) {
10731 for (GLsizei ii = 0; ii < n; ++ii) {
10732 VertexAttribManager* vao =
10733 GetVertexAttribManager(client_ids[ii]);
10734 if (vao && !vao->IsDeleted()) {
10735 if (state_.vertex_attrib_manager.get() == vao) {
10736 DoBindVertexArrayOES(0);
10738 RemoveVertexAttribManager(client_ids[ii]);
10743 void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id) {
10744 VertexAttribManager* vao = NULL;
10745 if (client_id != 0) {
10746 vao = GetVertexAttribManager(client_id);
10747 if (!vao) {
10748 // Unlike most Bind* methods, the spec explicitly states that VertexArray
10749 // only allows names that have been previously generated. As such, we do
10750 // not generate new names here.
10751 LOCAL_SET_GL_ERROR(
10752 GL_INVALID_OPERATION,
10753 "glBindVertexArrayOES", "bad vertex array id.");
10754 current_decoder_error_ = error::kNoError;
10755 return;
10757 } else {
10758 vao = state_.default_vertex_attrib_manager.get();
10761 // Only set the VAO state if it's changed
10762 if (state_.vertex_attrib_manager.get() != vao) {
10763 state_.vertex_attrib_manager = vao;
10764 if (!features().native_vertex_array_object) {
10765 EmulateVertexArrayState();
10766 } else {
10767 GLuint service_id = vao->service_id();
10768 glBindVertexArrayOES(service_id);
10773 // Used when OES_vertex_array_object isn't natively supported
10774 void GLES2DecoderImpl::EmulateVertexArrayState() {
10775 // Setup the Vertex attribute state
10776 for (uint32 vv = 0; vv < group_->max_vertex_attribs(); ++vv) {
10777 RestoreStateForAttrib(vv, true);
10780 // Setup the element buffer
10781 Buffer* element_array_buffer =
10782 state_.vertex_attrib_manager->element_array_buffer();
10783 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
10784 element_array_buffer ? element_array_buffer->service_id() : 0);
10787 bool GLES2DecoderImpl::DoIsVertexArrayOES(GLuint client_id) {
10788 const VertexAttribManager* vao =
10789 GetVertexAttribManager(client_id);
10790 return vao && vao->IsValid() && !vao->IsDeleted();
10793 #if defined(OS_MACOSX)
10794 void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id) {
10795 TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.find(
10796 texture_id);
10797 if (it != texture_to_io_surface_map_.end()) {
10798 // Found a previous IOSurface bound to this texture; release it.
10799 IOSurfaceRef surface = it->second;
10800 CFRelease(surface);
10801 texture_to_io_surface_map_.erase(it);
10804 #endif
10806 void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
10807 GLenum target, GLsizei width, GLsizei height,
10808 GLuint io_surface_id, GLuint plane) {
10809 #if defined(OS_MACOSX)
10810 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) {
10811 LOCAL_SET_GL_ERROR(
10812 GL_INVALID_OPERATION,
10813 "glTexImageIOSurface2DCHROMIUM", "only supported on desktop GL.");
10814 return;
10817 if (target != GL_TEXTURE_RECTANGLE_ARB) {
10818 // This might be supported in the future, and if we could require
10819 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
10820 // could delete a lot of code. For now, perform strict validation so we
10821 // know what's going on.
10822 LOCAL_SET_GL_ERROR(
10823 GL_INVALID_OPERATION,
10824 "glTexImageIOSurface2DCHROMIUM",
10825 "requires TEXTURE_RECTANGLE_ARB target");
10826 return;
10829 // Default target might be conceptually valid, but disallow it to avoid
10830 // accidents.
10831 TextureRef* texture_ref =
10832 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
10833 if (!texture_ref) {
10834 LOCAL_SET_GL_ERROR(
10835 GL_INVALID_OPERATION,
10836 "glTexImageIOSurface2DCHROMIUM", "no rectangle texture bound");
10837 return;
10840 // Look up the new IOSurface. Note that because of asynchrony
10841 // between processes this might fail; during live resizing the
10842 // plugin process might allocate and release an IOSurface before
10843 // this process gets a chance to look it up. Hold on to any old
10844 // IOSurface in this case.
10845 IOSurfaceRef surface = IOSurfaceLookup(io_surface_id);
10846 if (!surface) {
10847 LOCAL_SET_GL_ERROR(
10848 GL_INVALID_OPERATION,
10849 "glTexImageIOSurface2DCHROMIUM", "no IOSurface with the given ID");
10850 return;
10853 // Release any IOSurface previously bound to this texture.
10854 ReleaseIOSurfaceForTexture(texture_ref->service_id());
10856 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
10857 texture_to_io_surface_map_.insert(
10858 std::make_pair(texture_ref->service_id(), surface));
10860 CGLContextObj context =
10861 static_cast<CGLContextObj>(context_->GetHandle());
10863 CGLError err = CGLTexImageIOSurface2D(
10864 context,
10865 target,
10866 GL_RGBA,
10867 width,
10868 height,
10869 GL_BGRA,
10870 GL_UNSIGNED_INT_8_8_8_8_REV,
10871 surface,
10872 plane);
10874 if (err != kCGLNoError) {
10875 LOCAL_SET_GL_ERROR(
10876 GL_INVALID_OPERATION,
10877 "glTexImageIOSurface2DCHROMIUM", "error in CGLTexImageIOSurface2D");
10878 return;
10881 texture_manager()->SetLevelInfo(
10882 texture_ref, target, 0, GL_RGBA, width, height, 1, 0,
10883 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, true);
10885 #else
10886 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10887 "glTexImageIOSurface2DCHROMIUM", "not supported.");
10888 #endif
10891 static GLenum ExtractFormatFromStorageFormat(GLenum internalformat) {
10892 switch (internalformat) {
10893 case GL_RGB565:
10894 return GL_RGB;
10895 case GL_RGBA4:
10896 return GL_RGBA;
10897 case GL_RGB5_A1:
10898 return GL_RGBA;
10899 case GL_RGB8_OES:
10900 return GL_RGB;
10901 case GL_RGBA8_OES:
10902 return GL_RGBA;
10903 case GL_LUMINANCE8_ALPHA8_EXT:
10904 return GL_LUMINANCE_ALPHA;
10905 case GL_LUMINANCE8_EXT:
10906 return GL_LUMINANCE;
10907 case GL_ALPHA8_EXT:
10908 return GL_ALPHA;
10909 case GL_RGBA32F_EXT:
10910 return GL_RGBA;
10911 case GL_RGB32F_EXT:
10912 return GL_RGB;
10913 case GL_ALPHA32F_EXT:
10914 return GL_ALPHA;
10915 case GL_LUMINANCE32F_EXT:
10916 return GL_LUMINANCE;
10917 case GL_LUMINANCE_ALPHA32F_EXT:
10918 return GL_LUMINANCE_ALPHA;
10919 case GL_RGBA16F_EXT:
10920 return GL_RGBA;
10921 case GL_RGB16F_EXT:
10922 return GL_RGB;
10923 case GL_ALPHA16F_EXT:
10924 return GL_ALPHA;
10925 case GL_LUMINANCE16F_EXT:
10926 return GL_LUMINANCE;
10927 case GL_LUMINANCE_ALPHA16F_EXT:
10928 return GL_LUMINANCE_ALPHA;
10929 case GL_BGRA8_EXT:
10930 return GL_BGRA_EXT;
10931 case GL_SRGB8_ALPHA8_EXT:
10932 return GL_SRGB_ALPHA_EXT;
10933 default:
10934 return GL_NONE;
10938 void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
10939 GLenum target, GLuint source_id, GLuint dest_id, GLint level,
10940 GLenum internal_format, GLenum dest_type) {
10941 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopyTextureCHROMIUM");
10943 TextureRef* dest_texture_ref = GetTexture(dest_id);
10944 TextureRef* source_texture_ref = GetTexture(source_id);
10946 if (!source_texture_ref || !dest_texture_ref) {
10947 LOCAL_SET_GL_ERROR(
10948 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "unknown texture id");
10949 return;
10952 if (GL_TEXTURE_2D != target) {
10953 LOCAL_SET_GL_ERROR(
10954 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "invalid texture target");
10955 return;
10958 Texture* source_texture = source_texture_ref->texture();
10959 Texture* dest_texture = dest_texture_ref->texture();
10960 if (dest_texture->target() != GL_TEXTURE_2D ||
10961 (source_texture->target() != GL_TEXTURE_2D &&
10962 source_texture->target() != GL_TEXTURE_RECTANGLE_ARB &&
10963 source_texture->target() != GL_TEXTURE_EXTERNAL_OES)) {
10964 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
10965 "glCopyTextureCHROMIUM",
10966 "invalid texture target binding");
10967 return;
10970 int source_width, source_height, dest_width, dest_height;
10972 gfx::GLImage* image =
10973 source_texture->GetLevelImage(source_texture->target(), 0);
10974 if (image) {
10975 gfx::Size size = image->GetSize();
10976 source_width = size.width();
10977 source_height = size.height();
10978 if (source_width <= 0 || source_height <= 0) {
10979 LOCAL_SET_GL_ERROR(
10980 GL_INVALID_VALUE,
10981 "glCopyTextureChromium", "invalid image size");
10982 return;
10984 } else {
10985 if (!source_texture->GetLevelSize(
10986 source_texture->target(), 0, &source_width, &source_height)) {
10987 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
10988 "glCopyTextureChromium",
10989 "source texture has no level 0");
10990 return;
10993 // Check that this type of texture is allowed.
10994 if (!texture_manager()->ValidForTarget(
10995 source_texture->target(), level, source_width, source_height, 1)) {
10996 LOCAL_SET_GL_ERROR(
10997 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "Bad dimensions");
10998 return;
11002 // Clear the source texture if necessary.
11003 if (!texture_manager()->ClearTextureLevel(
11004 this, source_texture_ref, source_texture->target(), 0)) {
11005 LOCAL_SET_GL_ERROR(
11006 GL_OUT_OF_MEMORY, "glCopyTextureCHROMIUM", "dimensions too big");
11007 return;
11010 GLenum source_type = 0;
11011 GLenum source_internal_format = 0;
11012 source_texture->GetLevelType(
11013 source_texture->target(), 0, &source_type, &source_internal_format);
11015 // The destination format should be GL_RGB, or GL_RGBA. GL_ALPHA,
11016 // GL_LUMINANCE, and GL_LUMINANCE_ALPHA are not supported because they are not
11017 // renderable on some platforms.
11018 bool valid_dest_format = internal_format == GL_RGB ||
11019 internal_format == GL_RGBA ||
11020 internal_format == GL_BGRA_EXT;
11021 bool valid_source_format = source_internal_format == GL_ALPHA ||
11022 source_internal_format == GL_RGB ||
11023 source_internal_format == GL_RGBA ||
11024 source_internal_format == GL_LUMINANCE ||
11025 source_internal_format == GL_LUMINANCE_ALPHA ||
11026 source_internal_format == GL_BGRA_EXT;
11027 if (!valid_source_format || !valid_dest_format) {
11028 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
11029 "glCopyTextureCHROMIUM",
11030 "invalid internal format");
11031 return;
11034 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
11035 // needed because it takes 10s of milliseconds to initialize.
11036 if (!copy_texture_CHROMIUM_.get()) {
11037 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
11038 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
11039 copy_texture_CHROMIUM_->Initialize(this);
11040 RestoreCurrentFramebufferBindings();
11041 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR)
11042 return;
11045 GLenum dest_type_previous = dest_type;
11046 GLenum dest_internal_format = internal_format;
11047 bool dest_level_defined = dest_texture->GetLevelSize(
11048 GL_TEXTURE_2D, level, &dest_width, &dest_height);
11050 if (dest_level_defined) {
11051 dest_texture->GetLevelType(GL_TEXTURE_2D, level, &dest_type_previous,
11052 &dest_internal_format);
11055 // Resize the destination texture to the dimensions of the source texture.
11056 if (!dest_level_defined || dest_width != source_width ||
11057 dest_height != source_height ||
11058 dest_internal_format != internal_format ||
11059 dest_type_previous != dest_type) {
11060 // Ensure that the glTexImage2D succeeds.
11061 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
11062 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
11063 glTexImage2D(
11064 GL_TEXTURE_2D, level, internal_format, source_width, source_height,
11065 0, internal_format, dest_type, NULL);
11066 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM");
11067 if (error != GL_NO_ERROR) {
11068 RestoreCurrentTextureBindings(&state_, GL_TEXTURE_2D);
11069 return;
11072 texture_manager()->SetLevelInfo(
11073 dest_texture_ref, GL_TEXTURE_2D, level, internal_format, source_width,
11074 source_height, 1, 0, internal_format, dest_type, true);
11075 } else {
11076 texture_manager()->SetLevelCleared(
11077 dest_texture_ref, GL_TEXTURE_2D, level, true);
11080 ScopedModifyPixels modify(dest_texture_ref);
11082 // Try using GLImage::CopyTexImage when possible.
11083 bool unpack_premultiply_alpha_change =
11084 unpack_premultiply_alpha_ ^ unpack_unpremultiply_alpha_;
11085 if (image && !unpack_flip_y_ && !unpack_premultiply_alpha_change && !level) {
11086 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
11087 if (image->CopyTexImage(GL_TEXTURE_2D))
11088 return;
11091 DoWillUseTexImageIfNeeded(source_texture, source_texture->target());
11093 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
11094 // before presenting.
11095 if (source_texture->target() == GL_TEXTURE_EXTERNAL_OES) {
11096 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
11097 // instead of using default matrix crbug.com/226218.
11098 const static GLfloat default_matrix[16] = {1.0f, 0.0f, 0.0f, 0.0f,
11099 0.0f, 1.0f, 0.0f, 0.0f,
11100 0.0f, 0.0f, 1.0f, 0.0f,
11101 0.0f, 0.0f, 0.0f, 1.0f};
11102 copy_texture_CHROMIUM_->DoCopyTextureWithTransform(
11103 this,
11104 source_texture->target(),
11105 source_texture->service_id(),
11106 dest_texture->service_id(),
11107 level,
11108 source_width,
11109 source_height,
11110 unpack_flip_y_,
11111 unpack_premultiply_alpha_,
11112 unpack_unpremultiply_alpha_,
11113 default_matrix);
11114 } else {
11115 copy_texture_CHROMIUM_->DoCopyTexture(this,
11116 source_texture->target(),
11117 source_texture->service_id(),
11118 source_internal_format,
11119 dest_texture->service_id(),
11120 level,
11121 internal_format,
11122 source_width,
11123 source_height,
11124 unpack_flip_y_,
11125 unpack_premultiply_alpha_,
11126 unpack_unpremultiply_alpha_);
11129 DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
11132 static GLenum ExtractTypeFromStorageFormat(GLenum internalformat) {
11133 switch (internalformat) {
11134 case GL_RGB565:
11135 return GL_UNSIGNED_SHORT_5_6_5;
11136 case GL_RGBA4:
11137 return GL_UNSIGNED_SHORT_4_4_4_4;
11138 case GL_RGB5_A1:
11139 return GL_UNSIGNED_SHORT_5_5_5_1;
11140 case GL_RGB8_OES:
11141 return GL_UNSIGNED_BYTE;
11142 case GL_RGBA8_OES:
11143 return GL_UNSIGNED_BYTE;
11144 case GL_LUMINANCE8_ALPHA8_EXT:
11145 return GL_UNSIGNED_BYTE;
11146 case GL_LUMINANCE8_EXT:
11147 return GL_UNSIGNED_BYTE;
11148 case GL_ALPHA8_EXT:
11149 return GL_UNSIGNED_BYTE;
11150 case GL_RGBA32F_EXT:
11151 return GL_FLOAT;
11152 case GL_RGB32F_EXT:
11153 return GL_FLOAT;
11154 case GL_ALPHA32F_EXT:
11155 return GL_FLOAT;
11156 case GL_LUMINANCE32F_EXT:
11157 return GL_FLOAT;
11158 case GL_LUMINANCE_ALPHA32F_EXT:
11159 return GL_FLOAT;
11160 case GL_RGBA16F_EXT:
11161 return GL_HALF_FLOAT_OES;
11162 case GL_RGB16F_EXT:
11163 return GL_HALF_FLOAT_OES;
11164 case GL_ALPHA16F_EXT:
11165 return GL_HALF_FLOAT_OES;
11166 case GL_LUMINANCE16F_EXT:
11167 return GL_HALF_FLOAT_OES;
11168 case GL_LUMINANCE_ALPHA16F_EXT:
11169 return GL_HALF_FLOAT_OES;
11170 case GL_BGRA8_EXT:
11171 return GL_UNSIGNED_BYTE;
11172 default:
11173 return GL_NONE;
11177 void GLES2DecoderImpl::DoTexStorage2DEXT(
11178 GLenum target,
11179 GLint levels,
11180 GLenum internal_format,
11181 GLsizei width,
11182 GLsizei height) {
11183 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT",
11184 "width", width, "height", height);
11185 if (!texture_manager()->ValidForTarget(target, 0, width, height, 1) ||
11186 TextureManager::ComputeMipMapCount(target, width, height, 1) < levels) {
11187 LOCAL_SET_GL_ERROR(
11188 GL_INVALID_VALUE, "glTexStorage2DEXT", "dimensions out of range");
11189 return;
11191 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
11192 &state_, target);
11193 if (!texture_ref) {
11194 LOCAL_SET_GL_ERROR(
11195 GL_INVALID_OPERATION,
11196 "glTexStorage2DEXT", "unknown texture for target");
11197 return;
11199 Texture* texture = texture_ref->texture();
11200 if (texture->IsAttachedToFramebuffer()) {
11201 framebuffer_state_.clear_state_dirty = true;
11203 if (texture->IsImmutable()) {
11204 LOCAL_SET_GL_ERROR(
11205 GL_INVALID_OPERATION,
11206 "glTexStorage2DEXT", "texture is immutable");
11207 return;
11210 GLenum format = ExtractFormatFromStorageFormat(internal_format);
11211 GLenum type = ExtractTypeFromStorageFormat(internal_format);
11214 GLsizei level_width = width;
11215 GLsizei level_height = height;
11216 uint32 estimated_size = 0;
11217 for (int ii = 0; ii < levels; ++ii) {
11218 uint32 level_size = 0;
11219 if (!GLES2Util::ComputeImageDataSizes(
11220 level_width, level_height, 1, format, type, state_.unpack_alignment,
11221 &estimated_size, NULL, NULL) ||
11222 !SafeAddUint32(estimated_size, level_size, &estimated_size)) {
11223 LOCAL_SET_GL_ERROR(
11224 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "dimensions too large");
11225 return;
11227 level_width = std::max(1, level_width >> 1);
11228 level_height = std::max(1, level_height >> 1);
11230 if (!EnsureGPUMemoryAvailable(estimated_size)) {
11231 LOCAL_SET_GL_ERROR(
11232 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "out of memory");
11233 return;
11237 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexStorage2DEXT");
11238 glTexStorage2DEXT(target, levels, internal_format, width, height);
11239 GLenum error = LOCAL_PEEK_GL_ERROR("glTexStorage2DEXT");
11240 if (error == GL_NO_ERROR) {
11241 GLsizei level_width = width;
11242 GLsizei level_height = height;
11243 for (int ii = 0; ii < levels; ++ii) {
11244 texture_manager()->SetLevelInfo(
11245 texture_ref, target, ii, format,
11246 level_width, level_height, 1, 0, format, type, false);
11247 level_width = std::max(1, level_width >> 1);
11248 level_height = std::max(1, level_height >> 1);
11250 texture->SetImmutable(true);
11254 error::Error GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
11255 uint32 immediate_data_size,
11256 const void* cmd_data) {
11257 return error::kUnknownCommand;
11260 void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target,
11261 const GLbyte* data) {
11262 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureCHROMIUM",
11263 "context", logger_.GetLogPrefix(),
11264 "mailbox[0]", static_cast<unsigned char>(data[0]));
11266 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
11267 &state_, target);
11268 ProduceTextureRef("glProduceTextureCHROMIUM", texture_ref, target, data);
11271 void GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM(GLuint client_id,
11272 GLenum target, const GLbyte* data) {
11273 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM",
11274 "context", logger_.GetLogPrefix(),
11275 "mailbox[0]", static_cast<unsigned char>(data[0]));
11277 ProduceTextureRef("glProduceTextureDirectCHROMIUM", GetTexture(client_id),
11278 target, data);
11281 void GLES2DecoderImpl::ProduceTextureRef(std::string func_name,
11282 TextureRef* texture_ref, GLenum target, const GLbyte* data) {
11283 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
11284 DLOG_IF(ERROR, !mailbox.Verify()) << func_name << " was passed a "
11285 "mailbox that was not generated by "
11286 "GenMailboxCHROMIUM.";
11288 if (!texture_ref) {
11289 LOCAL_SET_GL_ERROR(
11290 GL_INVALID_OPERATION, func_name.c_str(), "unknown texture for target");
11291 return;
11294 Texture* produced = texture_manager()->Produce(texture_ref);
11295 if (!produced) {
11296 LOCAL_SET_GL_ERROR(
11297 GL_INVALID_OPERATION, func_name.c_str(), "invalid texture");
11298 return;
11301 if (produced->target() != target) {
11302 LOCAL_SET_GL_ERROR(
11303 GL_INVALID_OPERATION, func_name.c_str(), "invalid target");
11304 return;
11307 group_->mailbox_manager()->ProduceTexture(mailbox, produced);
11310 void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target,
11311 const GLbyte* data) {
11312 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoConsumeTextureCHROMIUM",
11313 "context", logger_.GetLogPrefix(),
11314 "mailbox[0]", static_cast<unsigned char>(data[0]));
11315 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
11316 DLOG_IF(ERROR, !mailbox.Verify()) << "ConsumeTextureCHROMIUM was passed a "
11317 "mailbox that was not generated by "
11318 "GenMailboxCHROMIUM.";
11320 scoped_refptr<TextureRef> texture_ref =
11321 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
11322 if (!texture_ref.get()) {
11323 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
11324 "glConsumeTextureCHROMIUM",
11325 "unknown texture for target");
11326 return;
11328 GLuint client_id = texture_ref->client_id();
11329 if (!client_id) {
11330 LOCAL_SET_GL_ERROR(
11331 GL_INVALID_OPERATION,
11332 "glConsumeTextureCHROMIUM", "unknown texture for target");
11333 return;
11335 Texture* texture = group_->mailbox_manager()->ConsumeTexture(mailbox);
11336 if (!texture) {
11337 LOCAL_SET_GL_ERROR(
11338 GL_INVALID_OPERATION,
11339 "glConsumeTextureCHROMIUM", "invalid mailbox name");
11340 return;
11342 if (texture->target() != target) {
11343 LOCAL_SET_GL_ERROR(
11344 GL_INVALID_OPERATION,
11345 "glConsumeTextureCHROMIUM", "invalid target");
11346 return;
11349 DeleteTexturesHelper(1, &client_id);
11350 texture_ref = texture_manager()->Consume(client_id, texture);
11351 glBindTexture(target, texture_ref->service_id());
11353 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
11354 unit.bind_target = target;
11355 switch (target) {
11356 case GL_TEXTURE_2D:
11357 unit.bound_texture_2d = texture_ref;
11358 break;
11359 case GL_TEXTURE_CUBE_MAP:
11360 unit.bound_texture_cube_map = texture_ref;
11361 break;
11362 case GL_TEXTURE_EXTERNAL_OES:
11363 unit.bound_texture_external_oes = texture_ref;
11364 break;
11365 case GL_TEXTURE_RECTANGLE_ARB:
11366 unit.bound_texture_rectangle_arb = texture_ref;
11367 break;
11368 default:
11369 NOTREACHED(); // Validation should prevent us getting here.
11370 break;
11374 error::Error GLES2DecoderImpl::HandleCreateAndConsumeTextureCHROMIUMImmediate(
11375 uint32_t immediate_data_size,
11376 const void* cmd_data) {
11377 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate& c =
11378 *static_cast<
11379 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate*>(
11380 cmd_data);
11381 GLenum target = static_cast<GLenum>(c.target);
11382 uint32_t data_size;
11383 if (!ComputeDataSize(1, sizeof(GLbyte), 64, &data_size)) {
11384 return error::kOutOfBounds;
11386 if (data_size > immediate_data_size) {
11387 return error::kOutOfBounds;
11389 const GLbyte* mailbox =
11390 GetImmediateDataAs<const GLbyte*>(c, data_size, immediate_data_size);
11391 if (!validators_->texture_bind_target.IsValid(target)) {
11392 LOCAL_SET_GL_ERROR_INVALID_ENUM(
11393 "glCreateAndConsumeTextureCHROMIUM", target, "target");
11394 return error::kNoError;
11396 if (mailbox == NULL) {
11397 return error::kOutOfBounds;
11399 uint32_t client_id = c.client_id;
11400 DoCreateAndConsumeTextureCHROMIUM(target, mailbox, client_id);
11401 return error::kNoError;
11404 void GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM(GLenum target,
11405 const GLbyte* data, GLuint client_id) {
11406 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM",
11407 "context", logger_.GetLogPrefix(),
11408 "mailbox[0]", static_cast<unsigned char>(data[0]));
11409 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
11410 DLOG_IF(ERROR, !mailbox.Verify()) << "CreateAndConsumeTextureCHROMIUM was "
11411 "passed a mailbox that was not "
11412 "generated by GenMailboxCHROMIUM.";
11414 TextureRef* texture_ref = GetTexture(client_id);
11415 if (texture_ref) {
11416 LOCAL_SET_GL_ERROR(
11417 GL_INVALID_OPERATION,
11418 "glCreateAndConsumeTextureCHROMIUM", "client id already in use");
11419 return;
11421 Texture* texture = group_->mailbox_manager()->ConsumeTexture(mailbox);
11422 if (!texture) {
11423 LOCAL_SET_GL_ERROR(
11424 GL_INVALID_OPERATION,
11425 "glCreateAndConsumeTextureCHROMIUM", "invalid mailbox name");
11426 return;
11428 if (texture->target() != target) {
11429 LOCAL_SET_GL_ERROR(
11430 GL_INVALID_OPERATION,
11431 "glCreateAndConsumeTextureCHROMIUM", "invalid target");
11432 return;
11435 texture_ref = texture_manager()->Consume(client_id, texture);
11438 bool GLES2DecoderImpl::DoIsValuebufferCHROMIUM(GLuint client_id) {
11439 const Valuebuffer* valuebuffer = GetValuebuffer(client_id);
11440 return valuebuffer && valuebuffer->IsValid();
11443 void GLES2DecoderImpl::DoBindValueBufferCHROMIUM(GLenum target,
11444 GLuint client_id) {
11445 Valuebuffer* valuebuffer = NULL;
11446 if (client_id != 0) {
11447 valuebuffer = GetValuebuffer(client_id);
11448 if (!valuebuffer) {
11449 if (!group_->bind_generates_resource()) {
11450 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glBindValuebufferCHROMIUM",
11451 "id not generated by glBindValuebufferCHROMIUM");
11452 return;
11455 // It's a new id so make a valuebuffer for it.
11456 CreateValuebuffer(client_id);
11457 valuebuffer = GetValuebuffer(client_id);
11459 valuebuffer->MarkAsValid();
11461 state_.bound_valuebuffer = valuebuffer;
11464 void GLES2DecoderImpl::DoSubscribeValueCHROMIUM(GLenum target,
11465 GLenum subscription) {
11466 if (!CheckCurrentValuebuffer("glSubscribeValueCHROMIUM")) {
11467 return;
11469 state_.bound_valuebuffer.get()->AddSubscription(subscription);
11472 void GLES2DecoderImpl::DoPopulateSubscribedValuesCHROMIUM(GLenum target) {
11473 if (!CheckCurrentValuebuffer("glPopulateSubscribedValuesCHROMIUM")) {
11474 return;
11476 valuebuffer_manager()->UpdateValuebufferState(state_.bound_valuebuffer.get());
11479 void GLES2DecoderImpl::DoUniformValueBufferCHROMIUM(GLint location,
11480 GLenum target,
11481 GLenum subscription) {
11482 if (!CheckCurrentValuebufferForSubscription(
11483 subscription, "glPopulateSubscribedValuesCHROMIUM")) {
11484 return;
11486 if (!CheckSubscriptionTarget(location, subscription,
11487 "glPopulateSubscribedValuesCHROMIUM")) {
11488 return;
11490 const ValueState* state =
11491 state_.bound_valuebuffer.get()->GetState(subscription);
11492 if (state) {
11493 switch (subscription) {
11494 case GL_MOUSE_POSITION_CHROMIUM:
11495 DoUniform2iv(location, 1, state->int_value);
11496 break;
11497 default:
11498 NOTREACHED() << "Unhandled uniform subscription target "
11499 << subscription;
11500 break;
11505 void GLES2DecoderImpl::DoInsertEventMarkerEXT(
11506 GLsizei length, const GLchar* marker) {
11507 if (!marker) {
11508 marker = "";
11510 debug_marker_manager_.SetMarker(
11511 length ? std::string(marker, length) : std::string(marker));
11514 void GLES2DecoderImpl::DoPushGroupMarkerEXT(
11515 GLsizei length, const GLchar* marker) {
11516 if (!marker) {
11517 marker = "";
11519 std::string name = length ? std::string(marker, length) : std::string(marker);
11520 debug_marker_manager_.PushGroup(name);
11521 gpu_tracer_->Begin(TRACE_DISABLED_BY_DEFAULT("gpu_group_marker"), name,
11522 kTraceGroupMarker);
11525 void GLES2DecoderImpl::DoPopGroupMarkerEXT(void) {
11526 debug_marker_manager_.PopGroup();
11527 gpu_tracer_->End(kTraceGroupMarker);
11530 void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(
11531 GLenum target, GLint image_id) {
11532 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM");
11534 if (target == GL_TEXTURE_CUBE_MAP) {
11535 LOCAL_SET_GL_ERROR(
11536 GL_INVALID_ENUM,
11537 "glBindTexImage2DCHROMIUM", "invalid target");
11538 return;
11541 // Default target might be conceptually valid, but disallow it to avoid
11542 // accidents.
11543 TextureRef* texture_ref =
11544 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
11545 if (!texture_ref) {
11546 LOCAL_SET_GL_ERROR(
11547 GL_INVALID_OPERATION,
11548 "glBindTexImage2DCHROMIUM", "no texture bound");
11549 return;
11552 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
11553 if (!gl_image) {
11554 LOCAL_SET_GL_ERROR(
11555 GL_INVALID_OPERATION,
11556 "glBindTexImage2DCHROMIUM", "no image found with the given ID");
11557 return;
11561 ScopedGLErrorSuppressor suppressor(
11562 "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", GetErrorState());
11563 if (!gl_image->BindTexImage(target)) {
11564 LOCAL_SET_GL_ERROR(
11565 GL_INVALID_OPERATION,
11566 "glBindTexImage2DCHROMIUM", "fail to bind image with the given ID");
11567 return;
11571 gfx::Size size = gl_image->GetSize();
11572 texture_manager()->SetLevelInfo(
11573 texture_ref, target, 0, GL_RGBA, size.width(), size.height(), 1, 0,
11574 GL_RGBA, GL_UNSIGNED_BYTE, true);
11575 texture_manager()->SetLevelImage(texture_ref, target, 0, gl_image);
11578 void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(
11579 GLenum target, GLint image_id) {
11580 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM");
11582 // Default target might be conceptually valid, but disallow it to avoid
11583 // accidents.
11584 TextureRef* texture_ref =
11585 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
11586 if (!texture_ref) {
11587 LOCAL_SET_GL_ERROR(
11588 GL_INVALID_OPERATION,
11589 "glReleaseTexImage2DCHROMIUM", "no texture bound");
11590 return;
11593 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
11594 if (!gl_image) {
11595 LOCAL_SET_GL_ERROR(
11596 GL_INVALID_OPERATION,
11597 "glReleaseTexImage2DCHROMIUM", "no image found with the given ID");
11598 return;
11601 // Do nothing when image is not currently bound.
11602 if (texture_ref->texture()->GetLevelImage(target, 0) != gl_image)
11603 return;
11606 ScopedGLErrorSuppressor suppressor(
11607 "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", GetErrorState());
11608 gl_image->ReleaseTexImage(target);
11611 texture_manager()->SetLevelInfo(
11612 texture_ref, target, 0, GL_RGBA, 0, 0, 1, 0,
11613 GL_RGBA, GL_UNSIGNED_BYTE, false);
11616 error::Error GLES2DecoderImpl::HandleTraceBeginCHROMIUM(
11617 uint32 immediate_data_size,
11618 const void* cmd_data) {
11619 const gles2::cmds::TraceBeginCHROMIUM& c =
11620 *static_cast<const gles2::cmds::TraceBeginCHROMIUM*>(cmd_data);
11621 Bucket* category_bucket = GetBucket(c.category_bucket_id);
11622 Bucket* name_bucket = GetBucket(c.name_bucket_id);
11623 if (!category_bucket || category_bucket->size() == 0 ||
11624 !name_bucket || name_bucket->size() == 0) {
11625 return error::kInvalidArguments;
11628 std::string category_name;
11629 std::string trace_name;
11630 if (!category_bucket->GetAsString(&category_name) ||
11631 !name_bucket->GetAsString(&trace_name)) {
11632 return error::kInvalidArguments;
11635 if (!gpu_tracer_->Begin(category_name, trace_name, kTraceCHROMIUM)) {
11636 LOCAL_SET_GL_ERROR(
11637 GL_INVALID_OPERATION,
11638 "glTraceBeginCHROMIUM", "unable to create begin trace");
11639 return error::kNoError;
11641 return error::kNoError;
11644 void GLES2DecoderImpl::DoTraceEndCHROMIUM() {
11645 if (!gpu_tracer_->End(kTraceCHROMIUM)) {
11646 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
11647 "glTraceEndCHROMIUM", "no trace begin found");
11648 return;
11652 void GLES2DecoderImpl::DoDrawBuffersEXT(
11653 GLsizei count, const GLenum* bufs) {
11654 if (count > static_cast<GLsizei>(group_->max_draw_buffers())) {
11655 LOCAL_SET_GL_ERROR(
11656 GL_INVALID_VALUE,
11657 "glDrawBuffersEXT", "greater than GL_MAX_DRAW_BUFFERS_EXT");
11658 return;
11661 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
11662 if (framebuffer) {
11663 for (GLsizei i = 0; i < count; ++i) {
11664 if (bufs[i] != static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i) &&
11665 bufs[i] != GL_NONE) {
11666 LOCAL_SET_GL_ERROR(
11667 GL_INVALID_OPERATION,
11668 "glDrawBuffersEXT",
11669 "bufs[i] not GL_NONE or GL_COLOR_ATTACHMENTi_EXT");
11670 return;
11673 glDrawBuffersARB(count, bufs);
11674 framebuffer->SetDrawBuffers(count, bufs);
11675 } else { // backbuffer
11676 if (count > 1 ||
11677 (bufs[0] != GL_BACK && bufs[0] != GL_NONE)) {
11678 LOCAL_SET_GL_ERROR(
11679 GL_INVALID_OPERATION,
11680 "glDrawBuffersEXT",
11681 "more than one buffer or bufs not GL_NONE or GL_BACK");
11682 return;
11684 GLenum mapped_buf = bufs[0];
11685 if (GetBackbufferServiceId() != 0 && // emulated backbuffer
11686 bufs[0] == GL_BACK) {
11687 mapped_buf = GL_COLOR_ATTACHMENT0;
11689 glDrawBuffersARB(count, &mapped_buf);
11690 group_->set_draw_buffer(bufs[0]);
11694 void GLES2DecoderImpl::DoLoseContextCHROMIUM(GLenum current, GLenum other) {
11695 group_->LoseContexts(other);
11696 reset_status_ = current;
11697 current_decoder_error_ = error::kLostContext;
11700 void GLES2DecoderImpl::DoMatrixLoadfCHROMIUM(GLenum matrix_mode,
11701 const GLfloat* matrix) {
11702 DCHECK(matrix_mode == GL_PATH_PROJECTION_CHROMIUM ||
11703 matrix_mode == GL_PATH_MODELVIEW_CHROMIUM);
11704 if (!features().chromium_path_rendering) {
11705 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
11706 "glMatrixLoadfCHROMIUM",
11707 "function not available");
11708 return;
11711 GLfloat* target_matrix = matrix_mode == GL_PATH_PROJECTION_CHROMIUM
11712 ? state_.projection_matrix
11713 : state_.modelview_matrix;
11714 memcpy(target_matrix, matrix, sizeof(GLfloat) * 16);
11715 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
11716 // since the values of the _NV and _CHROMIUM tokens match.
11717 glMatrixLoadfEXT(matrix_mode, matrix);
11720 void GLES2DecoderImpl::DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode) {
11721 DCHECK(matrix_mode == GL_PATH_PROJECTION_CHROMIUM ||
11722 matrix_mode == GL_PATH_MODELVIEW_CHROMIUM);
11724 if (!features().chromium_path_rendering) {
11725 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
11726 "glMatrixLoadIdentityCHROMIUM",
11727 "function not available");
11728 return;
11731 static GLfloat kIdentityMatrix[16] = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
11732 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
11733 0.0f, 0.0f, 0.0f, 1.0f};
11735 GLfloat* target_matrix = matrix_mode == GL_PATH_PROJECTION_CHROMIUM
11736 ? state_.projection_matrix
11737 : state_.modelview_matrix;
11738 memcpy(target_matrix, kIdentityMatrix, sizeof(kIdentityMatrix));
11739 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
11740 // since the values of the _NV and _CHROMIUM tokens match.
11741 glMatrixLoadIdentityEXT(matrix_mode);
11744 bool GLES2DecoderImpl::ValidateAsyncTransfer(
11745 const char* function_name,
11746 TextureRef* texture_ref,
11747 GLenum target,
11748 GLint level,
11749 const void * data) {
11750 // We only support async uploads to 2D textures for now.
11751 if (GL_TEXTURE_2D != target) {
11752 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
11753 return false;
11755 // We only support uploads to level zero for now.
11756 if (level != 0) {
11757 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "level != 0");
11758 return false;
11760 // A transfer buffer must be bound, even for asyncTexImage2D.
11761 if (data == NULL) {
11762 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, "buffer == 0");
11763 return false;
11765 // We only support one async transfer in progress.
11766 if (!texture_ref ||
11767 async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
11768 LOCAL_SET_GL_ERROR(
11769 GL_INVALID_OPERATION,
11770 function_name, "transfer already in progress");
11771 return false;
11773 return true;
11776 base::Closure GLES2DecoderImpl::AsyncUploadTokenCompletionClosure(
11777 uint32 async_upload_token,
11778 uint32 sync_data_shm_id,
11779 uint32 sync_data_shm_offset) {
11780 scoped_refptr<gpu::Buffer> buffer = GetSharedMemoryBuffer(sync_data_shm_id);
11781 if (!buffer.get() ||
11782 !buffer->GetDataAddress(sync_data_shm_offset, sizeof(AsyncUploadSync)))
11783 return base::Closure();
11785 AsyncMemoryParams mem_params(buffer,
11786 sync_data_shm_offset,
11787 sizeof(AsyncUploadSync));
11789 scoped_refptr<AsyncUploadTokenCompletionObserver> observer(
11790 new AsyncUploadTokenCompletionObserver(async_upload_token));
11792 return base::Bind(
11793 &AsyncPixelTransferManager::AsyncNotifyCompletion,
11794 base::Unretained(GetAsyncPixelTransferManager()),
11795 mem_params,
11796 observer);
11799 error::Error GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM(
11800 uint32 immediate_data_size,
11801 const void* cmd_data) {
11802 const gles2::cmds::AsyncTexImage2DCHROMIUM& c =
11803 *static_cast<const gles2::cmds::AsyncTexImage2DCHROMIUM*>(cmd_data);
11804 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM");
11805 GLenum target = static_cast<GLenum>(c.target);
11806 GLint level = static_cast<GLint>(c.level);
11807 GLenum internal_format = static_cast<GLenum>(c.internalformat);
11808 GLsizei width = static_cast<GLsizei>(c.width);
11809 GLsizei height = static_cast<GLsizei>(c.height);
11810 GLint border = static_cast<GLint>(c.border);
11811 GLenum format = static_cast<GLenum>(c.format);
11812 GLenum type = static_cast<GLenum>(c.type);
11813 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
11814 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
11815 uint32 pixels_size;
11816 uint32 async_upload_token = static_cast<uint32>(c.async_upload_token);
11817 uint32 sync_data_shm_id = static_cast<uint32>(c.sync_data_shm_id);
11818 uint32 sync_data_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
11820 base::ScopedClosureRunner scoped_completion_callback;
11821 if (async_upload_token) {
11822 base::Closure completion_closure =
11823 AsyncUploadTokenCompletionClosure(async_upload_token,
11824 sync_data_shm_id,
11825 sync_data_shm_offset);
11826 if (completion_closure.is_null())
11827 return error::kInvalidArguments;
11829 scoped_completion_callback.Reset(completion_closure);
11832 // TODO(epenner): Move this and copies of this memory validation
11833 // into ValidateTexImage2D step.
11834 if (!GLES2Util::ComputeImageDataSizes(
11835 width, height, 1, format, type, state_.unpack_alignment, &pixels_size,
11836 NULL, NULL)) {
11837 return error::kOutOfBounds;
11839 const void* pixels = NULL;
11840 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
11841 pixels = GetSharedMemoryAs<const void*>(
11842 pixels_shm_id, pixels_shm_offset, pixels_size);
11843 if (!pixels) {
11844 return error::kOutOfBounds;
11848 TextureManager::DoTextImage2DArguments args = {
11849 target, level, internal_format, width, height, border, format, type,
11850 pixels, pixels_size};
11851 TextureRef* texture_ref;
11852 // All the normal glTexSubImage2D validation.
11853 if (!texture_manager()->ValidateTexImage2D(
11854 &state_, "glAsyncTexImage2DCHROMIUM", args, &texture_ref)) {
11855 return error::kNoError;
11858 // Extra async validation.
11859 Texture* texture = texture_ref->texture();
11860 if (!ValidateAsyncTransfer(
11861 "glAsyncTexImage2DCHROMIUM", texture_ref, target, level, pixels))
11862 return error::kNoError;
11864 // Don't allow async redefinition of a textures.
11865 if (texture->IsDefined()) {
11866 LOCAL_SET_GL_ERROR(
11867 GL_INVALID_OPERATION,
11868 "glAsyncTexImage2DCHROMIUM", "already defined");
11869 return error::kNoError;
11872 if (!EnsureGPUMemoryAvailable(pixels_size)) {
11873 LOCAL_SET_GL_ERROR(
11874 GL_OUT_OF_MEMORY, "glAsyncTexImage2DCHROMIUM", "out of memory");
11875 return error::kNoError;
11878 // Setup the parameters.
11879 AsyncTexImage2DParams tex_params = {
11880 target, level, static_cast<GLenum>(internal_format),
11881 width, height, border, format, type};
11882 AsyncMemoryParams mem_params(
11883 GetSharedMemoryBuffer(c.pixels_shm_id), c.pixels_shm_offset, pixels_size);
11885 // Set up the async state if needed, and make the texture
11886 // immutable so the async state stays valid. The level info
11887 // is set up lazily when the transfer completes.
11888 AsyncPixelTransferDelegate* delegate =
11889 async_pixel_transfer_manager_->CreatePixelTransferDelegate(texture_ref,
11890 tex_params);
11891 texture->SetImmutable(true);
11893 delegate->AsyncTexImage2D(
11894 tex_params,
11895 mem_params,
11896 base::Bind(&TextureManager::SetLevelInfoFromParams,
11897 // The callback is only invoked if the transfer delegate still
11898 // exists, which implies through manager->texture_ref->state
11899 // ownership that both of these pointers are valid.
11900 base::Unretained(texture_manager()),
11901 base::Unretained(texture_ref),
11902 tex_params));
11903 return error::kNoError;
11906 error::Error GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM(
11907 uint32 immediate_data_size,
11908 const void* cmd_data) {
11909 const gles2::cmds::AsyncTexSubImage2DCHROMIUM& c =
11910 *static_cast<const gles2::cmds::AsyncTexSubImage2DCHROMIUM*>(cmd_data);
11911 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM");
11912 GLenum target = static_cast<GLenum>(c.target);
11913 GLint level = static_cast<GLint>(c.level);
11914 GLint xoffset = static_cast<GLint>(c.xoffset);
11915 GLint yoffset = static_cast<GLint>(c.yoffset);
11916 GLsizei width = static_cast<GLsizei>(c.width);
11917 GLsizei height = static_cast<GLsizei>(c.height);
11918 GLenum format = static_cast<GLenum>(c.format);
11919 GLenum type = static_cast<GLenum>(c.type);
11920 uint32 async_upload_token = static_cast<uint32>(c.async_upload_token);
11921 uint32 sync_data_shm_id = static_cast<uint32>(c.sync_data_shm_id);
11922 uint32 sync_data_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
11924 base::ScopedClosureRunner scoped_completion_callback;
11925 if (async_upload_token) {
11926 base::Closure completion_closure =
11927 AsyncUploadTokenCompletionClosure(async_upload_token,
11928 sync_data_shm_id,
11929 sync_data_shm_offset);
11930 if (completion_closure.is_null())
11931 return error::kInvalidArguments;
11933 scoped_completion_callback.Reset(completion_closure);
11936 // TODO(epenner): Move this and copies of this memory validation
11937 // into ValidateTexSubImage2D step.
11938 uint32 data_size;
11939 if (!GLES2Util::ComputeImageDataSizes(
11940 width, height, 1, format, type, state_.unpack_alignment, &data_size,
11941 NULL, NULL)) {
11942 return error::kOutOfBounds;
11944 const void* pixels = GetSharedMemoryAs<const void*>(
11945 c.data_shm_id, c.data_shm_offset, data_size);
11947 // All the normal glTexSubImage2D validation.
11948 error::Error error = error::kNoError;
11949 if (!ValidateTexSubImage2D(&error, "glAsyncTexSubImage2DCHROMIUM",
11950 target, level, xoffset, yoffset, width, height, format, type, pixels)) {
11951 return error;
11954 // Extra async validation.
11955 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
11956 &state_, target);
11957 Texture* texture = texture_ref->texture();
11958 if (!ValidateAsyncTransfer(
11959 "glAsyncTexSubImage2DCHROMIUM", texture_ref, target, level, pixels))
11960 return error::kNoError;
11962 // Guarantee async textures are always 'cleared' as follows:
11963 // - AsyncTexImage2D can not redefine an existing texture
11964 // - AsyncTexImage2D must initialize the entire image via non-null buffer.
11965 // - AsyncTexSubImage2D clears synchronously if not already cleared.
11966 // - Textures become immutable after an async call.
11967 // This way we know in all cases that an async texture is always clear.
11968 if (!texture->SafeToRenderFrom()) {
11969 if (!texture_manager()->ClearTextureLevel(this, texture_ref,
11970 target, level)) {
11971 LOCAL_SET_GL_ERROR(
11972 GL_OUT_OF_MEMORY,
11973 "glAsyncTexSubImage2DCHROMIUM", "dimensions too big");
11974 return error::kNoError;
11978 // Setup the parameters.
11979 AsyncTexSubImage2DParams tex_params = {target, level, xoffset, yoffset,
11980 width, height, format, type};
11981 AsyncMemoryParams mem_params(
11982 GetSharedMemoryBuffer(c.data_shm_id), c.data_shm_offset, data_size);
11983 AsyncPixelTransferDelegate* delegate =
11984 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
11985 if (!delegate) {
11986 // TODO(epenner): We may want to enforce exclusive use
11987 // of async APIs in which case this should become an error,
11988 // (the texture should have been async defined).
11989 AsyncTexImage2DParams define_params = {target, level,
11990 0, 0, 0, 0, 0, 0};
11991 texture->GetLevelSize(target, level, &define_params.width,
11992 &define_params.height);
11993 texture->GetLevelType(target, level, &define_params.type,
11994 &define_params.internal_format);
11995 // Set up the async state if needed, and make the texture
11996 // immutable so the async state stays valid.
11997 delegate = async_pixel_transfer_manager_->CreatePixelTransferDelegate(
11998 texture_ref, define_params);
11999 texture->SetImmutable(true);
12002 delegate->AsyncTexSubImage2D(tex_params, mem_params);
12003 return error::kNoError;
12006 error::Error GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM(
12007 uint32 immediate_data_size,
12008 const void* cmd_data) {
12009 const gles2::cmds::WaitAsyncTexImage2DCHROMIUM& c =
12010 *static_cast<const gles2::cmds::WaitAsyncTexImage2DCHROMIUM*>(cmd_data);
12011 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
12012 GLenum target = static_cast<GLenum>(c.target);
12014 if (GL_TEXTURE_2D != target) {
12015 LOCAL_SET_GL_ERROR(
12016 GL_INVALID_ENUM, "glWaitAsyncTexImage2DCHROMIUM", "target");
12017 return error::kNoError;
12019 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
12020 &state_, target);
12021 if (!texture_ref) {
12022 LOCAL_SET_GL_ERROR(
12023 GL_INVALID_OPERATION,
12024 "glWaitAsyncTexImage2DCHROMIUM", "unknown texture");
12025 return error::kNoError;
12027 AsyncPixelTransferDelegate* delegate =
12028 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
12029 if (!delegate) {
12030 LOCAL_SET_GL_ERROR(
12031 GL_INVALID_OPERATION,
12032 "glWaitAsyncTexImage2DCHROMIUM", "No async transfer started");
12033 return error::kNoError;
12035 delegate->WaitForTransferCompletion();
12036 ProcessFinishedAsyncTransfers();
12037 return error::kNoError;
12040 error::Error GLES2DecoderImpl::HandleWaitAllAsyncTexImage2DCHROMIUM(
12041 uint32 immediate_data_size,
12042 const void* data) {
12043 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
12045 GetAsyncPixelTransferManager()->WaitAllAsyncTexImage2D();
12046 ProcessFinishedAsyncTransfers();
12047 return error::kNoError;
12050 error::Error GLES2DecoderImpl::HandleUniformBlockBinding(
12051 uint32_t immediate_data_size, const void* cmd_data) {
12052 if (!unsafe_es3_apis_enabled())
12053 return error::kUnknownCommand;
12054 const gles2::cmds::UniformBlockBinding& c =
12055 *static_cast<const gles2::cmds::UniformBlockBinding*>(cmd_data);
12056 GLuint client_id = c.program;
12057 GLuint index = static_cast<GLuint>(c.index);
12058 GLuint binding = static_cast<GLuint>(c.binding);
12059 Program* program = GetProgramInfoNotShader(
12060 client_id, "glUniformBlockBinding");
12061 if (!program) {
12062 return error::kNoError;
12064 GLuint service_id = program->service_id();
12065 glUniformBlockBinding(service_id, index, binding);
12066 return error::kNoError;
12069 error::Error GLES2DecoderImpl::HandleClientWaitSync(
12070 uint32_t immediate_data_size, const void* cmd_data) {
12071 if (!unsafe_es3_apis_enabled())
12072 return error::kUnknownCommand;
12073 const gles2::cmds::ClientWaitSync& c =
12074 *static_cast<const gles2::cmds::ClientWaitSync*>(cmd_data);
12075 GLuint sync = static_cast<GLuint>(c.sync);
12076 GLbitfield flags = static_cast<GLbitfield>(c.flags);
12077 GLuint64 timeout = GLES2Util::MapTwoUint32ToUint64(c.timeout_0, c.timeout_1);
12078 typedef cmds::ClientWaitSync::Result Result;
12079 Result* result_dst = GetSharedMemoryAs<Result*>(
12080 c.result_shm_id, c.result_shm_offset, sizeof(*result_dst));
12081 if (!result_dst) {
12082 return error::kOutOfBounds;
12084 if (*result_dst != GL_WAIT_FAILED) {
12085 return error::kInvalidArguments;
12087 GLsync service_sync = 0;
12088 if (!group_->GetSyncServiceId(sync, &service_sync)) {
12089 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "ClientWaitSync", "invalid sync");
12090 return error::kNoError;
12092 *result_dst = glClientWaitSync(service_sync, flags, timeout);
12093 return error::kNoError;
12096 error::Error GLES2DecoderImpl::HandleWaitSync(
12097 uint32_t immediate_data_size, const void* cmd_data) {
12098 if (!unsafe_es3_apis_enabled())
12099 return error::kUnknownCommand;
12100 const gles2::cmds::WaitSync& c =
12101 *static_cast<const gles2::cmds::WaitSync*>(cmd_data);
12102 GLuint sync = static_cast<GLuint>(c.sync);
12103 GLbitfield flags = static_cast<GLbitfield>(c.flags);
12104 GLuint64 timeout = GLES2Util::MapTwoUint32ToUint64(c.timeout_0, c.timeout_1);
12105 GLsync service_sync = 0;
12106 if (!group_->GetSyncServiceId(sync, &service_sync)) {
12107 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "WaitSync", "invalid sync");
12108 return error::kNoError;
12110 glWaitSync(service_sync, flags, timeout);
12111 return error::kNoError;
12114 void GLES2DecoderImpl::OnTextureRefDetachedFromFramebuffer(
12115 TextureRef* texture_ref) {
12116 Texture* texture = texture_ref->texture();
12117 DoDidUseTexImageIfNeeded(texture, texture->target());
12120 void GLES2DecoderImpl::OnContextLostError() {
12121 group_->LoseContexts(GL_UNKNOWN_CONTEXT_RESET_ARB);
12124 void GLES2DecoderImpl::OnOutOfMemoryError() {
12125 if (lose_context_when_out_of_memory_) {
12126 group_->LoseContexts(GL_UNKNOWN_CONTEXT_RESET_ARB);
12130 // Include the auto-generated part of this file. We split this because it means
12131 // we can easily edit the non-auto generated parts right here in this file
12132 // instead of having to edit some template or the code generator.
12133 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
12135 } // namespace gles2
12136 } // namespace gpu