Don't show supervised user as "already on this device" while they're being imported.
[chromium-blink-merge.git] / gpu / command_buffer / service / gles2_cmd_decoder.cc
blob1e8e80f6a87499709255fbef02041e49febe680a
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
7 #include <stdio.h>
9 #include <algorithm>
10 #include <cmath>
11 #include <list>
12 #include <map>
13 #include <queue>
14 #include <stack>
15 #include <string>
16 #include <vector>
18 #include "base/at_exit.h"
19 #include "base/bind.h"
20 #include "base/callback_helpers.h"
21 #include "base/command_line.h"
22 #include "base/memory/scoped_ptr.h"
23 #include "base/numerics/safe_math.h"
24 #include "base/strings/string_number_conversions.h"
25 #include "base/strings/string_split.h"
26 #include "base/trace_event/trace_event.h"
27 #include "base/trace_event/trace_event_synthetic_delay.h"
28 #include "build/build_config.h"
29 #define GLES2_GPU_SERVICE 1
30 #include "gpu/command_buffer/common/debug_marker_manager.h"
31 #include "gpu/command_buffer/common/gles2_cmd_format.h"
32 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
33 #include "gpu/command_buffer/common/id_allocator.h"
34 #include "gpu/command_buffer/common/mailbox.h"
35 #include "gpu/command_buffer/service/async_pixel_transfer_delegate.h"
36 #include "gpu/command_buffer/service/async_pixel_transfer_manager.h"
37 #include "gpu/command_buffer/service/buffer_manager.h"
38 #include "gpu/command_buffer/service/cmd_buffer_engine.h"
39 #include "gpu/command_buffer/service/context_group.h"
40 #include "gpu/command_buffer/service/context_state.h"
41 #include "gpu/command_buffer/service/error_state.h"
42 #include "gpu/command_buffer/service/feature_info.h"
43 #include "gpu/command_buffer/service/framebuffer_manager.h"
44 #include "gpu/command_buffer/service/gl_utils.h"
45 #include "gpu/command_buffer/service/gles2_cmd_clear_framebuffer.h"
46 #include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h"
47 #include "gpu/command_buffer/service/gles2_cmd_validation.h"
48 #include "gpu/command_buffer/service/gpu_state_tracer.h"
49 #include "gpu/command_buffer/service/gpu_switches.h"
50 #include "gpu/command_buffer/service/gpu_tracer.h"
51 #include "gpu/command_buffer/service/image_manager.h"
52 #include "gpu/command_buffer/service/mailbox_manager.h"
53 #include "gpu/command_buffer/service/memory_tracking.h"
54 #include "gpu/command_buffer/service/program_manager.h"
55 #include "gpu/command_buffer/service/query_manager.h"
56 #include "gpu/command_buffer/service/renderbuffer_manager.h"
57 #include "gpu/command_buffer/service/shader_manager.h"
58 #include "gpu/command_buffer/service/shader_translator.h"
59 #include "gpu/command_buffer/service/shader_translator_cache.h"
60 #include "gpu/command_buffer/service/texture_manager.h"
61 #include "gpu/command_buffer/service/valuebuffer_manager.h"
62 #include "gpu/command_buffer/service/vertex_array_manager.h"
63 #include "gpu/command_buffer/service/vertex_attrib_manager.h"
64 #include "third_party/smhasher/src/City.h"
65 #include "ui/gl/gl_fence.h"
66 #include "ui/gl/gl_image.h"
67 #include "ui/gl/gl_implementation.h"
68 #include "ui/gl/gl_surface.h"
70 #if defined(OS_MACOSX)
71 #include <IOSurface/IOSurfaceAPI.h>
72 // Note that this must be included after gl_bindings.h to avoid conflicts.
73 #include <OpenGL/CGLIOSurface.h>
74 #endif
76 #if defined(OS_WIN)
77 #include "base/win/win_util.h"
78 #endif
80 namespace gpu {
81 namespace gles2 {
83 namespace {
85 const char kOESDerivativeExtension[] = "GL_OES_standard_derivatives";
86 const char kEXTFragDepthExtension[] = "GL_EXT_frag_depth";
87 const char kEXTDrawBuffersExtension[] = "GL_EXT_draw_buffers";
88 const char kEXTShaderTextureLodExtension[] = "GL_EXT_shader_texture_lod";
90 const GLfloat kIdentityMatrix[16] = {1.0f, 0.0f, 0.0f, 0.0f,
91 0.0f, 1.0f, 0.0f, 0.0f,
92 0.0f, 0.0f, 1.0f, 0.0f,
93 0.0f, 0.0f, 0.0f, 1.0f};
95 bool PrecisionMeetsSpecForHighpFloat(GLint rangeMin,
96 GLint rangeMax,
97 GLint precision) {
98 return (rangeMin >= 62) && (rangeMax >= 62) && (precision >= 16);
101 void GetShaderPrecisionFormatImpl(GLenum shader_type,
102 GLenum precision_type,
103 GLint* range, GLint* precision) {
104 switch (precision_type) {
105 case GL_LOW_INT:
106 case GL_MEDIUM_INT:
107 case GL_HIGH_INT:
108 // These values are for a 32-bit twos-complement integer format.
109 range[0] = 31;
110 range[1] = 30;
111 *precision = 0;
112 break;
113 case GL_LOW_FLOAT:
114 case GL_MEDIUM_FLOAT:
115 case GL_HIGH_FLOAT:
116 // These values are for an IEEE single-precision floating-point format.
117 range[0] = 127;
118 range[1] = 127;
119 *precision = 23;
120 break;
121 default:
122 NOTREACHED();
123 break;
126 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
127 gfx::g_driver_gl.fn.glGetShaderPrecisionFormatFn) {
128 // This function is sometimes defined even though it's really just
129 // a stub, so we need to set range and precision as if it weren't
130 // defined before calling it.
131 // On Mac OS with some GPUs, calling this generates a
132 // GL_INVALID_OPERATION error. Avoid calling it on non-GLES2
133 // platforms.
134 glGetShaderPrecisionFormat(shader_type, precision_type,
135 range, precision);
137 // TODO(brianderson): Make the following official workarounds.
139 // Some drivers have bugs where they report the ranges as a negative number.
140 // Taking the absolute value here shouldn't hurt because negative numbers
141 // aren't expected anyway.
142 range[0] = abs(range[0]);
143 range[1] = abs(range[1]);
145 // If the driver reports a precision for highp float that isn't actually
146 // highp, don't pretend like it's supported because shader compilation will
147 // fail anyway.
148 if (precision_type == GL_HIGH_FLOAT &&
149 !PrecisionMeetsSpecForHighpFloat(range[0], range[1], *precision)) {
150 range[0] = 0;
151 range[1] = 0;
152 *precision = 0;
157 gfx::OverlayTransform GetGFXOverlayTransform(GLenum plane_transform) {
158 switch (plane_transform) {
159 case GL_OVERLAY_TRANSFORM_NONE_CHROMIUM:
160 return gfx::OVERLAY_TRANSFORM_NONE;
161 case GL_OVERLAY_TRANSFORM_FLIP_HORIZONTAL_CHROMIUM:
162 return gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL;
163 case GL_OVERLAY_TRANSFORM_FLIP_VERTICAL_CHROMIUM:
164 return gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL;
165 case GL_OVERLAY_TRANSFORM_ROTATE_90_CHROMIUM:
166 return gfx::OVERLAY_TRANSFORM_ROTATE_90;
167 case GL_OVERLAY_TRANSFORM_ROTATE_180_CHROMIUM:
168 return gfx::OVERLAY_TRANSFORM_ROTATE_180;
169 case GL_OVERLAY_TRANSFORM_ROTATE_270_CHROMIUM:
170 return gfx::OVERLAY_TRANSFORM_ROTATE_270;
171 default:
172 return gfx::OVERLAY_TRANSFORM_INVALID;
176 template <typename MANAGER_TYPE, typename OBJECT_TYPE>
177 GLuint GetClientId(const MANAGER_TYPE* manager, const OBJECT_TYPE* object) {
178 DCHECK(manager);
179 GLuint client_id = 0;
180 if (object) {
181 manager->GetClientId(object->service_id(), &client_id);
183 return client_id;
186 struct Vec4f {
187 explicit Vec4f(const Vec4& data) {
188 data.GetValues(v);
191 GLfloat v[4];
194 } // namespace
196 class GLES2DecoderImpl;
198 // Local versions of the SET_GL_ERROR macros
199 #define LOCAL_SET_GL_ERROR(error, function_name, msg) \
200 ERRORSTATE_SET_GL_ERROR(state_.GetErrorState(), error, function_name, msg)
201 #define LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, value, label) \
202 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(state_.GetErrorState(), \
203 function_name, value, label)
204 #define LOCAL_SET_GL_ERROR_INVALID_PARAM(error, function_name, pname) \
205 ERRORSTATE_SET_GL_ERROR_INVALID_PARAM(state_.GetErrorState(), error, \
206 function_name, pname)
207 #define LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name) \
208 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(state_.GetErrorState(), \
209 function_name)
210 #define LOCAL_PEEK_GL_ERROR(function_name) \
211 ERRORSTATE_PEEK_GL_ERROR(state_.GetErrorState(), function_name)
212 #define LOCAL_CLEAR_REAL_GL_ERRORS(function_name) \
213 ERRORSTATE_CLEAR_REAL_GL_ERRORS(state_.GetErrorState(), function_name)
214 #define LOCAL_PERFORMANCE_WARNING(msg) \
215 PerformanceWarning(__FILE__, __LINE__, msg)
216 #define LOCAL_RENDER_WARNING(msg) \
217 RenderWarning(__FILE__, __LINE__, msg)
219 // Check that certain assumptions the code makes are true. There are places in
220 // the code where shared memory is passed direclty to GL. Example, glUniformiv,
221 // glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
222 // a few others) are 32bits. If they are not 32bits the code will have to change
223 // to call those GL functions with service side memory and then copy the results
224 // to shared memory, converting the sizes.
225 static_assert(sizeof(GLint) == sizeof(uint32), // NOLINT
226 "GLint should be the same size as uint32");
227 static_assert(sizeof(GLsizei) == sizeof(uint32), // NOLINT
228 "GLsizei should be the same size as uint32");
229 static_assert(sizeof(GLfloat) == sizeof(float), // NOLINT
230 "GLfloat should be the same size as float");
232 // TODO(kbr): the use of this anonymous namespace core dumps the
233 // linker on Mac OS X 10.6 when the symbol ordering file is used
234 // namespace {
236 // Returns the address of the first byte after a struct.
237 template <typename T>
238 const void* AddressAfterStruct(const T& pod) {
239 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
242 // Returns the address of the frst byte after the struct or NULL if size >
243 // immediate_data_size.
244 template <typename RETURN_TYPE, typename COMMAND_TYPE>
245 RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod,
246 uint32 size,
247 uint32 immediate_data_size) {
248 return (size <= immediate_data_size) ?
249 static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))) :
250 NULL;
253 // Computes the data size for certain gl commands like glUniform.
254 bool ComputeDataSize(
255 GLuint count,
256 size_t size,
257 unsigned int elements_per_unit,
258 uint32* dst) {
259 uint32 value;
260 if (!SafeMultiplyUint32(count, size, &value)) {
261 return false;
263 if (!SafeMultiplyUint32(value, elements_per_unit, &value)) {
264 return false;
266 *dst = value;
267 return true;
270 // Return true if a character belongs to the ASCII subset as defined in
271 // GLSL ES 1.0 spec section 3.1.
272 static bool CharacterIsValidForGLES(unsigned char c) {
273 // Printing characters are valid except " $ ` @ \ ' DEL.
274 if (c >= 32 && c <= 126 &&
275 c != '"' &&
276 c != '$' &&
277 c != '`' &&
278 c != '@' &&
279 c != '\\' &&
280 c != '\'') {
281 return true;
283 // Horizontal tab, line feed, vertical tab, form feed, carriage return
284 // are also valid.
285 if (c >= 9 && c <= 13) {
286 return true;
289 return false;
292 static bool StringIsValidForGLES(const char* str) {
293 for (; *str; ++str) {
294 if (!CharacterIsValidForGLES(*str)) {
295 return false;
298 return true;
301 // This class prevents any GL errors that occur when it is in scope from
302 // being reported to the client.
303 class ScopedGLErrorSuppressor {
304 public:
305 explicit ScopedGLErrorSuppressor(
306 const char* function_name, ErrorState* error_state);
307 ~ScopedGLErrorSuppressor();
308 private:
309 const char* function_name_;
310 ErrorState* error_state_;
311 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor);
314 // Temporarily changes a decoder's bound texture and restore it when this
315 // object goes out of scope. Also temporarily switches to using active texture
316 // unit zero in case the client has changed that to something invalid.
317 class ScopedTextureBinder {
318 public:
319 explicit ScopedTextureBinder(ContextState* state, GLuint id, GLenum target);
320 ~ScopedTextureBinder();
322 private:
323 ContextState* state_;
324 GLenum target_;
325 DISALLOW_COPY_AND_ASSIGN(ScopedTextureBinder);
328 // Temporarily changes a decoder's bound render buffer and restore it when this
329 // object goes out of scope.
330 class ScopedRenderBufferBinder {
331 public:
332 explicit ScopedRenderBufferBinder(ContextState* state, GLuint id);
333 ~ScopedRenderBufferBinder();
335 private:
336 ContextState* state_;
337 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder);
340 // Temporarily changes a decoder's bound frame buffer and restore it when this
341 // object goes out of scope.
342 class ScopedFrameBufferBinder {
343 public:
344 explicit ScopedFrameBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
345 ~ScopedFrameBufferBinder();
347 private:
348 GLES2DecoderImpl* decoder_;
349 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder);
352 // Temporarily changes a decoder's bound frame buffer to a resolved version of
353 // the multisampled offscreen render buffer if that buffer is multisampled, and,
354 // if it is bound or enforce_internal_framebuffer is true. If internal is
355 // true, the resolved framebuffer is not visible to the parent.
356 class ScopedResolvedFrameBufferBinder {
357 public:
358 explicit ScopedResolvedFrameBufferBinder(GLES2DecoderImpl* decoder,
359 bool enforce_internal_framebuffer,
360 bool internal);
361 ~ScopedResolvedFrameBufferBinder();
363 private:
364 GLES2DecoderImpl* decoder_;
365 bool resolve_and_bind_;
366 DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder);
369 class ScopedModifyPixels {
370 public:
371 explicit ScopedModifyPixels(TextureRef* ref);
372 ~ScopedModifyPixels();
374 private:
375 TextureRef* ref_;
378 ScopedModifyPixels::ScopedModifyPixels(TextureRef* ref) : ref_(ref) {
379 if (ref_)
380 ref_->texture()->OnWillModifyPixels();
383 ScopedModifyPixels::~ScopedModifyPixels() {
384 if (ref_)
385 ref_->texture()->OnDidModifyPixels();
388 class ScopedRenderTo {
389 public:
390 explicit ScopedRenderTo(Framebuffer* framebuffer);
391 ~ScopedRenderTo();
393 private:
394 const Framebuffer* framebuffer_;
397 ScopedRenderTo::ScopedRenderTo(Framebuffer* framebuffer)
398 : framebuffer_(framebuffer) {
399 if (framebuffer)
400 framebuffer_->OnWillRenderTo();
403 ScopedRenderTo::~ScopedRenderTo() {
404 if (framebuffer_)
405 framebuffer_->OnDidRenderTo();
408 // Encapsulates an OpenGL texture.
409 class BackTexture {
410 public:
411 explicit BackTexture(MemoryTracker* memory_tracker, ContextState* state);
412 ~BackTexture();
414 // Create a new render texture.
415 void Create();
417 // Set the initial size and format of a render texture or resize it.
418 bool AllocateStorage(const gfx::Size& size, GLenum format, bool zero);
420 // Copy the contents of the currently bound frame buffer.
421 void Copy(const gfx::Size& size, GLenum format);
423 // Destroy the render texture. This must be explicitly called before
424 // destroying this object.
425 void Destroy();
427 // Invalidate the texture. This can be used when a context is lost and it is
428 // not possible to make it current in order to free the resource.
429 void Invalidate();
431 GLuint id() const {
432 return id_;
435 gfx::Size size() const {
436 return size_;
439 private:
440 MemoryTypeTracker memory_tracker_;
441 ContextState* state_;
442 size_t bytes_allocated_;
443 GLuint id_;
444 gfx::Size size_;
445 DISALLOW_COPY_AND_ASSIGN(BackTexture);
448 // Encapsulates an OpenGL render buffer of any format.
449 class BackRenderbuffer {
450 public:
451 explicit BackRenderbuffer(
452 RenderbufferManager* renderbuffer_manager,
453 MemoryTracker* memory_tracker,
454 ContextState* state);
455 ~BackRenderbuffer();
457 // Create a new render buffer.
458 void Create();
460 // Set the initial size and format of a render buffer or resize it.
461 bool AllocateStorage(const FeatureInfo* feature_info,
462 const gfx::Size& size,
463 GLenum format,
464 GLsizei samples);
466 // Destroy the render buffer. This must be explicitly called before destroying
467 // this object.
468 void Destroy();
470 // Invalidate the render buffer. This can be used when a context is lost and
471 // it is not possible to make it current in order to free the resource.
472 void Invalidate();
474 GLuint id() const {
475 return id_;
478 private:
479 RenderbufferManager* renderbuffer_manager_;
480 MemoryTypeTracker memory_tracker_;
481 ContextState* state_;
482 size_t bytes_allocated_;
483 GLuint id_;
484 DISALLOW_COPY_AND_ASSIGN(BackRenderbuffer);
487 // Encapsulates an OpenGL frame buffer.
488 class BackFramebuffer {
489 public:
490 explicit BackFramebuffer(GLES2DecoderImpl* decoder);
491 ~BackFramebuffer();
493 // Create a new frame buffer.
494 void Create();
496 // Attach a color render buffer to a frame buffer.
497 void AttachRenderTexture(BackTexture* texture);
499 // Attach a render buffer to a frame buffer. Note that this unbinds any
500 // currently bound frame buffer.
501 void AttachRenderBuffer(GLenum target, BackRenderbuffer* render_buffer);
503 // Destroy the frame buffer. This must be explicitly called before destroying
504 // this object.
505 void Destroy();
507 // Invalidate the frame buffer. This can be used when a context is lost and it
508 // is not possible to make it current in order to free the resource.
509 void Invalidate();
511 // See glCheckFramebufferStatusEXT.
512 GLenum CheckStatus();
514 GLuint id() const {
515 return id_;
518 private:
519 GLES2DecoderImpl* decoder_;
520 GLuint id_;
521 DISALLOW_COPY_AND_ASSIGN(BackFramebuffer);
524 struct FenceCallback {
525 FenceCallback()
526 : fence(gfx::GLFence::Create()) {
527 DCHECK(fence);
529 std::vector<base::Closure> callbacks;
530 scoped_ptr<gfx::GLFence> fence;
533 class AsyncUploadTokenCompletionObserver
534 : public AsyncPixelTransferCompletionObserver {
535 public:
536 explicit AsyncUploadTokenCompletionObserver(uint32 async_upload_token)
537 : async_upload_token_(async_upload_token) {
540 void DidComplete(const AsyncMemoryParams& mem_params) override {
541 DCHECK(mem_params.buffer().get());
542 void* data = mem_params.GetDataAddress();
543 AsyncUploadSync* sync = static_cast<AsyncUploadSync*>(data);
544 sync->SetAsyncUploadToken(async_upload_token_);
547 private:
548 ~AsyncUploadTokenCompletionObserver() override {}
550 uint32 async_upload_token_;
552 DISALLOW_COPY_AND_ASSIGN(AsyncUploadTokenCompletionObserver);
555 // } // anonymous namespace.
557 // static
558 const unsigned int GLES2Decoder::kDefaultStencilMask =
559 static_cast<unsigned int>(-1);
561 bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id,
562 uint32* service_texture_id) {
563 return false;
566 GLES2Decoder::GLES2Decoder()
567 : initialized_(false),
568 debug_(false),
569 log_commands_(false),
570 unsafe_es3_apis_enabled_(false) {
573 GLES2Decoder::~GLES2Decoder() {
576 void GLES2Decoder::BeginDecoding() {}
578 void GLES2Decoder::EndDecoding() {}
580 // This class implements GLES2Decoder so we don't have to expose all the GLES2
581 // cmd stuff to outside this class.
582 class GLES2DecoderImpl : public GLES2Decoder,
583 public FramebufferManager::TextureDetachObserver,
584 public ErrorStateClient {
585 public:
586 explicit GLES2DecoderImpl(ContextGroup* group);
587 ~GLES2DecoderImpl() override;
589 // Overridden from AsyncAPIInterface.
590 Error DoCommand(unsigned int command,
591 unsigned int arg_count,
592 const void* args) override;
594 error::Error DoCommands(unsigned int num_commands,
595 const void* buffer,
596 int num_entries,
597 int* entries_processed) override;
599 template <bool DebugImpl>
600 error::Error DoCommandsImpl(unsigned int num_commands,
601 const void* buffer,
602 int num_entries,
603 int* entries_processed);
605 // Overridden from AsyncAPIInterface.
606 const char* GetCommandName(unsigned int command_id) const override;
608 // Overridden from GLES2Decoder.
609 bool Initialize(const scoped_refptr<gfx::GLSurface>& surface,
610 const scoped_refptr<gfx::GLContext>& context,
611 bool offscreen,
612 const gfx::Size& offscreen_size,
613 const DisallowedFeatures& disallowed_features,
614 const std::vector<int32>& attribs) override;
615 void Destroy(bool have_context) override;
616 void SetSurface(const scoped_refptr<gfx::GLSurface>& surface) override;
617 void ProduceFrontBuffer(const Mailbox& mailbox) override;
618 bool ResizeOffscreenFrameBuffer(const gfx::Size& size) override;
619 void UpdateParentTextureInfo();
620 bool MakeCurrent() override;
621 GLES2Util* GetGLES2Util() override { return &util_; }
622 gfx::GLContext* GetGLContext() override { return context_.get(); }
623 ContextGroup* GetContextGroup() override { return group_.get(); }
624 Capabilities GetCapabilities() override;
625 void RestoreState(const ContextState* prev_state) override;
627 void RestoreActiveTexture() const override { state_.RestoreActiveTexture(); }
628 void RestoreAllTextureUnitBindings(
629 const ContextState* prev_state) const override {
630 state_.RestoreAllTextureUnitBindings(prev_state);
632 void RestoreActiveTextureUnitBinding(unsigned int target) const override {
633 state_.RestoreActiveTextureUnitBinding(target);
635 void RestoreBufferBindings() const override {
636 state_.RestoreBufferBindings();
638 void RestoreGlobalState() const override { state_.RestoreGlobalState(NULL); }
639 void RestoreProgramBindings() const override {
640 state_.RestoreProgramBindings();
642 void RestoreTextureUnitBindings(unsigned unit) const override {
643 state_.RestoreTextureUnitBindings(unit, NULL);
645 void RestoreFramebufferBindings() const override;
646 void RestoreRenderbufferBindings() override;
647 void RestoreTextureState(unsigned service_id) const override;
649 void ClearAllAttributes() const override;
650 void RestoreAllAttributes() const override;
652 QueryManager* GetQueryManager() override { return query_manager_.get(); }
653 VertexArrayManager* GetVertexArrayManager() override {
654 return vertex_array_manager_.get();
656 ImageManager* GetImageManager() override { return image_manager_.get(); }
658 ValuebufferManager* GetValuebufferManager() override {
659 return valuebuffer_manager();
662 bool ProcessPendingQueries(bool did_finish) override;
664 bool HasMoreIdleWork() override;
665 void PerformIdleWork() override;
667 void WaitForReadPixels(base::Closure callback) override;
669 void SetResizeCallback(
670 const base::Callback<void(gfx::Size, float)>& callback) override;
672 Logger* GetLogger() override;
674 void BeginDecoding() override;
675 void EndDecoding() override;
677 ErrorState* GetErrorState() override;
678 const ContextState* GetContextState() override { return &state_; }
680 void SetShaderCacheCallback(const ShaderCacheCallback& callback) override;
681 void SetWaitSyncPointCallback(const WaitSyncPointCallback& callback) override;
683 AsyncPixelTransferManager* GetAsyncPixelTransferManager() override;
684 void ResetAsyncPixelTransferManagerForTest() override;
685 void SetAsyncPixelTransferManagerForTest(
686 AsyncPixelTransferManager* manager) override;
687 void SetIgnoreCachedStateForTest(bool ignore) override;
688 void ProcessFinishedAsyncTransfers();
690 bool GetServiceTextureId(uint32 client_texture_id,
691 uint32* service_texture_id) override;
693 uint32 GetTextureUploadCount() override;
694 base::TimeDelta GetTotalTextureUploadTime() override;
695 base::TimeDelta GetTotalProcessingCommandsTime() override;
696 void AddProcessingCommandsTime(base::TimeDelta) override;
698 // Restores the current state to the user's settings.
699 void RestoreCurrentFramebufferBindings();
701 // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
702 void ApplyDirtyState();
704 // These check the state of the currently bound framebuffer or the
705 // backbuffer if no framebuffer is bound.
706 // If all_draw_buffers is false, only check with COLOR_ATTACHMENT0, otherwise
707 // check with all attached and enabled color attachments.
708 bool BoundFramebufferHasColorAttachmentWithAlpha(bool all_draw_buffers);
709 bool BoundFramebufferHasDepthAttachment();
710 bool BoundFramebufferHasStencilAttachment();
712 error::ContextLostReason GetContextLostReason() override;
714 // Overridden from FramebufferManager::TextureDetachObserver:
715 void OnTextureRefDetachedFromFramebuffer(TextureRef* texture) override;
717 // Overriden from ErrorStateClient.
718 void OnContextLostError() override;
719 void OnOutOfMemoryError() override;
721 // Ensure Renderbuffer corresponding to last DoBindRenderbuffer() is bound.
722 void EnsureRenderbufferBound();
724 // Helpers to facilitate calling into compatible extensions.
725 static void RenderbufferStorageMultisampleHelper(
726 const FeatureInfo* feature_info,
727 GLenum target,
728 GLsizei samples,
729 GLenum internal_format,
730 GLsizei width,
731 GLsizei height);
733 void BlitFramebufferHelper(GLint srcX0,
734 GLint srcY0,
735 GLint srcX1,
736 GLint srcY1,
737 GLint dstX0,
738 GLint dstY0,
739 GLint dstX1,
740 GLint dstY1,
741 GLbitfield mask,
742 GLenum filter);
744 private:
745 friend class ScopedFrameBufferBinder;
746 friend class ScopedResolvedFrameBufferBinder;
747 friend class BackFramebuffer;
749 // Initialize or re-initialize the shader translator.
750 bool InitializeShaderTranslator();
752 void UpdateCapabilities();
754 // Helpers for the glGen and glDelete functions.
755 bool GenTexturesHelper(GLsizei n, const GLuint* client_ids);
756 void DeleteTexturesHelper(GLsizei n, const GLuint* client_ids);
757 bool GenBuffersHelper(GLsizei n, const GLuint* client_ids);
758 void DeleteBuffersHelper(GLsizei n, const GLuint* client_ids);
759 bool GenFramebuffersHelper(GLsizei n, const GLuint* client_ids);
760 void DeleteFramebuffersHelper(GLsizei n, const GLuint* client_ids);
761 bool GenRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
762 void DeleteRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
763 bool GenValuebuffersCHROMIUMHelper(GLsizei n, const GLuint* client_ids);
764 void DeleteValuebuffersCHROMIUMHelper(GLsizei n, const GLuint* client_ids);
765 bool GenQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
766 void DeleteQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
767 bool GenVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
768 void DeleteVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
770 // Helper for async upload token completion notification callback.
771 base::Closure AsyncUploadTokenCompletionClosure(uint32 async_upload_token,
772 uint32 sync_data_shm_id,
773 uint32 sync_data_shm_offset);
777 // Workarounds
778 void OnFboChanged() const;
779 void OnUseFramebuffer() const;
781 error::ContextLostReason GetContextLostReasonFromResetStatus(
782 GLenum reset_status) const;
784 // TODO(gman): Cache these pointers?
785 BufferManager* buffer_manager() {
786 return group_->buffer_manager();
789 RenderbufferManager* renderbuffer_manager() {
790 return group_->renderbuffer_manager();
793 FramebufferManager* framebuffer_manager() {
794 return group_->framebuffer_manager();
797 ValuebufferManager* valuebuffer_manager() {
798 return group_->valuebuffer_manager();
801 ProgramManager* program_manager() {
802 return group_->program_manager();
805 ShaderManager* shader_manager() {
806 return group_->shader_manager();
809 ShaderTranslatorCache* shader_translator_cache() {
810 return group_->shader_translator_cache();
813 const TextureManager* texture_manager() const {
814 return group_->texture_manager();
817 TextureManager* texture_manager() {
818 return group_->texture_manager();
821 MailboxManager* mailbox_manager() {
822 return group_->mailbox_manager();
825 ImageManager* image_manager() { return image_manager_.get(); }
827 VertexArrayManager* vertex_array_manager() {
828 return vertex_array_manager_.get();
831 MemoryTracker* memory_tracker() {
832 return group_->memory_tracker();
835 bool EnsureGPUMemoryAvailable(size_t estimated_size) {
836 MemoryTracker* tracker = memory_tracker();
837 if (tracker) {
838 return tracker->EnsureGPUMemoryAvailable(estimated_size);
840 return true;
843 bool IsOffscreenBufferMultisampled() const {
844 return offscreen_target_samples_ > 1;
847 // Creates a Texture for the given texture.
848 TextureRef* CreateTexture(
849 GLuint client_id, GLuint service_id) {
850 return texture_manager()->CreateTexture(client_id, service_id);
853 // Gets the texture info for the given texture. Returns NULL if none exists.
854 TextureRef* GetTexture(GLuint client_id) const {
855 return texture_manager()->GetTexture(client_id);
858 // Deletes the texture info for the given texture.
859 void RemoveTexture(GLuint client_id) {
860 texture_manager()->RemoveTexture(client_id);
863 // Get the size (in pixels) of the currently bound frame buffer (either FBO
864 // or regular back buffer).
865 gfx::Size GetBoundReadFrameBufferSize();
867 // Get the format of the currently bound frame buffer (either FBO or regular
868 // back buffer)
869 GLenum GetBoundReadFrameBufferTextureType();
870 GLenum GetBoundReadFrameBufferInternalFormat();
871 GLenum GetBoundDrawFrameBufferInternalFormat();
873 // Wrapper for CompressedTexImage2D commands.
874 error::Error DoCompressedTexImage2D(
875 GLenum target,
876 GLint level,
877 GLenum internal_format,
878 GLsizei width,
879 GLsizei height,
880 GLint border,
881 GLsizei image_size,
882 const void* data);
884 // Wrapper for CompressedTexImage3D commands.
885 error::Error DoCompressedTexImage3D(
886 GLenum target,
887 GLint level,
888 GLenum internal_format,
889 GLsizei width,
890 GLsizei height,
891 GLsizei depth,
892 GLint border,
893 GLsizei image_size,
894 const void* data);
896 // Wrapper for CompressedTexSubImage2D.
897 void DoCompressedTexSubImage2D(
898 GLenum target,
899 GLint level,
900 GLint xoffset,
901 GLint yoffset,
902 GLsizei width,
903 GLsizei height,
904 GLenum format,
905 GLsizei imageSize,
906 const void * data);
908 // Wrapper for CompressedTexSubImage3D.
909 void DoCompressedTexSubImage3D(
910 GLenum target,
911 GLint level,
912 GLint xoffset,
913 GLint yoffset,
914 GLint zoffset,
915 GLsizei width,
916 GLsizei height,
917 GLsizei depth,
918 GLenum format,
919 GLsizei image_size,
920 const void* data);
922 // Wrapper for CopyTexImage2D.
923 void DoCopyTexImage2D(
924 GLenum target,
925 GLint level,
926 GLenum internal_format,
927 GLint x,
928 GLint y,
929 GLsizei width,
930 GLsizei height,
931 GLint border);
933 // Wrapper for SwapBuffers.
934 void DoSwapBuffers();
936 // Wrapper for SwapInterval.
937 void DoSwapInterval(int interval);
939 // Wrapper for CopyTexSubImage2D.
940 void DoCopyTexSubImage2D(
941 GLenum target,
942 GLint level,
943 GLint xoffset,
944 GLint yoffset,
945 GLint x,
946 GLint y,
947 GLsizei width,
948 GLsizei height);
950 // Validation for TexSubImage2D.
951 bool ValidateTexSubImage2D(
952 error::Error* error,
953 const char* function_name,
954 GLenum target,
955 GLint level,
956 GLint xoffset,
957 GLint yoffset,
958 GLsizei width,
959 GLsizei height,
960 GLenum format,
961 GLenum type,
962 const void * data);
964 // Wrapper for TexSubImage2D.
965 error::Error DoTexSubImage2D(
966 GLenum target,
967 GLint level,
968 GLint xoffset,
969 GLint yoffset,
970 GLsizei width,
971 GLsizei height,
972 GLenum format,
973 GLenum type,
974 const void * data);
976 // Wrapper for TexSubImage3D.
977 error::Error DoTexSubImage3D(
978 GLenum target,
979 GLint level,
980 GLint xoffset,
981 GLint yoffset,
982 GLint zoffset,
983 GLsizei width,
984 GLsizei height,
985 GLsizei depth,
986 GLenum format,
987 GLenum type,
988 const void * data);
990 // Extra validation for async tex(Sub)Image2D.
991 bool ValidateAsyncTransfer(
992 const char* function_name,
993 TextureRef* texture_ref,
994 GLenum target,
995 GLint level,
996 const void * data);
998 // Wrapper for TexImageIOSurface2DCHROMIUM.
999 void DoTexImageIOSurface2DCHROMIUM(
1000 GLenum target,
1001 GLsizei width,
1002 GLsizei height,
1003 GLuint io_surface_id,
1004 GLuint plane);
1006 void DoCopyTextureCHROMIUM(GLenum target,
1007 GLuint source_id,
1008 GLuint dest_id,
1009 GLenum internal_format,
1010 GLenum dest_type);
1012 void DoCopySubTextureCHROMIUM(GLenum target,
1013 GLuint source_id,
1014 GLuint dest_id,
1015 GLint xoffset,
1016 GLint yoffset,
1017 GLint x,
1018 GLint y,
1019 GLsizei width,
1020 GLsizei height);
1022 // Wrapper for TexStorage2DEXT.
1023 void DoTexStorage2DEXT(
1024 GLenum target,
1025 GLint levels,
1026 GLenum internal_format,
1027 GLsizei width,
1028 GLsizei height);
1030 void DoProduceTextureCHROMIUM(GLenum target, const GLbyte* key);
1031 void DoProduceTextureDirectCHROMIUM(GLuint texture, GLenum target,
1032 const GLbyte* key);
1033 void ProduceTextureRef(std::string func_name, TextureRef* texture_ref,
1034 GLenum target, const GLbyte* data);
1036 void EnsureTextureForClientId(GLenum target, GLuint client_id);
1037 void DoConsumeTextureCHROMIUM(GLenum target, const GLbyte* key);
1038 void DoCreateAndConsumeTextureCHROMIUM(GLenum target, const GLbyte* key,
1039 GLuint client_id);
1041 bool DoIsValuebufferCHROMIUM(GLuint client_id);
1042 void DoBindValueBufferCHROMIUM(GLenum target, GLuint valuebuffer);
1043 void DoSubscribeValueCHROMIUM(GLenum target, GLenum subscription);
1044 void DoPopulateSubscribedValuesCHROMIUM(GLenum target);
1045 void DoUniformValueBufferCHROMIUM(GLint location,
1046 GLenum target,
1047 GLenum subscription);
1049 void DoBindTexImage2DCHROMIUM(
1050 GLenum target,
1051 GLint image_id);
1052 void DoReleaseTexImage2DCHROMIUM(
1053 GLenum target,
1054 GLint image_id);
1056 void DoTraceEndCHROMIUM(void);
1058 void DoDrawBuffersEXT(GLsizei count, const GLenum* bufs);
1060 void DoLoseContextCHROMIUM(GLenum current, GLenum other);
1062 void DoMatrixLoadfCHROMIUM(GLenum matrix_mode, const GLfloat* matrix);
1063 void DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode);
1065 // Creates a Program for the given program.
1066 Program* CreateProgram(
1067 GLuint client_id, GLuint service_id) {
1068 return program_manager()->CreateProgram(client_id, service_id);
1071 // Gets the program info for the given program. Returns NULL if none exists.
1072 Program* GetProgram(GLuint client_id) {
1073 return program_manager()->GetProgram(client_id);
1076 #if defined(NDEBUG)
1077 void LogClientServiceMapping(
1078 const char* /* function_name */,
1079 GLuint /* client_id */,
1080 GLuint /* service_id */) {
1082 template<typename T>
1083 void LogClientServiceForInfo(
1084 T* /* info */, GLuint /* client_id */, const char* /* function_name */) {
1086 #else
1087 void LogClientServiceMapping(
1088 const char* function_name, GLuint client_id, GLuint service_id) {
1089 if (service_logging_) {
1090 VLOG(1) << "[" << logger_.GetLogPrefix() << "] " << function_name
1091 << ": client_id = " << client_id
1092 << ", service_id = " << service_id;
1095 template<typename T>
1096 void LogClientServiceForInfo(
1097 T* info, GLuint client_id, const char* function_name) {
1098 if (info) {
1099 LogClientServiceMapping(function_name, client_id, info->service_id());
1102 #endif
1104 // Gets the program info for the given program. If it's not a program
1105 // generates a GL error. Returns NULL if not program.
1106 Program* GetProgramInfoNotShader(
1107 GLuint client_id, const char* function_name) {
1108 Program* program = GetProgram(client_id);
1109 if (!program) {
1110 if (GetShader(client_id)) {
1111 LOCAL_SET_GL_ERROR(
1112 GL_INVALID_OPERATION, function_name, "shader passed for program");
1113 } else {
1114 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "unknown program");
1117 LogClientServiceForInfo(program, client_id, function_name);
1118 return program;
1122 // Creates a Shader for the given shader.
1123 Shader* CreateShader(
1124 GLuint client_id,
1125 GLuint service_id,
1126 GLenum shader_type) {
1127 return shader_manager()->CreateShader(
1128 client_id, service_id, shader_type);
1131 // Gets the shader info for the given shader. Returns NULL if none exists.
1132 Shader* GetShader(GLuint client_id) {
1133 return shader_manager()->GetShader(client_id);
1136 // Gets the shader info for the given shader. If it's not a shader generates a
1137 // GL error. Returns NULL if not shader.
1138 Shader* GetShaderInfoNotProgram(
1139 GLuint client_id, const char* function_name) {
1140 Shader* shader = GetShader(client_id);
1141 if (!shader) {
1142 if (GetProgram(client_id)) {
1143 LOCAL_SET_GL_ERROR(
1144 GL_INVALID_OPERATION, function_name, "program passed for shader");
1145 } else {
1146 LOCAL_SET_GL_ERROR(
1147 GL_INVALID_VALUE, function_name, "unknown shader");
1150 LogClientServiceForInfo(shader, client_id, function_name);
1151 return shader;
1154 // Creates a buffer info for the given buffer.
1155 void CreateBuffer(GLuint client_id, GLuint service_id) {
1156 return buffer_manager()->CreateBuffer(client_id, service_id);
1159 // Gets the buffer info for the given buffer.
1160 Buffer* GetBuffer(GLuint client_id) {
1161 Buffer* buffer = buffer_manager()->GetBuffer(client_id);
1162 return buffer;
1165 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
1166 // on glDeleteBuffers so we can make sure the user does not try to render
1167 // with deleted buffers.
1168 void RemoveBuffer(GLuint client_id);
1170 // Creates a framebuffer info for the given framebuffer.
1171 void CreateFramebuffer(GLuint client_id, GLuint service_id) {
1172 return framebuffer_manager()->CreateFramebuffer(client_id, service_id);
1175 // Gets the framebuffer info for the given framebuffer.
1176 Framebuffer* GetFramebuffer(GLuint client_id) {
1177 return framebuffer_manager()->GetFramebuffer(client_id);
1180 // Removes the framebuffer info for the given framebuffer.
1181 void RemoveFramebuffer(GLuint client_id) {
1182 framebuffer_manager()->RemoveFramebuffer(client_id);
1185 // Creates a renderbuffer info for the given renderbuffer.
1186 void CreateRenderbuffer(GLuint client_id, GLuint service_id) {
1187 return renderbuffer_manager()->CreateRenderbuffer(
1188 client_id, service_id);
1191 // Gets the renderbuffer info for the given renderbuffer.
1192 Renderbuffer* GetRenderbuffer(GLuint client_id) {
1193 return renderbuffer_manager()->GetRenderbuffer(client_id);
1196 // Removes the renderbuffer info for the given renderbuffer.
1197 void RemoveRenderbuffer(GLuint client_id) {
1198 renderbuffer_manager()->RemoveRenderbuffer(client_id);
1201 // Creates a valuebuffer info for the given valuebuffer.
1202 void CreateValuebuffer(GLuint client_id) {
1203 return valuebuffer_manager()->CreateValuebuffer(client_id);
1206 // Gets the valuebuffer info for a given valuebuffer.
1207 Valuebuffer* GetValuebuffer(GLuint client_id) {
1208 return valuebuffer_manager()->GetValuebuffer(client_id);
1211 // Removes the valuebuffer info for the given valuebuffer.
1212 void RemoveValuebuffer(GLuint client_id) {
1213 valuebuffer_manager()->RemoveValuebuffer(client_id);
1216 // Gets the vertex attrib manager for the given vertex array.
1217 VertexAttribManager* GetVertexAttribManager(GLuint client_id) {
1218 VertexAttribManager* info =
1219 vertex_array_manager()->GetVertexAttribManager(client_id);
1220 return info;
1223 // Removes the vertex attrib manager for the given vertex array.
1224 void RemoveVertexAttribManager(GLuint client_id) {
1225 vertex_array_manager()->RemoveVertexAttribManager(client_id);
1228 // Creates a vertex attrib manager for the given vertex array.
1229 scoped_refptr<VertexAttribManager> CreateVertexAttribManager(
1230 GLuint client_id,
1231 GLuint service_id,
1232 bool client_visible) {
1233 return vertex_array_manager()->CreateVertexAttribManager(
1234 client_id, service_id, group_->max_vertex_attribs(), client_visible);
1237 void DoBindAttribLocation(GLuint client_id, GLuint index, const char* name);
1238 void DoBindUniformLocationCHROMIUM(
1239 GLuint client_id, GLint location, const char* name);
1241 error::Error GetAttribLocationHelper(
1242 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1243 const std::string& name_str);
1245 error::Error GetUniformLocationHelper(
1246 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1247 const std::string& name_str);
1249 error::Error GetFragDataLocationHelper(
1250 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1251 const std::string& name_str);
1253 // Wrapper for glShaderSource.
1254 void DoShaderSource(
1255 GLuint client_id, GLsizei count, const char** data, const GLint* length);
1257 // Wrapper for glTransformFeedbackVaryings.
1258 void DoTransformFeedbackVaryings(
1259 GLuint client_program_id, GLsizei count, const char* const* varyings,
1260 GLenum buffer_mode);
1262 // Clear any textures used by the current program.
1263 bool ClearUnclearedTextures();
1265 // Clears any uncleared attachments attached to the given frame buffer.
1266 // Returns false if there was a generated GL error.
1267 void ClearUnclearedAttachments(GLenum target, Framebuffer* framebuffer);
1269 // overridden from GLES2Decoder
1270 bool ClearLevel(Texture* texture,
1271 unsigned target,
1272 int level,
1273 unsigned internal_format,
1274 unsigned format,
1275 unsigned type,
1276 int width,
1277 int height,
1278 bool is_texture_immutable) override;
1280 // Restore all GL state that affects clearing.
1281 void RestoreClearState();
1283 // Remembers the state of some capabilities.
1284 // Returns: true if glEnable/glDisable should actually be called.
1285 bool SetCapabilityState(GLenum cap, bool enabled);
1287 // Check that the currently bound framebuffers are valid.
1288 // Generates GL error if not.
1289 bool CheckBoundFramebuffersValid(const char* func_name);
1291 // Check that the currently bound read framebuffer has a color image
1292 // attached. Generates GL error if not.
1293 bool CheckBoundReadFramebufferColorAttachment(const char* func_name);
1295 // Check that the currently bound read framebuffer's color image
1296 // isn't the target texture of the glCopyTex{Sub}Image2D.
1297 bool FormsTextureCopyingFeedbackLoop(TextureRef* texture, GLint level);
1299 // Check if a framebuffer meets our requirements.
1300 bool CheckFramebufferValid(
1301 Framebuffer* framebuffer,
1302 GLenum target,
1303 const char* func_name);
1305 // Check if the current valuebuffer exists and is valid. If not generates
1306 // the appropriate GL error. Returns true if the current valuebuffer is in
1307 // a usable state.
1308 bool CheckCurrentValuebuffer(const char* function_name);
1310 // Check if the current valuebuffer exists and is valiud and that the
1311 // value buffer is actually subscribed to the given subscription
1312 bool CheckCurrentValuebufferForSubscription(GLenum subscription,
1313 const char* function_name);
1315 // Check if the location can be used for the given subscription target. If not
1316 // generates the appropriate GL error. Returns true if the location is usable
1317 bool CheckSubscriptionTarget(GLint location,
1318 GLenum subscription,
1319 const char* function_name);
1321 // Checks if the current program exists and is valid. If not generates the
1322 // appropriate GL error. Returns true if the current program is in a usable
1323 // state.
1324 bool CheckCurrentProgram(const char* function_name);
1326 // Checks if the current program exists and is valid and that location is not
1327 // -1. If the current program is not valid generates the appropriate GL
1328 // error. Returns true if the current program is in a usable state and
1329 // location is not -1.
1330 bool CheckCurrentProgramForUniform(GLint location, const char* function_name);
1332 // Checks if the current program samples a texture that is also the color
1333 // image of the current bound framebuffer, i.e., the source and destination
1334 // of the draw operation are the same.
1335 bool CheckDrawingFeedbackLoops();
1337 // Checks if |api_type| is valid for the given uniform
1338 // If the api type is not valid generates the appropriate GL
1339 // error. Returns true if |api_type| is valid for the uniform
1340 bool CheckUniformForApiType(const Program::UniformInfo* info,
1341 const char* function_name,
1342 Program::UniformApiType api_type);
1344 // Gets the type of a uniform for a location in the current program. Sets GL
1345 // errors if the current program is not valid. Returns true if the current
1346 // program is valid and the location exists. Adjusts count so it
1347 // does not overflow the uniform.
1348 bool PrepForSetUniformByLocation(GLint fake_location,
1349 const char* function_name,
1350 Program::UniformApiType api_type,
1351 GLint* real_location,
1352 GLenum* type,
1353 GLsizei* count);
1355 // Gets the service id for any simulated backbuffer fbo.
1356 GLuint GetBackbufferServiceId() const;
1358 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
1359 bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
1361 // Helper for glGetVertexAttrib
1362 void GetVertexAttribHelper(
1363 const VertexAttrib* attrib, GLenum pname, GLint* param);
1365 // Wrapper for glActiveTexture
1366 void DoActiveTexture(GLenum texture_unit);
1368 // Wrapper for glAttachShader
1369 void DoAttachShader(GLuint client_program_id, GLint client_shader_id);
1371 // Wrapper for glBindBuffer since we need to track the current targets.
1372 void DoBindBuffer(GLenum target, GLuint buffer);
1374 // Wrapper for glBindFramebuffer since we need to track the current targets.
1375 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
1377 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1378 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
1380 // Wrapper for glBindTexture since we need to track the current targets.
1381 void DoBindTexture(GLenum target, GLuint texture);
1383 // Wrapper for glBindVertexArrayOES
1384 void DoBindVertexArrayOES(GLuint array);
1385 void EmulateVertexArrayState();
1387 // Wrapper for glBlitFramebufferCHROMIUM.
1388 void DoBlitFramebufferCHROMIUM(
1389 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
1390 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
1391 GLbitfield mask, GLenum filter);
1393 // Wrapper for glBufferSubData.
1394 void DoBufferSubData(
1395 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
1397 // Wrapper for glCheckFramebufferStatus
1398 GLenum DoCheckFramebufferStatus(GLenum target);
1400 // Wrapper for glClear
1401 error::Error DoClear(GLbitfield mask);
1403 // Wrappers for various state.
1404 void DoDepthRangef(GLclampf znear, GLclampf zfar);
1405 void DoSampleCoverage(GLclampf value, GLboolean invert);
1407 // Wrapper for glCompileShader.
1408 void DoCompileShader(GLuint shader);
1410 // Wrapper for glDetachShader
1411 void DoDetachShader(GLuint client_program_id, GLint client_shader_id);
1413 // Wrapper for glDisable
1414 void DoDisable(GLenum cap);
1416 // Wrapper for glDisableVertexAttribArray.
1417 void DoDisableVertexAttribArray(GLuint index);
1419 // Wrapper for glDiscardFramebufferEXT, since we need to track undefined
1420 // attachments.
1421 void DoDiscardFramebufferEXT(GLenum target,
1422 GLsizei numAttachments,
1423 const GLenum* attachments);
1425 // Wrapper for glEnable
1426 void DoEnable(GLenum cap);
1428 // Wrapper for glEnableVertexAttribArray.
1429 void DoEnableVertexAttribArray(GLuint index);
1431 // Wrapper for glFinish.
1432 void DoFinish();
1434 // Wrapper for glFlush.
1435 void DoFlush();
1437 // Wrapper for glFramebufferRenderbufffer.
1438 void DoFramebufferRenderbuffer(
1439 GLenum target, GLenum attachment, GLenum renderbuffertarget,
1440 GLuint renderbuffer);
1442 // Wrapper for glFramebufferTexture2D.
1443 void DoFramebufferTexture2D(
1444 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
1445 GLint level);
1447 // Wrapper for glFramebufferTexture2DMultisampleEXT.
1448 void DoFramebufferTexture2DMultisample(
1449 GLenum target, GLenum attachment, GLenum textarget,
1450 GLuint texture, GLint level, GLsizei samples);
1452 // Common implementation for both DoFramebufferTexture2D wrappers.
1453 void DoFramebufferTexture2DCommon(const char* name,
1454 GLenum target, GLenum attachment, GLenum textarget,
1455 GLuint texture, GLint level, GLsizei samples);
1457 // Wrapper for glFramebufferTextureLayer.
1458 void DoFramebufferTextureLayer(
1459 GLenum target, GLenum attachment, GLuint texture, GLint level,
1460 GLint layer);
1462 // Wrapper for glGenerateMipmap
1463 void DoGenerateMipmap(GLenum target);
1465 // Helper for DoGetBooleanv, Floatv, and Intergerv to adjust pname
1466 // to account for different pname values defined in different extension
1467 // variants.
1468 GLenum AdjustGetPname(GLenum pname);
1470 // Wrapper for DoGetBooleanv.
1471 void DoGetBooleanv(GLenum pname, GLboolean* params);
1473 // Wrapper for DoGetFloatv.
1474 void DoGetFloatv(GLenum pname, GLfloat* params);
1476 // Wrapper for glGetFramebufferAttachmentParameteriv.
1477 void DoGetFramebufferAttachmentParameteriv(
1478 GLenum target, GLenum attachment, GLenum pname, GLint* params);
1480 // Wrapper for glGetInteger64v.
1481 void DoGetInteger64v(GLenum pname, GLint64* params);
1483 // Wrapper for glGetIntegerv.
1484 void DoGetIntegerv(GLenum pname, GLint* params);
1486 // Gets the max value in a range in a buffer.
1487 GLuint DoGetMaxValueInBufferCHROMIUM(
1488 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset);
1490 // Wrapper for glGetBufferParameteriv.
1491 void DoGetBufferParameteriv(
1492 GLenum target, GLenum pname, GLint* params);
1494 // Wrapper for glGetProgramiv.
1495 void DoGetProgramiv(
1496 GLuint program_id, GLenum pname, GLint* params);
1498 // Wrapper for glRenderbufferParameteriv.
1499 void DoGetRenderbufferParameteriv(
1500 GLenum target, GLenum pname, GLint* params);
1502 // Wrapper for glGetShaderiv
1503 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
1505 // Wrappers for glGetTexParameter.
1506 void DoGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params);
1507 void DoGetTexParameteriv(GLenum target, GLenum pname, GLint* params);
1508 void InitTextureMaxAnisotropyIfNeeded(GLenum target, GLenum pname);
1510 // Wrappers for glGetVertexAttrib.
1511 template <typename T>
1512 void DoGetVertexAttribImpl(GLuint index, GLenum pname, T* params);
1513 void DoGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params);
1514 void DoGetVertexAttribiv(GLuint index, GLenum pname, GLint* params);
1515 void DoGetVertexAttribIiv(GLuint index, GLenum pname, GLint* params);
1516 void DoGetVertexAttribIuiv(GLuint index, GLenum pname, GLuint* params);
1518 // Wrappers for glIsXXX functions.
1519 bool DoIsEnabled(GLenum cap);
1520 bool DoIsBuffer(GLuint client_id);
1521 bool DoIsFramebuffer(GLuint client_id);
1522 bool DoIsProgram(GLuint client_id);
1523 bool DoIsRenderbuffer(GLuint client_id);
1524 bool DoIsShader(GLuint client_id);
1525 bool DoIsTexture(GLuint client_id);
1526 bool DoIsVertexArrayOES(GLuint client_id);
1528 // Wrapper for glLinkProgram
1529 void DoLinkProgram(GLuint program);
1531 // Wrapper for glRenderbufferStorage.
1532 void DoRenderbufferStorage(
1533 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
1535 // Handler for glRenderbufferStorageMultisampleCHROMIUM.
1536 void DoRenderbufferStorageMultisampleCHROMIUM(
1537 GLenum target, GLsizei samples, GLenum internalformat,
1538 GLsizei width, GLsizei height);
1540 // Handler for glRenderbufferStorageMultisampleEXT
1541 // (multisampled_render_to_texture).
1542 void DoRenderbufferStorageMultisampleEXT(
1543 GLenum target, GLsizei samples, GLenum internalformat,
1544 GLsizei width, GLsizei height);
1546 // Common validation for multisample extensions.
1547 bool ValidateRenderbufferStorageMultisample(GLsizei samples,
1548 GLenum internalformat,
1549 GLsizei width,
1550 GLsizei height);
1552 // Verifies that the currently bound multisample renderbuffer is valid
1553 // Very slow! Only done on platforms with driver bugs that return invalid
1554 // buffers under memory pressure
1555 bool VerifyMultisampleRenderbufferIntegrity(
1556 GLuint renderbuffer, GLenum format);
1558 // Wrapper for glReleaseShaderCompiler.
1559 void DoReleaseShaderCompiler() { }
1561 // Wrappers for glSamplerParameter*v functions.
1562 void DoSamplerParameterfv(
1563 GLuint sampler, GLenum pname, const GLfloat* params);
1564 void DoSamplerParameteriv(GLuint sampler, GLenum pname, const GLint* params);
1566 // Wrappers for glTexParameter functions.
1567 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
1568 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
1569 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
1570 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
1572 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1573 // spec only these 2 functions can be used to set sampler uniforms.
1574 void DoUniform1i(GLint fake_location, GLint v0);
1575 void DoUniform1iv(GLint fake_location, GLsizei count, const GLint* value);
1576 void DoUniform2iv(GLint fake_location, GLsizei count, const GLint* value);
1577 void DoUniform3iv(GLint fake_location, GLsizei count, const GLint* value);
1578 void DoUniform4iv(GLint fake_location, GLsizei count, const GLint* value);
1580 // Wrappers for glUniformfv because some drivers don't correctly accept
1581 // bool uniforms.
1582 void DoUniform1fv(GLint fake_location, GLsizei count, const GLfloat* value);
1583 void DoUniform2fv(GLint fake_location, GLsizei count, const GLfloat* value);
1584 void DoUniform3fv(GLint fake_location, GLsizei count, const GLfloat* value);
1585 void DoUniform4fv(GLint fake_location, GLsizei count, const GLfloat* value);
1587 void DoUniformMatrix2fv(
1588 GLint fake_location, GLsizei count, GLboolean transpose,
1589 const GLfloat* value);
1590 void DoUniformMatrix3fv(
1591 GLint fake_location, GLsizei count, GLboolean transpose,
1592 const GLfloat* value);
1593 void DoUniformMatrix4fv(
1594 GLint fake_location, GLsizei count, GLboolean transpose,
1595 const GLfloat* value);
1597 template <typename T>
1598 bool SetVertexAttribValue(
1599 const char* function_name, GLuint index, const T* value);
1601 // Wrappers for glVertexAttrib??
1602 void DoVertexAttrib1f(GLuint index, GLfloat v0);
1603 void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
1604 void DoVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
1605 void DoVertexAttrib4f(
1606 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
1607 void DoVertexAttrib1fv(GLuint index, const GLfloat* v);
1608 void DoVertexAttrib2fv(GLuint index, const GLfloat* v);
1609 void DoVertexAttrib3fv(GLuint index, const GLfloat* v);
1610 void DoVertexAttrib4fv(GLuint index, const GLfloat* v);
1611 void DoVertexAttribI4i(GLuint index, GLint v0, GLint v1, GLint v2, GLint v3);
1612 void DoVertexAttribI4iv(GLuint index, const GLint* v);
1613 void DoVertexAttribI4ui(
1614 GLuint index, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
1615 void DoVertexAttribI4uiv(GLuint index, const GLuint* v);
1617 // Wrapper for glViewport
1618 void DoViewport(GLint x, GLint y, GLsizei width, GLsizei height);
1620 // Wrapper for glUseProgram
1621 void DoUseProgram(GLuint program);
1623 // Wrapper for glValidateProgram.
1624 void DoValidateProgram(GLuint program_client_id);
1626 void DoInsertEventMarkerEXT(GLsizei length, const GLchar* marker);
1627 void DoPushGroupMarkerEXT(GLsizei length, const GLchar* group);
1628 void DoPopGroupMarkerEXT(void);
1630 // Gets the number of values that will be returned by glGetXXX. Returns
1631 // false if pname is unknown.
1632 bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
1634 // Checks if the current program and vertex attributes are valid for drawing.
1635 bool IsDrawValid(
1636 const char* function_name, GLuint max_vertex_accessed, bool instanced,
1637 GLsizei primcount);
1639 // Returns true if successful, simulated will be true if attrib0 was
1640 // simulated.
1641 bool SimulateAttrib0(
1642 const char* function_name, GLuint max_vertex_accessed, bool* simulated);
1643 void RestoreStateForAttrib(GLuint attrib, bool restore_array_binding);
1645 // If an image is bound to texture, this will call Will/DidUseTexImage
1646 // if needed.
1647 void DoWillUseTexImageIfNeeded(Texture* texture, GLenum textarget);
1648 void DoDidUseTexImageIfNeeded(Texture* texture, GLenum textarget);
1650 // Returns false if textures were replaced.
1651 bool PrepareTexturesForRender();
1652 void RestoreStateForTextures();
1654 // Returns true if GL_FIXED attribs were simulated.
1655 bool SimulateFixedAttribs(
1656 const char* function_name,
1657 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount);
1658 void RestoreStateForSimulatedFixedAttribs();
1660 // Handle DrawArrays and DrawElements for both instanced and non-instanced
1661 // cases (primcount is always 1 for non-instanced).
1662 error::Error DoDrawArrays(
1663 const char* function_name,
1664 bool instanced, GLenum mode, GLint first, GLsizei count,
1665 GLsizei primcount);
1666 error::Error DoDrawElements(
1667 const char* function_name,
1668 bool instanced, GLenum mode, GLsizei count, GLenum type,
1669 int32 offset, GLsizei primcount);
1671 GLenum GetBindTargetForSamplerType(GLenum type) {
1672 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
1673 type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB);
1674 switch (type) {
1675 case GL_SAMPLER_2D:
1676 return GL_TEXTURE_2D;
1677 case GL_SAMPLER_CUBE:
1678 return GL_TEXTURE_CUBE_MAP;
1679 case GL_SAMPLER_EXTERNAL_OES:
1680 return GL_TEXTURE_EXTERNAL_OES;
1681 case GL_SAMPLER_2D_RECT_ARB:
1682 return GL_TEXTURE_RECTANGLE_ARB;
1685 NOTREACHED();
1686 return 0;
1689 // Gets the framebuffer info for a particular target.
1690 Framebuffer* GetFramebufferInfoForTarget(GLenum target) {
1691 Framebuffer* framebuffer = NULL;
1692 switch (target) {
1693 case GL_FRAMEBUFFER:
1694 case GL_DRAW_FRAMEBUFFER_EXT:
1695 framebuffer = framebuffer_state_.bound_draw_framebuffer.get();
1696 break;
1697 case GL_READ_FRAMEBUFFER_EXT:
1698 framebuffer = framebuffer_state_.bound_read_framebuffer.get();
1699 break;
1700 default:
1701 NOTREACHED();
1702 break;
1704 return framebuffer;
1707 Renderbuffer* GetRenderbufferInfoForTarget(
1708 GLenum target) {
1709 Renderbuffer* renderbuffer = NULL;
1710 switch (target) {
1711 case GL_RENDERBUFFER:
1712 renderbuffer = state_.bound_renderbuffer.get();
1713 break;
1714 default:
1715 NOTREACHED();
1716 break;
1718 return renderbuffer;
1721 // Validates the program and location for a glGetUniform call and returns
1722 // a SizeResult setup to receive the result. Returns true if glGetUniform
1723 // should be called.
1724 template <class T>
1725 bool GetUniformSetup(GLuint program,
1726 GLint fake_location,
1727 uint32 shm_id,
1728 uint32 shm_offset,
1729 error::Error* error,
1730 GLint* real_location,
1731 GLuint* service_id,
1732 SizedResult<T>** result,
1733 GLenum* result_type,
1734 GLsizei* result_size);
1736 bool WasContextLost() const override;
1737 bool WasContextLostByRobustnessExtension() const override;
1738 void MarkContextLost(error::ContextLostReason reason) override;
1739 bool CheckResetStatus();
1741 #if defined(OS_MACOSX)
1742 void ReleaseIOSurfaceForTexture(GLuint texture_id);
1743 #endif
1745 bool ValidateCompressedTexDimensions(
1746 const char* function_name, GLenum target, GLint level,
1747 GLsizei width, GLsizei height, GLsizei depth, GLenum format);
1748 bool ValidateCompressedTexFuncData(
1749 const char* function_name, GLsizei width, GLsizei height, GLsizei depth,
1750 GLenum format, GLsizei size);
1751 bool ValidateCompressedTexSubDimensions(
1752 const char* function_name,
1753 GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
1754 GLsizei width, GLsizei height, GLsizei depth, GLenum format,
1755 Texture* texture);
1756 bool ValidateCopyTextureCHROMIUM(const char* function_name,
1757 GLenum target,
1758 TextureRef* source_texture_ref,
1759 TextureRef* dest_texture_ref,
1760 GLenum dest_internal_format);
1762 void RenderWarning(const char* filename, int line, const std::string& msg);
1763 void PerformanceWarning(
1764 const char* filename, int line, const std::string& msg);
1766 const FeatureInfo::FeatureFlags& features() const {
1767 return feature_info_->feature_flags();
1770 const FeatureInfo::Workarounds& workarounds() const {
1771 return feature_info_->workarounds();
1774 bool ShouldDeferDraws() {
1775 return !offscreen_target_frame_buffer_.get() &&
1776 framebuffer_state_.bound_draw_framebuffer.get() == NULL &&
1777 surface_->DeferDraws();
1780 bool ShouldDeferReads() {
1781 return !offscreen_target_frame_buffer_.get() &&
1782 framebuffer_state_.bound_read_framebuffer.get() == NULL &&
1783 surface_->DeferDraws();
1786 bool IsRobustnessSupported() {
1787 return has_robustness_extension_ &&
1788 context_->WasAllocatedUsingRobustnessExtension();
1791 error::Error WillAccessBoundFramebufferForDraw() {
1792 if (ShouldDeferDraws())
1793 return error::kDeferCommandUntilLater;
1794 if (!offscreen_target_frame_buffer_.get() &&
1795 !framebuffer_state_.bound_draw_framebuffer.get() &&
1796 !surface_->SetBackbufferAllocation(true))
1797 return error::kLostContext;
1798 return error::kNoError;
1801 error::Error WillAccessBoundFramebufferForRead() {
1802 if (ShouldDeferReads())
1803 return error::kDeferCommandUntilLater;
1804 if (!offscreen_target_frame_buffer_.get() &&
1805 !framebuffer_state_.bound_read_framebuffer.get() &&
1806 !surface_->SetBackbufferAllocation(true))
1807 return error::kLostContext;
1808 return error::kNoError;
1811 // Set remaining commands to process to 0 to force DoCommands to return
1812 // and allow context preemption and GPU watchdog checks in GpuScheduler().
1813 void ExitCommandProcessingEarly() { commands_to_process_ = 0; }
1815 void ProcessPendingReadPixels();
1816 void FinishReadPixels(const cmds::ReadPixels& c, GLuint buffer);
1818 // Generate a member function prototype for each command in an automated and
1819 // typesafe way.
1820 #define GLES2_CMD_OP(name) \
1821 Error Handle##name(uint32 immediate_data_size, const void* data);
1823 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1825 #undef GLES2_CMD_OP
1827 // The GL context this decoder renders to on behalf of the client.
1828 scoped_refptr<gfx::GLSurface> surface_;
1829 scoped_refptr<gfx::GLContext> context_;
1831 // The ContextGroup for this decoder uses to track resources.
1832 scoped_refptr<ContextGroup> group_;
1834 DebugMarkerManager debug_marker_manager_;
1835 Logger logger_;
1837 // All the state for this context.
1838 ContextState state_;
1840 // Current width and height of the offscreen frame buffer.
1841 gfx::Size offscreen_size_;
1843 // Util to help with GL.
1844 GLES2Util util_;
1846 // unpack flip y as last set by glPixelStorei
1847 bool unpack_flip_y_;
1849 // unpack (un)premultiply alpha as last set by glPixelStorei
1850 bool unpack_premultiply_alpha_;
1851 bool unpack_unpremultiply_alpha_;
1853 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1854 GLuint attrib_0_buffer_id_;
1856 // The value currently in attrib_0.
1857 Vec4 attrib_0_value_;
1859 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1860 bool attrib_0_buffer_matches_value_;
1862 // The size of attrib 0.
1863 GLsizei attrib_0_size_;
1865 // The buffer used to simulate GL_FIXED attribs.
1866 GLuint fixed_attrib_buffer_id_;
1868 // The size of fiixed attrib buffer.
1869 GLsizei fixed_attrib_buffer_size_;
1871 // The offscreen frame buffer that the client renders to. With EGL, the
1872 // depth and stencil buffers are separate. With regular GL there is a single
1873 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1874 // offscreen_target_stencil_render_buffer_ is unused.
1875 scoped_ptr<BackFramebuffer> offscreen_target_frame_buffer_;
1876 scoped_ptr<BackTexture> offscreen_target_color_texture_;
1877 scoped_ptr<BackRenderbuffer> offscreen_target_color_render_buffer_;
1878 scoped_ptr<BackRenderbuffer> offscreen_target_depth_render_buffer_;
1879 scoped_ptr<BackRenderbuffer> offscreen_target_stencil_render_buffer_;
1880 GLenum offscreen_target_color_format_;
1881 GLenum offscreen_target_depth_format_;
1882 GLenum offscreen_target_stencil_format_;
1883 GLsizei offscreen_target_samples_;
1884 GLboolean offscreen_target_buffer_preserved_;
1886 // The copy that is saved when SwapBuffers is called.
1887 scoped_ptr<BackFramebuffer> offscreen_saved_frame_buffer_;
1888 scoped_ptr<BackTexture> offscreen_saved_color_texture_;
1889 scoped_refptr<TextureRef>
1890 offscreen_saved_color_texture_info_;
1892 // The copy that is used as the destination for multi-sample resolves.
1893 scoped_ptr<BackFramebuffer> offscreen_resolved_frame_buffer_;
1894 scoped_ptr<BackTexture> offscreen_resolved_color_texture_;
1895 GLenum offscreen_saved_color_format_;
1897 scoped_ptr<QueryManager> query_manager_;
1899 scoped_ptr<VertexArrayManager> vertex_array_manager_;
1901 scoped_ptr<ImageManager> image_manager_;
1903 base::Callback<void(gfx::Size, float)> resize_callback_;
1905 WaitSyncPointCallback wait_sync_point_callback_;
1907 ShaderCacheCallback shader_cache_callback_;
1909 scoped_ptr<AsyncPixelTransferManager> async_pixel_transfer_manager_;
1911 // The format of the back buffer_
1912 GLenum back_buffer_color_format_;
1913 bool back_buffer_has_depth_;
1914 bool back_buffer_has_stencil_;
1916 bool surfaceless_;
1918 // Backbuffer attachments that are currently undefined.
1919 uint32 backbuffer_needs_clear_bits_;
1921 // The current decoder error communicates the decoder error through command
1922 // processing functions that do not return the error value. Should be set only
1923 // if not returning an error.
1924 error::Error current_decoder_error_;
1926 bool use_shader_translator_;
1927 scoped_refptr<ShaderTranslatorInterface> vertex_translator_;
1928 scoped_refptr<ShaderTranslatorInterface> fragment_translator_;
1930 DisallowedFeatures disallowed_features_;
1932 // Cached from ContextGroup
1933 const Validators* validators_;
1934 scoped_refptr<FeatureInfo> feature_info_;
1936 int frame_number_;
1938 // Number of commands remaining to be processed in DoCommands().
1939 int commands_to_process_;
1941 bool has_robustness_extension_;
1942 error::ContextLostReason context_lost_reason_;
1943 bool context_was_lost_;
1944 bool reset_by_robustness_extension_;
1945 bool supports_post_sub_buffer_;
1947 // These flags are used to override the state of the shared feature_info_
1948 // member. Because the same FeatureInfo instance may be shared among many
1949 // contexts, the assumptions on the availablity of extensions in WebGL
1950 // contexts may be broken. These flags override the shared state to preserve
1951 // WebGL semantics.
1952 bool force_webgl_glsl_validation_;
1953 bool derivatives_explicitly_enabled_;
1954 bool frag_depth_explicitly_enabled_;
1955 bool draw_buffers_explicitly_enabled_;
1956 bool shader_texture_lod_explicitly_enabled_;
1958 bool compile_shader_always_succeeds_;
1960 // An optional behaviour to lose the context and group when OOM.
1961 bool lose_context_when_out_of_memory_;
1963 // Log extra info.
1964 bool service_logging_;
1966 #if defined(OS_MACOSX)
1967 typedef std::map<GLuint, IOSurfaceRef> TextureToIOSurfaceMap;
1968 TextureToIOSurfaceMap texture_to_io_surface_map_;
1969 #endif
1971 scoped_ptr<CopyTextureCHROMIUMResourceManager> copy_texture_CHROMIUM_;
1972 scoped_ptr<ClearFramebufferResourceManager> clear_framebuffer_blit_;
1974 // Cached values of the currently assigned viewport dimensions.
1975 GLsizei viewport_max_width_;
1976 GLsizei viewport_max_height_;
1978 // Command buffer stats.
1979 base::TimeDelta total_processing_commands_time_;
1981 // States related to each manager.
1982 DecoderTextureState texture_state_;
1983 DecoderFramebufferState framebuffer_state_;
1985 scoped_ptr<GPUTracer> gpu_tracer_;
1986 scoped_ptr<GPUStateTracer> gpu_state_tracer_;
1987 const unsigned char* cb_command_trace_category_;
1988 const unsigned char* gpu_decoder_category_;
1989 int gpu_trace_level_;
1990 bool gpu_trace_commands_;
1991 bool gpu_debug_commands_;
1993 std::queue<linked_ptr<FenceCallback> > pending_readpixel_fences_;
1995 // Used to validate multisample renderbuffers if needed
1996 GLuint validation_texture_;
1997 GLuint validation_fbo_multisample_;
1998 GLuint validation_fbo_;
2000 typedef gpu::gles2::GLES2Decoder::Error (GLES2DecoderImpl::*CmdHandler)(
2001 uint32 immediate_data_size,
2002 const void* data);
2004 // A struct to hold info about each command.
2005 struct CommandInfo {
2006 CmdHandler cmd_handler;
2007 uint8 arg_flags; // How to handle the arguments for this command
2008 uint8 cmd_flags; // How to handle this command
2009 uint16 arg_count; // How many arguments are expected for this command.
2012 // A table of CommandInfo for all the commands.
2013 static const CommandInfo command_info[kNumCommands - kStartPoint];
2015 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
2018 const GLES2DecoderImpl::CommandInfo GLES2DecoderImpl::command_info[] = {
2019 #define GLES2_CMD_OP(name) \
2021 &GLES2DecoderImpl::Handle##name, cmds::name::kArgFlags, \
2022 cmds::name::cmd_flags, \
2023 sizeof(cmds::name) / sizeof(CommandBufferEntry) - 1, \
2025 , /* NOLINT */
2026 GLES2_COMMAND_LIST(GLES2_CMD_OP)
2027 #undef GLES2_CMD_OP
2030 ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(
2031 const char* function_name, ErrorState* error_state)
2032 : function_name_(function_name),
2033 error_state_(error_state) {
2034 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state_, function_name_);
2037 ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
2038 ERRORSTATE_CLEAR_REAL_GL_ERRORS(error_state_, function_name_);
2041 static void RestoreCurrentTextureBindings(ContextState* state, GLenum target) {
2042 TextureUnit& info = state->texture_units[0];
2043 GLuint last_id;
2044 scoped_refptr<TextureRef> texture_ref;
2045 switch (target) {
2046 case GL_TEXTURE_2D:
2047 texture_ref = info.bound_texture_2d;
2048 break;
2049 case GL_TEXTURE_CUBE_MAP:
2050 texture_ref = info.bound_texture_cube_map;
2051 break;
2052 case GL_TEXTURE_EXTERNAL_OES:
2053 texture_ref = info.bound_texture_external_oes;
2054 break;
2055 case GL_TEXTURE_RECTANGLE_ARB:
2056 texture_ref = info.bound_texture_rectangle_arb;
2057 break;
2058 default:
2059 NOTREACHED();
2060 break;
2062 if (texture_ref.get()) {
2063 last_id = texture_ref->service_id();
2064 } else {
2065 last_id = 0;
2068 glBindTexture(target, last_id);
2069 glActiveTexture(GL_TEXTURE0 + state->active_texture_unit);
2072 ScopedTextureBinder::ScopedTextureBinder(ContextState* state,
2073 GLuint id,
2074 GLenum target)
2075 : state_(state),
2076 target_(target) {
2077 ScopedGLErrorSuppressor suppressor(
2078 "ScopedTextureBinder::ctor", state_->GetErrorState());
2080 // TODO(apatrick): Check if there are any other states that need to be reset
2081 // before binding a new texture.
2082 glActiveTexture(GL_TEXTURE0);
2083 glBindTexture(target, id);
2086 ScopedTextureBinder::~ScopedTextureBinder() {
2087 ScopedGLErrorSuppressor suppressor(
2088 "ScopedTextureBinder::dtor", state_->GetErrorState());
2089 RestoreCurrentTextureBindings(state_, target_);
2092 ScopedRenderBufferBinder::ScopedRenderBufferBinder(ContextState* state,
2093 GLuint id)
2094 : state_(state) {
2095 ScopedGLErrorSuppressor suppressor(
2096 "ScopedRenderBufferBinder::ctor", state_->GetErrorState());
2097 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
2100 ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
2101 ScopedGLErrorSuppressor suppressor(
2102 "ScopedRenderBufferBinder::dtor", state_->GetErrorState());
2103 state_->RestoreRenderbufferBindings();
2106 ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
2107 GLuint id)
2108 : decoder_(decoder) {
2109 ScopedGLErrorSuppressor suppressor(
2110 "ScopedFrameBufferBinder::ctor", decoder_->GetErrorState());
2111 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
2112 decoder->OnFboChanged();
2115 ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
2116 ScopedGLErrorSuppressor suppressor(
2117 "ScopedFrameBufferBinder::dtor", decoder_->GetErrorState());
2118 decoder_->RestoreCurrentFramebufferBindings();
2121 ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
2122 GLES2DecoderImpl* decoder, bool enforce_internal_framebuffer, bool internal)
2123 : decoder_(decoder) {
2124 resolve_and_bind_ = (
2125 decoder_->offscreen_target_frame_buffer_.get() &&
2126 decoder_->IsOffscreenBufferMultisampled() &&
2127 (!decoder_->framebuffer_state_.bound_read_framebuffer.get() ||
2128 enforce_internal_framebuffer));
2129 if (!resolve_and_bind_)
2130 return;
2132 ScopedGLErrorSuppressor suppressor(
2133 "ScopedResolvedFrameBufferBinder::ctor", decoder_->GetErrorState());
2134 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT,
2135 decoder_->offscreen_target_frame_buffer_->id());
2136 GLuint targetid;
2137 if (internal) {
2138 if (!decoder_->offscreen_resolved_frame_buffer_.get()) {
2139 decoder_->offscreen_resolved_frame_buffer_.reset(
2140 new BackFramebuffer(decoder_));
2141 decoder_->offscreen_resolved_frame_buffer_->Create();
2142 decoder_->offscreen_resolved_color_texture_.reset(
2143 new BackTexture(decoder->memory_tracker(), &decoder->state_));
2144 decoder_->offscreen_resolved_color_texture_->Create();
2146 DCHECK(decoder_->offscreen_saved_color_format_);
2147 decoder_->offscreen_resolved_color_texture_->AllocateStorage(
2148 decoder_->offscreen_size_, decoder_->offscreen_saved_color_format_,
2149 false);
2150 decoder_->offscreen_resolved_frame_buffer_->AttachRenderTexture(
2151 decoder_->offscreen_resolved_color_texture_.get());
2152 if (decoder_->offscreen_resolved_frame_buffer_->CheckStatus() !=
2153 GL_FRAMEBUFFER_COMPLETE) {
2154 LOG(ERROR) << "ScopedResolvedFrameBufferBinder failed "
2155 << "because offscreen resolved FBO was incomplete.";
2156 return;
2159 targetid = decoder_->offscreen_resolved_frame_buffer_->id();
2160 } else {
2161 targetid = decoder_->offscreen_saved_frame_buffer_->id();
2163 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, targetid);
2164 const int width = decoder_->offscreen_size_.width();
2165 const int height = decoder_->offscreen_size_.height();
2166 decoder->state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
2167 decoder->BlitFramebufferHelper(0,
2169 width,
2170 height,
2173 width,
2174 height,
2175 GL_COLOR_BUFFER_BIT,
2176 GL_NEAREST);
2177 glBindFramebufferEXT(GL_FRAMEBUFFER, targetid);
2180 ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
2181 if (!resolve_and_bind_)
2182 return;
2184 ScopedGLErrorSuppressor suppressor(
2185 "ScopedResolvedFrameBufferBinder::dtor", decoder_->GetErrorState());
2186 decoder_->RestoreCurrentFramebufferBindings();
2187 if (decoder_->state_.enable_flags.scissor_test) {
2188 decoder_->state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
2192 BackTexture::BackTexture(
2193 MemoryTracker* memory_tracker,
2194 ContextState* state)
2195 : memory_tracker_(memory_tracker, MemoryTracker::kUnmanaged),
2196 state_(state),
2197 bytes_allocated_(0),
2198 id_(0) {
2201 BackTexture::~BackTexture() {
2202 // This does not destroy the render texture because that would require that
2203 // the associated GL context was current. Just check that it was explicitly
2204 // destroyed.
2205 DCHECK_EQ(id_, 0u);
2208 void BackTexture::Create() {
2209 ScopedGLErrorSuppressor suppressor("BackTexture::Create",
2210 state_->GetErrorState());
2211 Destroy();
2212 glGenTextures(1, &id_);
2213 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2214 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2215 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2216 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2217 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2219 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
2220 // never called on an offscreen context, no data will ever be uploaded to the
2221 // saved offscreen color texture (it is deferred until to when SwapBuffers
2222 // is called). My idea is that some nvidia drivers might have a bug where
2223 // deleting a texture that has never been populated might cause a
2224 // crash.
2225 glTexImage2D(
2226 GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
2228 bytes_allocated_ = 16u * 16u * 4u;
2229 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2232 bool BackTexture::AllocateStorage(
2233 const gfx::Size& size, GLenum format, bool zero) {
2234 DCHECK_NE(id_, 0u);
2235 ScopedGLErrorSuppressor suppressor("BackTexture::AllocateStorage",
2236 state_->GetErrorState());
2237 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2238 uint32 image_size = 0;
2239 GLES2Util::ComputeImageDataSizes(
2240 size.width(), size.height(), 1, format, GL_UNSIGNED_BYTE, 8, &image_size,
2241 NULL, NULL);
2243 if (!memory_tracker_.EnsureGPUMemoryAvailable(image_size)) {
2244 return false;
2247 scoped_ptr<char[]> zero_data;
2248 if (zero) {
2249 zero_data.reset(new char[image_size]);
2250 memset(zero_data.get(), 0, image_size);
2253 glTexImage2D(GL_TEXTURE_2D,
2254 0, // mip level
2255 format,
2256 size.width(),
2257 size.height(),
2258 0, // border
2259 format,
2260 GL_UNSIGNED_BYTE,
2261 zero_data.get());
2263 size_ = size;
2265 bool success = glGetError() == GL_NO_ERROR;
2266 if (success) {
2267 memory_tracker_.TrackMemFree(bytes_allocated_);
2268 bytes_allocated_ = image_size;
2269 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2271 return success;
2274 void BackTexture::Copy(const gfx::Size& size, GLenum format) {
2275 DCHECK_NE(id_, 0u);
2276 ScopedGLErrorSuppressor suppressor("BackTexture::Copy",
2277 state_->GetErrorState());
2278 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2279 glCopyTexImage2D(GL_TEXTURE_2D,
2280 0, // level
2281 format,
2282 0, 0,
2283 size.width(),
2284 size.height(),
2285 0); // border
2288 void BackTexture::Destroy() {
2289 if (id_ != 0) {
2290 ScopedGLErrorSuppressor suppressor("BackTexture::Destroy",
2291 state_->GetErrorState());
2292 glDeleteTextures(1, &id_);
2293 id_ = 0;
2295 memory_tracker_.TrackMemFree(bytes_allocated_);
2296 bytes_allocated_ = 0;
2299 void BackTexture::Invalidate() {
2300 id_ = 0;
2303 BackRenderbuffer::BackRenderbuffer(
2304 RenderbufferManager* renderbuffer_manager,
2305 MemoryTracker* memory_tracker,
2306 ContextState* state)
2307 : renderbuffer_manager_(renderbuffer_manager),
2308 memory_tracker_(memory_tracker, MemoryTracker::kUnmanaged),
2309 state_(state),
2310 bytes_allocated_(0),
2311 id_(0) {
2314 BackRenderbuffer::~BackRenderbuffer() {
2315 // This does not destroy the render buffer because that would require that
2316 // the associated GL context was current. Just check that it was explicitly
2317 // destroyed.
2318 DCHECK_EQ(id_, 0u);
2321 void BackRenderbuffer::Create() {
2322 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Create",
2323 state_->GetErrorState());
2324 Destroy();
2325 glGenRenderbuffersEXT(1, &id_);
2328 bool BackRenderbuffer::AllocateStorage(const FeatureInfo* feature_info,
2329 const gfx::Size& size,
2330 GLenum format,
2331 GLsizei samples) {
2332 ScopedGLErrorSuppressor suppressor(
2333 "BackRenderbuffer::AllocateStorage", state_->GetErrorState());
2334 ScopedRenderBufferBinder binder(state_, id_);
2336 uint32 estimated_size = 0;
2337 if (!renderbuffer_manager_->ComputeEstimatedRenderbufferSize(
2338 size.width(), size.height(), samples, format, &estimated_size)) {
2339 return false;
2342 if (!memory_tracker_.EnsureGPUMemoryAvailable(estimated_size)) {
2343 return false;
2346 if (samples <= 1) {
2347 glRenderbufferStorageEXT(GL_RENDERBUFFER,
2348 format,
2349 size.width(),
2350 size.height());
2351 } else {
2352 GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(feature_info,
2353 GL_RENDERBUFFER,
2354 samples,
2355 format,
2356 size.width(),
2357 size.height());
2359 bool success = glGetError() == GL_NO_ERROR;
2360 if (success) {
2361 // Mark the previously allocated bytes as free.
2362 memory_tracker_.TrackMemFree(bytes_allocated_);
2363 bytes_allocated_ = estimated_size;
2364 // Track the newly allocated bytes.
2365 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2367 return success;
2370 void BackRenderbuffer::Destroy() {
2371 if (id_ != 0) {
2372 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Destroy",
2373 state_->GetErrorState());
2374 glDeleteRenderbuffersEXT(1, &id_);
2375 id_ = 0;
2377 memory_tracker_.TrackMemFree(bytes_allocated_);
2378 bytes_allocated_ = 0;
2381 void BackRenderbuffer::Invalidate() {
2382 id_ = 0;
2385 BackFramebuffer::BackFramebuffer(GLES2DecoderImpl* decoder)
2386 : decoder_(decoder),
2387 id_(0) {
2390 BackFramebuffer::~BackFramebuffer() {
2391 // This does not destroy the frame buffer because that would require that
2392 // the associated GL context was current. Just check that it was explicitly
2393 // destroyed.
2394 DCHECK_EQ(id_, 0u);
2397 void BackFramebuffer::Create() {
2398 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Create",
2399 decoder_->GetErrorState());
2400 Destroy();
2401 glGenFramebuffersEXT(1, &id_);
2404 void BackFramebuffer::AttachRenderTexture(BackTexture* texture) {
2405 DCHECK_NE(id_, 0u);
2406 ScopedGLErrorSuppressor suppressor(
2407 "BackFramebuffer::AttachRenderTexture", decoder_->GetErrorState());
2408 ScopedFrameBufferBinder binder(decoder_, id_);
2409 GLuint attach_id = texture ? texture->id() : 0;
2410 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
2411 GL_COLOR_ATTACHMENT0,
2412 GL_TEXTURE_2D,
2413 attach_id,
2417 void BackFramebuffer::AttachRenderBuffer(GLenum target,
2418 BackRenderbuffer* render_buffer) {
2419 DCHECK_NE(id_, 0u);
2420 ScopedGLErrorSuppressor suppressor(
2421 "BackFramebuffer::AttachRenderBuffer", decoder_->GetErrorState());
2422 ScopedFrameBufferBinder binder(decoder_, id_);
2423 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
2424 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
2425 target,
2426 GL_RENDERBUFFER,
2427 attach_id);
2430 void BackFramebuffer::Destroy() {
2431 if (id_ != 0) {
2432 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Destroy",
2433 decoder_->GetErrorState());
2434 glDeleteFramebuffersEXT(1, &id_);
2435 id_ = 0;
2439 void BackFramebuffer::Invalidate() {
2440 id_ = 0;
2443 GLenum BackFramebuffer::CheckStatus() {
2444 DCHECK_NE(id_, 0u);
2445 ScopedGLErrorSuppressor suppressor("BackFramebuffer::CheckStatus",
2446 decoder_->GetErrorState());
2447 ScopedFrameBufferBinder binder(decoder_, id_);
2448 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
2451 GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
2452 return new GLES2DecoderImpl(group);
2455 GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
2456 : GLES2Decoder(),
2457 group_(group),
2458 logger_(&debug_marker_manager_),
2459 state_(group_->feature_info(), this, &logger_),
2460 unpack_flip_y_(false),
2461 unpack_premultiply_alpha_(false),
2462 unpack_unpremultiply_alpha_(false),
2463 attrib_0_buffer_id_(0),
2464 attrib_0_buffer_matches_value_(true),
2465 attrib_0_size_(0),
2466 fixed_attrib_buffer_id_(0),
2467 fixed_attrib_buffer_size_(0),
2468 offscreen_target_color_format_(0),
2469 offscreen_target_depth_format_(0),
2470 offscreen_target_stencil_format_(0),
2471 offscreen_target_samples_(0),
2472 offscreen_target_buffer_preserved_(true),
2473 offscreen_saved_color_format_(0),
2474 back_buffer_color_format_(0),
2475 back_buffer_has_depth_(false),
2476 back_buffer_has_stencil_(false),
2477 surfaceless_(false),
2478 backbuffer_needs_clear_bits_(0),
2479 current_decoder_error_(error::kNoError),
2480 use_shader_translator_(true),
2481 validators_(group_->feature_info()->validators()),
2482 feature_info_(group_->feature_info()),
2483 frame_number_(0),
2484 has_robustness_extension_(false),
2485 context_lost_reason_(error::kUnknown),
2486 context_was_lost_(false),
2487 reset_by_robustness_extension_(false),
2488 supports_post_sub_buffer_(false),
2489 force_webgl_glsl_validation_(false),
2490 derivatives_explicitly_enabled_(false),
2491 frag_depth_explicitly_enabled_(false),
2492 draw_buffers_explicitly_enabled_(false),
2493 shader_texture_lod_explicitly_enabled_(false),
2494 compile_shader_always_succeeds_(false),
2495 lose_context_when_out_of_memory_(false),
2496 service_logging_(base::CommandLine::ForCurrentProcess()->HasSwitch(
2497 switches::kEnableGPUServiceLoggingGPU)),
2498 viewport_max_width_(0),
2499 viewport_max_height_(0),
2500 texture_state_(group_->feature_info()
2501 ->workarounds()
2502 .texsubimage_faster_than_teximage),
2503 cb_command_trace_category_(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
2504 TRACE_DISABLED_BY_DEFAULT("cb_command"))),
2505 gpu_decoder_category_(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
2506 TRACE_DISABLED_BY_DEFAULT("gpu_decoder"))),
2507 gpu_trace_level_(2),
2508 gpu_trace_commands_(false),
2509 gpu_debug_commands_(false),
2510 validation_texture_(0),
2511 validation_fbo_multisample_(0),
2512 validation_fbo_(0) {
2513 DCHECK(group);
2515 // The shader translator is used for WebGL even when running on EGL
2516 // because additional restrictions are needed (like only enabling
2517 // GL_OES_standard_derivatives on demand). It is used for the unit
2518 // tests because GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes
2519 // the empty string to CompileShader and this is not a valid shader.
2520 if (gfx::GetGLImplementation() == gfx::kGLImplementationMockGL ||
2521 base::CommandLine::ForCurrentProcess()->HasSwitch(
2522 switches::kDisableGLSLTranslator)) {
2523 use_shader_translator_ = false;
2527 GLES2DecoderImpl::~GLES2DecoderImpl() {
2530 bool GLES2DecoderImpl::Initialize(
2531 const scoped_refptr<gfx::GLSurface>& surface,
2532 const scoped_refptr<gfx::GLContext>& context,
2533 bool offscreen,
2534 const gfx::Size& offscreen_size,
2535 const DisallowedFeatures& disallowed_features,
2536 const std::vector<int32>& attribs) {
2537 TRACE_EVENT0("gpu", "GLES2DecoderImpl::Initialize");
2538 DCHECK(context->IsCurrent(surface.get()));
2539 DCHECK(!context_.get());
2540 DCHECK(!offscreen || !offscreen_size.IsEmpty());
2542 ContextCreationAttribHelper attrib_parser;
2543 if (!attrib_parser.Parse(attribs))
2544 return false;
2546 surfaceless_ = surface->IsSurfaceless() && !offscreen;
2548 set_initialized();
2549 gpu_state_tracer_ = GPUStateTracer::Create(&state_);
2551 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2552 switches::kEnableGPUDebugging)) {
2553 set_debug(true);
2556 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2557 switches::kEnableGPUCommandLogging)) {
2558 set_log_commands(true);
2561 compile_shader_always_succeeds_ =
2562 base::CommandLine::ForCurrentProcess()->HasSwitch(
2563 switches::kCompileShaderAlwaysSucceeds);
2565 // Take ownership of the context and surface. The surface can be replaced with
2566 // SetSurface.
2567 context_ = context;
2568 surface_ = surface;
2570 // Create GPU Tracer for timing values.
2571 gpu_tracer_.reset(new GPUTracer(this));
2573 // Save the loseContextWhenOutOfMemory context creation attribute.
2574 lose_context_when_out_of_memory_ =
2575 attrib_parser.lose_context_when_out_of_memory;
2577 // If the failIfMajorPerformanceCaveat context creation attribute was true
2578 // and we are using a software renderer, fail.
2579 if (attrib_parser.fail_if_major_perf_caveat &&
2580 feature_info_->feature_flags().is_swiftshader) {
2581 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
2582 Destroy(true);
2583 return false;
2586 if (!group_->Initialize(this, disallowed_features)) {
2587 LOG(ERROR) << "GpuScheduler::InitializeCommon failed because group "
2588 << "failed to initialize.";
2589 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
2590 Destroy(true);
2591 return false;
2593 CHECK_GL_ERROR();
2595 if (attrib_parser.es3_context_required &&
2596 feature_info_->IsES3Capable()) {
2597 feature_info_->EnableES3Validators();
2598 set_unsafe_es3_apis_enabled(true);
2601 disallowed_features_ = disallowed_features;
2603 state_.attrib_values.resize(group_->max_vertex_attribs());
2604 vertex_array_manager_.reset(new VertexArrayManager());
2606 GLuint default_vertex_attrib_service_id = 0;
2607 if (features().native_vertex_array_object) {
2608 glGenVertexArraysOES(1, &default_vertex_attrib_service_id);
2609 glBindVertexArrayOES(default_vertex_attrib_service_id);
2612 state_.default_vertex_attrib_manager =
2613 CreateVertexAttribManager(0, default_vertex_attrib_service_id, false);
2615 state_.default_vertex_attrib_manager->Initialize(
2616 group_->max_vertex_attribs(),
2617 feature_info_->workarounds().init_vertex_attributes);
2619 // vertex_attrib_manager is set to default_vertex_attrib_manager by this call
2620 DoBindVertexArrayOES(0);
2622 query_manager_.reset(new QueryManager(this, feature_info_.get()));
2624 image_manager_.reset(new ImageManager);
2626 util_.set_num_compressed_texture_formats(
2627 validators_->compressed_texture_format.GetValues().size());
2629 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2630 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
2631 // OpenGL ES 2.0 does not have this issue.
2632 glEnableVertexAttribArray(0);
2634 glGenBuffersARB(1, &attrib_0_buffer_id_);
2635 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
2636 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
2637 glBindBuffer(GL_ARRAY_BUFFER, 0);
2638 glGenBuffersARB(1, &fixed_attrib_buffer_id_);
2640 state_.texture_units.resize(group_->max_texture_units());
2641 for (uint32 tt = 0; tt < state_.texture_units.size(); ++tt) {
2642 glActiveTexture(GL_TEXTURE0 + tt);
2643 // We want the last bind to be 2D.
2644 TextureRef* ref;
2645 if (features().oes_egl_image_external) {
2646 ref = texture_manager()->GetDefaultTextureInfo(
2647 GL_TEXTURE_EXTERNAL_OES);
2648 state_.texture_units[tt].bound_texture_external_oes = ref;
2649 glBindTexture(GL_TEXTURE_EXTERNAL_OES, ref ? ref->service_id() : 0);
2651 if (features().arb_texture_rectangle) {
2652 ref = texture_manager()->GetDefaultTextureInfo(
2653 GL_TEXTURE_RECTANGLE_ARB);
2654 state_.texture_units[tt].bound_texture_rectangle_arb = ref;
2655 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, ref ? ref->service_id() : 0);
2657 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
2658 state_.texture_units[tt].bound_texture_cube_map = ref;
2659 glBindTexture(GL_TEXTURE_CUBE_MAP, ref ? ref->service_id() : 0);
2660 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
2661 state_.texture_units[tt].bound_texture_2d = ref;
2662 glBindTexture(GL_TEXTURE_2D, ref ? ref->service_id() : 0);
2664 glActiveTexture(GL_TEXTURE0);
2665 CHECK_GL_ERROR();
2667 // cache ALPHA_BITS result for re-use with clear behaviour
2668 GLint alpha_bits = 0;
2670 if (offscreen) {
2671 if (attrib_parser.samples > 0 && attrib_parser.sample_buffers > 0 &&
2672 features().chromium_framebuffer_multisample) {
2673 // Per ext_framebuffer_multisample spec, need max bound on sample count.
2674 // max_sample_count must be initialized to a sane value. If
2675 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2676 GLint max_sample_count = 1;
2677 glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count);
2678 offscreen_target_samples_ = std::min(attrib_parser.samples,
2679 max_sample_count);
2680 } else {
2681 offscreen_target_samples_ = 1;
2683 offscreen_target_buffer_preserved_ = attrib_parser.buffer_preserved;
2685 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
2686 const bool rgb8_supported =
2687 context_->HasExtension("GL_OES_rgb8_rgba8");
2688 // The only available default render buffer formats in GLES2 have very
2689 // little precision. Don't enable multisampling unless 8-bit render
2690 // buffer formats are available--instead fall back to 8-bit textures.
2691 if (rgb8_supported && offscreen_target_samples_ > 1) {
2692 offscreen_target_color_format_ = attrib_parser.alpha_size > 0 ?
2693 GL_RGBA8 : GL_RGB8;
2694 } else {
2695 offscreen_target_samples_ = 1;
2696 offscreen_target_color_format_ =
2697 attrib_parser.alpha_size > 0 || workarounds().disable_gl_rgb_format
2698 ? GL_RGBA
2699 : GL_RGB;
2702 // ANGLE only supports packed depth/stencil formats, so use it if it is
2703 // available.
2704 const bool depth24_stencil8_supported =
2705 feature_info_->feature_flags().packed_depth24_stencil8;
2706 VLOG(1) << "GL_OES_packed_depth_stencil "
2707 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
2708 if ((attrib_parser.depth_size > 0 || attrib_parser.stencil_size > 0) &&
2709 depth24_stencil8_supported) {
2710 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2711 offscreen_target_stencil_format_ = 0;
2712 } else {
2713 // It may be the case that this depth/stencil combination is not
2714 // supported, but this will be checked later by CheckFramebufferStatus.
2715 offscreen_target_depth_format_ = attrib_parser.depth_size > 0 ?
2716 GL_DEPTH_COMPONENT16 : 0;
2717 offscreen_target_stencil_format_ = attrib_parser.stencil_size > 0 ?
2718 GL_STENCIL_INDEX8 : 0;
2720 } else {
2721 offscreen_target_color_format_ =
2722 attrib_parser.alpha_size > 0 || workarounds().disable_gl_rgb_format
2723 ? GL_RGBA
2724 : GL_RGB;
2726 // If depth is requested at all, use the packed depth stencil format if
2727 // it's available, as some desktop GL drivers don't support any non-packed
2728 // formats for depth attachments.
2729 const bool depth24_stencil8_supported =
2730 feature_info_->feature_flags().packed_depth24_stencil8;
2731 VLOG(1) << "GL_EXT_packed_depth_stencil "
2732 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
2734 if ((attrib_parser.depth_size > 0 || attrib_parser.stencil_size > 0) &&
2735 depth24_stencil8_supported) {
2736 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2737 offscreen_target_stencil_format_ = 0;
2738 } else {
2739 offscreen_target_depth_format_ = attrib_parser.depth_size > 0 ?
2740 GL_DEPTH_COMPONENT : 0;
2741 offscreen_target_stencil_format_ = attrib_parser.stencil_size > 0 ?
2742 GL_STENCIL_INDEX : 0;
2746 offscreen_saved_color_format_ =
2747 attrib_parser.alpha_size > 0 || workarounds().disable_gl_rgb_format
2748 ? GL_RGBA
2749 : GL_RGB;
2751 // Create the target frame buffer. This is the one that the client renders
2752 // directly to.
2753 offscreen_target_frame_buffer_.reset(new BackFramebuffer(this));
2754 offscreen_target_frame_buffer_->Create();
2755 // Due to GLES2 format limitations, either the color texture (for
2756 // non-multisampling) or the color render buffer (for multisampling) will be
2757 // attached to the offscreen frame buffer. The render buffer has more
2758 // limited formats available to it, but the texture can't do multisampling.
2759 if (IsOffscreenBufferMultisampled()) {
2760 offscreen_target_color_render_buffer_.reset(new BackRenderbuffer(
2761 renderbuffer_manager(), memory_tracker(), &state_));
2762 offscreen_target_color_render_buffer_->Create();
2763 } else {
2764 offscreen_target_color_texture_.reset(new BackTexture(
2765 memory_tracker(), &state_));
2766 offscreen_target_color_texture_->Create();
2768 offscreen_target_depth_render_buffer_.reset(new BackRenderbuffer(
2769 renderbuffer_manager(), memory_tracker(), &state_));
2770 offscreen_target_depth_render_buffer_->Create();
2771 offscreen_target_stencil_render_buffer_.reset(new BackRenderbuffer(
2772 renderbuffer_manager(), memory_tracker(), &state_));
2773 offscreen_target_stencil_render_buffer_->Create();
2775 // Create the saved offscreen texture. The target frame buffer is copied
2776 // here when SwapBuffers is called.
2777 offscreen_saved_frame_buffer_.reset(new BackFramebuffer(this));
2778 offscreen_saved_frame_buffer_->Create();
2780 offscreen_saved_color_texture_.reset(new BackTexture(
2781 memory_tracker(), &state_));
2782 offscreen_saved_color_texture_->Create();
2784 // Allocate the render buffers at their initial size and check the status
2785 // of the frame buffers is okay.
2786 if (!ResizeOffscreenFrameBuffer(offscreen_size)) {
2787 LOG(ERROR) << "Could not allocate offscreen buffer storage.";
2788 Destroy(true);
2789 return false;
2792 state_.viewport_width = offscreen_size.width();
2793 state_.viewport_height = offscreen_size.height();
2795 // Allocate the offscreen saved color texture.
2796 DCHECK(offscreen_saved_color_format_);
2797 offscreen_saved_color_texture_->AllocateStorage(
2798 gfx::Size(1, 1), offscreen_saved_color_format_, true);
2800 offscreen_saved_frame_buffer_->AttachRenderTexture(
2801 offscreen_saved_color_texture_.get());
2802 if (offscreen_saved_frame_buffer_->CheckStatus() !=
2803 GL_FRAMEBUFFER_COMPLETE) {
2804 LOG(ERROR) << "Offscreen saved FBO was incomplete.";
2805 Destroy(true);
2806 return false;
2809 // Bind to the new default frame buffer (the offscreen target frame buffer).
2810 // This should now be associated with ID zero.
2811 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2812 } else {
2813 glBindFramebufferEXT(GL_FRAMEBUFFER, GetBackbufferServiceId());
2814 // These are NOT if the back buffer has these proprorties. They are
2815 // if we want the command buffer to enforce them regardless of what
2816 // the real backbuffer is assuming the real back buffer gives us more than
2817 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2818 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2819 // can't do anything about that.
2821 if (!surfaceless_) {
2822 GLint depth_bits = 0;
2823 GLint stencil_bits = 0;
2825 bool default_fb = (GetBackbufferServiceId() == 0);
2827 if (feature_info_->gl_version_info().is_desktop_core_profile) {
2828 glGetFramebufferAttachmentParameterivEXT(
2829 GL_FRAMEBUFFER,
2830 default_fb ? GL_BACK_LEFT : GL_COLOR_ATTACHMENT0,
2831 GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE, &alpha_bits);
2832 glGetFramebufferAttachmentParameterivEXT(
2833 GL_FRAMEBUFFER,
2834 default_fb ? GL_DEPTH : GL_DEPTH_ATTACHMENT,
2835 GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE, &depth_bits);
2836 glGetFramebufferAttachmentParameterivEXT(
2837 GL_FRAMEBUFFER,
2838 default_fb ? GL_STENCIL : GL_STENCIL_ATTACHMENT,
2839 GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE, &stencil_bits);
2840 } else {
2841 glGetIntegerv(GL_ALPHA_BITS, &alpha_bits);
2842 glGetIntegerv(GL_DEPTH_BITS, &depth_bits);
2843 glGetIntegerv(GL_STENCIL_BITS, &stencil_bits);
2846 // This checks if the user requested RGBA and we have RGBA then RGBA. If
2847 // the user requested RGB then RGB. If the user did not specify a
2848 // preference than use whatever we were given. Same for DEPTH and STENCIL.
2849 back_buffer_color_format_ =
2850 (attrib_parser.alpha_size != 0 && alpha_bits > 0) ? GL_RGBA : GL_RGB;
2851 back_buffer_has_depth_ = attrib_parser.depth_size != 0 && depth_bits > 0;
2852 back_buffer_has_stencil_ =
2853 attrib_parser.stencil_size != 0 && stencil_bits > 0;
2856 state_.viewport_width = surface->GetSize().width();
2857 state_.viewport_height = surface->GetSize().height();
2860 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2861 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2862 // isn't well documented; it was discovered in the Khronos OpenGL ES
2863 // mailing list archives. It also implicitly enables the desktop GL
2864 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2865 // variable in fragment shaders.
2866 if (!feature_info_->gl_version_info().BehavesLikeGLES()) {
2867 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
2868 glEnable(GL_POINT_SPRITE);
2871 has_robustness_extension_ =
2872 context->HasExtension("GL_ARB_robustness") ||
2873 context->HasExtension("GL_KHR_robustness") ||
2874 context->HasExtension("GL_EXT_robustness");
2876 if (!InitializeShaderTranslator()) {
2877 return false;
2880 GLint viewport_params[4] = { 0 };
2881 glGetIntegerv(GL_MAX_VIEWPORT_DIMS, viewport_params);
2882 viewport_max_width_ = viewport_params[0];
2883 viewport_max_height_ = viewport_params[1];
2885 state_.scissor_width = state_.viewport_width;
2886 state_.scissor_height = state_.viewport_height;
2888 // Set all the default state because some GL drivers get it wrong.
2889 state_.InitCapabilities(NULL);
2890 state_.InitState(NULL);
2891 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
2893 DoBindBuffer(GL_ARRAY_BUFFER, 0);
2894 DoBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
2895 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2896 DoBindRenderbuffer(GL_RENDERBUFFER, 0);
2897 DoBindValueBufferCHROMIUM(GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM, 0);
2899 bool call_gl_clear = !surfaceless_;
2900 #if defined(OS_ANDROID)
2901 // Temporary workaround for Android WebView because this clear ignores the
2902 // clip and corrupts that external UI of the App. Not calling glClear is ok
2903 // because the system already clears the buffer before each draw. Proper
2904 // fix might be setting the scissor clip properly before initialize. See
2905 // crbug.com/259023 for details.
2906 call_gl_clear = surface_->GetHandle();
2907 #endif
2908 if (call_gl_clear) {
2909 // On configs where we report no alpha, if the underlying surface has
2910 // alpha, clear the surface alpha to 1.0 to be correct on ReadPixels/etc.
2911 bool clear_alpha = back_buffer_color_format_ == GL_RGB && alpha_bits > 0;
2912 if (clear_alpha) {
2913 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
2916 // Clear the backbuffer.
2917 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2919 // Restore alpha clear value if we changed it.
2920 if (clear_alpha) {
2921 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
2925 supports_post_sub_buffer_ = surface->SupportsPostSubBuffer();
2926 if (feature_info_->workarounds()
2927 .disable_post_sub_buffers_for_onscreen_surfaces &&
2928 !surface->IsOffscreen())
2929 supports_post_sub_buffer_ = false;
2931 if (feature_info_->workarounds().reverse_point_sprite_coord_origin) {
2932 glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT);
2935 if (feature_info_->workarounds().unbind_fbo_on_context_switch) {
2936 context_->SetUnbindFboOnMakeCurrent();
2939 // Only compositor contexts are known to use only the subset of GL
2940 // that can be safely migrated between the iGPU and the dGPU. Mark
2941 // those contexts as safe to forcibly transition between the GPUs.
2942 // http://crbug.com/180876, http://crbug.com/227228
2943 if (!offscreen)
2944 context_->SetSafeToForceGpuSwitch();
2946 async_pixel_transfer_manager_.reset(
2947 AsyncPixelTransferManager::Create(context.get()));
2948 async_pixel_transfer_manager_->Initialize(texture_manager());
2950 if (workarounds().gl_clear_broken) {
2951 DCHECK(!clear_framebuffer_blit_.get());
2952 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glClearWorkaroundInit");
2953 clear_framebuffer_blit_.reset(new ClearFramebufferResourceManager(this));
2954 if (LOCAL_PEEK_GL_ERROR("glClearWorkaroundInit") != GL_NO_ERROR)
2955 return false;
2958 framebuffer_manager()->AddObserver(this);
2960 return true;
2963 Capabilities GLES2DecoderImpl::GetCapabilities() {
2964 DCHECK(initialized());
2965 Capabilities caps;
2966 caps.VisitPrecisions([](GLenum shader, GLenum type,
2967 Capabilities::ShaderPrecision* shader_precision) {
2968 GLint range[2] = {0, 0};
2969 GLint precision = 0;
2970 GetShaderPrecisionFormatImpl(shader, type, range, &precision);
2971 shader_precision->min_range = range[0];
2972 shader_precision->max_range = range[1];
2973 shader_precision->precision = precision;
2975 DoGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS,
2976 &caps.max_combined_texture_image_units);
2977 DoGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &caps.max_cube_map_texture_size);
2978 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS,
2979 &caps.max_fragment_uniform_vectors);
2980 DoGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &caps.max_renderbuffer_size);
2981 DoGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &caps.max_texture_image_units);
2982 DoGetIntegerv(GL_MAX_TEXTURE_SIZE, &caps.max_texture_size);
2983 DoGetIntegerv(GL_MAX_VARYING_VECTORS, &caps.max_varying_vectors);
2984 DoGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &caps.max_vertex_attribs);
2985 DoGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS,
2986 &caps.max_vertex_texture_image_units);
2987 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS,
2988 &caps.max_vertex_uniform_vectors);
2989 DoGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS,
2990 &caps.num_compressed_texture_formats);
2991 DoGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS, &caps.num_shader_binary_formats);
2992 DoGetIntegerv(GL_BIND_GENERATES_RESOURCE_CHROMIUM,
2993 &caps.bind_generates_resource_chromium);
2994 if (unsafe_es3_apis_enabled()) {
2995 // TODO(zmo): Note that some parameter values could be more than 32-bit,
2996 // but for now we clamp them to 32-bit max.
2997 DoGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &caps.max_3d_texture_size);
2998 DoGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &caps.max_array_texture_layers);
2999 DoGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &caps.max_color_attachments);
3000 DoGetInteger64v(GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS,
3001 &caps.max_combined_fragment_uniform_components);
3002 DoGetIntegerv(GL_MAX_COMBINED_UNIFORM_BLOCKS,
3003 &caps.max_combined_uniform_blocks);
3004 DoGetInteger64v(GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS,
3005 &caps.max_combined_vertex_uniform_components);
3006 DoGetIntegerv(GL_MAX_DRAW_BUFFERS, &caps.max_draw_buffers);
3007 DoGetInteger64v(GL_MAX_ELEMENT_INDEX, &caps.max_element_index);
3008 DoGetIntegerv(GL_MAX_ELEMENTS_INDICES, &caps.max_elements_indices);
3009 DoGetIntegerv(GL_MAX_ELEMENTS_VERTICES, &caps.max_elements_vertices);
3010 DoGetIntegerv(GL_MAX_FRAGMENT_INPUT_COMPONENTS,
3011 &caps.max_fragment_input_components);
3012 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_BLOCKS,
3013 &caps.max_fragment_uniform_blocks);
3014 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS,
3015 &caps.max_fragment_uniform_components);
3016 DoGetIntegerv(GL_MAX_PROGRAM_TEXEL_OFFSET,
3017 &caps.max_program_texel_offset);
3018 DoGetInteger64v(GL_MAX_SERVER_WAIT_TIMEOUT, &caps.max_server_wait_timeout);
3019 // Work around Linux NVIDIA driver bug where GL_TIMEOUT_IGNORED is
3020 // returned.
3021 if (caps.max_server_wait_timeout < 0)
3022 caps.max_server_wait_timeout = 0;
3023 DoGetFloatv(GL_MAX_TEXTURE_LOD_BIAS, &caps.max_texture_lod_bias);
3024 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS,
3025 &caps.max_transform_feedback_interleaved_components);
3026 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS,
3027 &caps.max_transform_feedback_separate_attribs);
3028 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS,
3029 &caps.max_transform_feedback_separate_components);
3030 DoGetInteger64v(GL_MAX_UNIFORM_BLOCK_SIZE, &caps.max_uniform_block_size);
3031 DoGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS,
3032 &caps.max_uniform_buffer_bindings);
3033 DoGetIntegerv(GL_MAX_VARYING_COMPONENTS, &caps.max_varying_components);
3034 DoGetIntegerv(GL_MAX_VERTEX_OUTPUT_COMPONENTS,
3035 &caps.max_vertex_output_components);
3036 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_BLOCKS,
3037 &caps.max_vertex_uniform_blocks);
3038 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS,
3039 &caps.max_vertex_uniform_components);
3040 DoGetIntegerv(GL_MIN_PROGRAM_TEXEL_OFFSET, &caps.min_program_texel_offset);
3041 DoGetIntegerv(GL_NUM_EXTENSIONS, &caps.num_extensions);
3042 DoGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS,
3043 &caps.num_program_binary_formats);
3044 DoGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT,
3045 &caps.uniform_buffer_offset_alignment);
3046 // TODO(zmo): once we switch to MANGLE, we should query version numbers.
3047 caps.major_version = 3;
3048 caps.minor_version = 0;
3050 if (feature_info_->feature_flags().multisampled_render_to_texture ||
3051 feature_info_->feature_flags().chromium_framebuffer_multisample ||
3052 unsafe_es3_apis_enabled()) {
3053 DoGetIntegerv(GL_MAX_SAMPLES, &caps.max_samples);
3056 caps.egl_image_external =
3057 feature_info_->feature_flags().oes_egl_image_external;
3058 caps.texture_format_atc =
3059 feature_info_->feature_flags().ext_texture_format_atc;
3060 caps.texture_format_bgra8888 =
3061 feature_info_->feature_flags().ext_texture_format_bgra8888;
3062 caps.texture_format_dxt1 =
3063 feature_info_->feature_flags().ext_texture_format_dxt1;
3064 caps.texture_format_dxt5 =
3065 feature_info_->feature_flags().ext_texture_format_dxt5;
3066 caps.texture_format_etc1 =
3067 feature_info_->feature_flags().oes_compressed_etc1_rgb8_texture;
3068 caps.texture_format_etc1_npot =
3069 caps.texture_format_etc1 && !workarounds().etc1_power_of_two_only;
3070 caps.texture_rectangle = feature_info_->feature_flags().arb_texture_rectangle;
3071 caps.texture_usage = feature_info_->feature_flags().angle_texture_usage;
3072 caps.texture_storage = feature_info_->feature_flags().ext_texture_storage;
3073 caps.discard_framebuffer =
3074 feature_info_->feature_flags().ext_discard_framebuffer;
3075 caps.sync_query = feature_info_->feature_flags().chromium_sync_query;
3077 #if defined(OS_MACOSX)
3078 // This is unconditionally true on mac, no need to test for it at runtime.
3079 caps.iosurface = true;
3080 #endif
3082 caps.post_sub_buffer = supports_post_sub_buffer_;
3083 caps.image = true;
3085 caps.blend_equation_advanced =
3086 feature_info_->feature_flags().blend_equation_advanced;
3087 caps.blend_equation_advanced_coherent =
3088 feature_info_->feature_flags().blend_equation_advanced_coherent;
3089 caps.texture_rg = feature_info_->feature_flags().ext_texture_rg;
3090 return caps;
3093 void GLES2DecoderImpl::UpdateCapabilities() {
3094 util_.set_num_compressed_texture_formats(
3095 validators_->compressed_texture_format.GetValues().size());
3096 util_.set_num_shader_binary_formats(
3097 validators_->shader_binary_format.GetValues().size());
3100 bool GLES2DecoderImpl::InitializeShaderTranslator() {
3101 TRACE_EVENT0("gpu", "GLES2DecoderImpl::InitializeShaderTranslator");
3103 if (!use_shader_translator_) {
3104 return true;
3106 ShBuiltInResources resources;
3107 ShInitBuiltInResources(&resources);
3108 resources.MaxVertexAttribs = group_->max_vertex_attribs();
3109 resources.MaxVertexUniformVectors =
3110 group_->max_vertex_uniform_vectors();
3111 resources.MaxVaryingVectors = group_->max_varying_vectors();
3112 resources.MaxVertexTextureImageUnits =
3113 group_->max_vertex_texture_image_units();
3114 resources.MaxCombinedTextureImageUnits = group_->max_texture_units();
3115 resources.MaxTextureImageUnits = group_->max_texture_image_units();
3116 resources.MaxFragmentUniformVectors =
3117 group_->max_fragment_uniform_vectors();
3118 resources.MaxDrawBuffers = group_->max_draw_buffers();
3119 resources.MaxExpressionComplexity = 256;
3120 resources.MaxCallStackDepth = 256;
3122 GLint range[2] = { 0, 0 };
3123 GLint precision = 0;
3124 GetShaderPrecisionFormatImpl(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT,
3125 range, &precision);
3126 resources.FragmentPrecisionHigh =
3127 PrecisionMeetsSpecForHighpFloat(range[0], range[1], precision);
3129 if (force_webgl_glsl_validation_) {
3130 resources.OES_standard_derivatives = derivatives_explicitly_enabled_;
3131 resources.EXT_frag_depth = frag_depth_explicitly_enabled_;
3132 resources.EXT_draw_buffers = draw_buffers_explicitly_enabled_;
3133 if (!draw_buffers_explicitly_enabled_)
3134 resources.MaxDrawBuffers = 1;
3135 resources.EXT_shader_texture_lod = shader_texture_lod_explicitly_enabled_;
3136 resources.NV_draw_buffers =
3137 draw_buffers_explicitly_enabled_ && features().nv_draw_buffers;
3138 } else {
3139 resources.OES_standard_derivatives =
3140 features().oes_standard_derivatives ? 1 : 0;
3141 resources.ARB_texture_rectangle =
3142 features().arb_texture_rectangle ? 1 : 0;
3143 resources.OES_EGL_image_external =
3144 features().oes_egl_image_external ? 1 : 0;
3145 resources.EXT_draw_buffers =
3146 features().ext_draw_buffers ? 1 : 0;
3147 resources.EXT_frag_depth =
3148 features().ext_frag_depth ? 1 : 0;
3149 resources.EXT_shader_texture_lod =
3150 features().ext_shader_texture_lod ? 1 : 0;
3151 resources.NV_draw_buffers =
3152 features().nv_draw_buffers ? 1 : 0;
3155 ShShaderSpec shader_spec;
3156 if (force_webgl_glsl_validation_) {
3157 shader_spec = unsafe_es3_apis_enabled() ? SH_WEBGL2_SPEC : SH_WEBGL_SPEC;
3158 } else {
3159 shader_spec = unsafe_es3_apis_enabled() ? SH_GLES3_SPEC : SH_GLES2_SPEC;
3162 if ((shader_spec == SH_WEBGL_SPEC || shader_spec == SH_WEBGL2_SPEC) &&
3163 features().enable_shader_name_hashing)
3164 resources.HashFunction = &CityHash64;
3165 else
3166 resources.HashFunction = NULL;
3167 ShaderTranslatorInterface::GlslImplementationType implementation_type =
3168 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 ?
3169 ShaderTranslatorInterface::kGlslES : ShaderTranslatorInterface::kGlsl;
3170 int driver_bug_workarounds = 0;
3171 if (workarounds().needs_glsl_built_in_function_emulation)
3172 driver_bug_workarounds |= SH_EMULATE_BUILT_IN_FUNCTIONS;
3173 if (workarounds().init_gl_position_in_vertex_shader)
3174 driver_bug_workarounds |= SH_INIT_GL_POSITION;
3175 if (workarounds().unfold_short_circuit_as_ternary_operation)
3176 driver_bug_workarounds |= SH_UNFOLD_SHORT_CIRCUIT;
3177 if (workarounds().init_varyings_without_static_use)
3178 driver_bug_workarounds |= SH_INIT_VARYINGS_WITHOUT_STATIC_USE;
3179 if (workarounds().unroll_for_loop_with_sampler_array_index)
3180 driver_bug_workarounds |= SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX;
3181 if (workarounds().scalarize_vec_and_mat_constructor_args)
3182 driver_bug_workarounds |= SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS;
3183 if (workarounds().regenerate_struct_names)
3184 driver_bug_workarounds |= SH_REGENERATE_STRUCT_NAMES;
3186 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
3187 switches::kEmulateShaderPrecision))
3188 resources.WEBGL_debug_shader_precision = true;
3190 vertex_translator_ = shader_translator_cache()->GetTranslator(
3191 GL_VERTEX_SHADER,
3192 shader_spec,
3193 &resources,
3194 implementation_type,
3195 static_cast<ShCompileOptions>(driver_bug_workarounds));
3196 if (!vertex_translator_.get()) {
3197 LOG(ERROR) << "Could not initialize vertex shader translator.";
3198 Destroy(true);
3199 return false;
3202 fragment_translator_ = shader_translator_cache()->GetTranslator(
3203 GL_FRAGMENT_SHADER,
3204 shader_spec,
3205 &resources,
3206 implementation_type,
3207 static_cast<ShCompileOptions>(driver_bug_workarounds));
3208 if (!fragment_translator_.get()) {
3209 LOG(ERROR) << "Could not initialize fragment shader translator.";
3210 Destroy(true);
3211 return false;
3213 return true;
3216 bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
3217 for (GLsizei ii = 0; ii < n; ++ii) {
3218 if (GetBuffer(client_ids[ii])) {
3219 return false;
3222 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3223 glGenBuffersARB(n, service_ids.get());
3224 for (GLsizei ii = 0; ii < n; ++ii) {
3225 CreateBuffer(client_ids[ii], service_ids[ii]);
3227 return true;
3230 bool GLES2DecoderImpl::GenFramebuffersHelper(
3231 GLsizei n, const GLuint* client_ids) {
3232 for (GLsizei ii = 0; ii < n; ++ii) {
3233 if (GetFramebuffer(client_ids[ii])) {
3234 return false;
3237 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3238 glGenFramebuffersEXT(n, service_ids.get());
3239 for (GLsizei ii = 0; ii < n; ++ii) {
3240 CreateFramebuffer(client_ids[ii], service_ids[ii]);
3242 return true;
3245 bool GLES2DecoderImpl::GenRenderbuffersHelper(
3246 GLsizei n, const GLuint* client_ids) {
3247 for (GLsizei ii = 0; ii < n; ++ii) {
3248 if (GetRenderbuffer(client_ids[ii])) {
3249 return false;
3252 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3253 glGenRenderbuffersEXT(n, service_ids.get());
3254 for (GLsizei ii = 0; ii < n; ++ii) {
3255 CreateRenderbuffer(client_ids[ii], service_ids[ii]);
3257 return true;
3260 bool GLES2DecoderImpl::GenValuebuffersCHROMIUMHelper(GLsizei n,
3261 const GLuint* client_ids) {
3262 for (GLsizei ii = 0; ii < n; ++ii) {
3263 if (GetValuebuffer(client_ids[ii])) {
3264 return false;
3267 for (GLsizei ii = 0; ii < n; ++ii) {
3268 CreateValuebuffer(client_ids[ii]);
3270 return true;
3273 bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
3274 for (GLsizei ii = 0; ii < n; ++ii) {
3275 if (GetTexture(client_ids[ii])) {
3276 return false;
3279 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3280 glGenTextures(n, service_ids.get());
3281 for (GLsizei ii = 0; ii < n; ++ii) {
3282 CreateTexture(client_ids[ii], service_ids[ii]);
3284 return true;
3287 void GLES2DecoderImpl::DeleteBuffersHelper(
3288 GLsizei n, const GLuint* client_ids) {
3289 for (GLsizei ii = 0; ii < n; ++ii) {
3290 Buffer* buffer = GetBuffer(client_ids[ii]);
3291 if (buffer && !buffer->IsDeleted()) {
3292 buffer->RemoveMappedRange();
3293 state_.RemoveBoundBuffer(buffer);
3294 RemoveBuffer(client_ids[ii]);
3299 void GLES2DecoderImpl::DeleteFramebuffersHelper(
3300 GLsizei n, const GLuint* client_ids) {
3301 bool supports_separate_framebuffer_binds =
3302 features().chromium_framebuffer_multisample;
3304 for (GLsizei ii = 0; ii < n; ++ii) {
3305 Framebuffer* framebuffer =
3306 GetFramebuffer(client_ids[ii]);
3307 if (framebuffer && !framebuffer->IsDeleted()) {
3308 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
3309 GLenum target = supports_separate_framebuffer_binds ?
3310 GL_DRAW_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
3312 // Unbind attachments on FBO before deletion.
3313 if (workarounds().unbind_attachments_on_bound_render_fbo_delete)
3314 framebuffer->DoUnbindGLAttachmentsForWorkaround(target);
3316 glBindFramebufferEXT(target, GetBackbufferServiceId());
3317 framebuffer_state_.bound_draw_framebuffer = NULL;
3318 framebuffer_state_.clear_state_dirty = true;
3320 if (framebuffer == framebuffer_state_.bound_read_framebuffer.get()) {
3321 framebuffer_state_.bound_read_framebuffer = NULL;
3322 GLenum target = supports_separate_framebuffer_binds ?
3323 GL_READ_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
3324 glBindFramebufferEXT(target, GetBackbufferServiceId());
3326 OnFboChanged();
3327 RemoveFramebuffer(client_ids[ii]);
3332 void GLES2DecoderImpl::DeleteRenderbuffersHelper(
3333 GLsizei n, const GLuint* client_ids) {
3334 bool supports_separate_framebuffer_binds =
3335 features().chromium_framebuffer_multisample;
3336 for (GLsizei ii = 0; ii < n; ++ii) {
3337 Renderbuffer* renderbuffer =
3338 GetRenderbuffer(client_ids[ii]);
3339 if (renderbuffer && !renderbuffer->IsDeleted()) {
3340 if (state_.bound_renderbuffer.get() == renderbuffer) {
3341 state_.bound_renderbuffer = NULL;
3343 // Unbind from current framebuffers.
3344 if (supports_separate_framebuffer_binds) {
3345 if (framebuffer_state_.bound_read_framebuffer.get()) {
3346 framebuffer_state_.bound_read_framebuffer
3347 ->UnbindRenderbuffer(GL_READ_FRAMEBUFFER_EXT, renderbuffer);
3349 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3350 framebuffer_state_.bound_draw_framebuffer
3351 ->UnbindRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT, renderbuffer);
3353 } else {
3354 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3355 framebuffer_state_.bound_draw_framebuffer
3356 ->UnbindRenderbuffer(GL_FRAMEBUFFER, renderbuffer);
3359 framebuffer_state_.clear_state_dirty = true;
3360 RemoveRenderbuffer(client_ids[ii]);
3365 void GLES2DecoderImpl::DeleteValuebuffersCHROMIUMHelper(
3366 GLsizei n,
3367 const GLuint* client_ids) {
3368 for (GLsizei ii = 0; ii < n; ++ii) {
3369 Valuebuffer* valuebuffer = GetValuebuffer(client_ids[ii]);
3370 if (valuebuffer) {
3371 if (state_.bound_valuebuffer.get() == valuebuffer) {
3372 state_.bound_valuebuffer = NULL;
3374 RemoveValuebuffer(client_ids[ii]);
3379 void GLES2DecoderImpl::DeleteTexturesHelper(
3380 GLsizei n, const GLuint* client_ids) {
3381 bool supports_separate_framebuffer_binds =
3382 features().chromium_framebuffer_multisample;
3383 for (GLsizei ii = 0; ii < n; ++ii) {
3384 TextureRef* texture_ref = GetTexture(client_ids[ii]);
3385 if (texture_ref) {
3386 Texture* texture = texture_ref->texture();
3387 if (texture->IsAttachedToFramebuffer()) {
3388 framebuffer_state_.clear_state_dirty = true;
3390 // Unbind texture_ref from texture_ref units.
3391 for (size_t jj = 0; jj < state_.texture_units.size(); ++jj) {
3392 state_.texture_units[jj].Unbind(texture_ref);
3394 // Unbind from current framebuffers.
3395 if (supports_separate_framebuffer_binds) {
3396 if (framebuffer_state_.bound_read_framebuffer.get()) {
3397 framebuffer_state_.bound_read_framebuffer
3398 ->UnbindTexture(GL_READ_FRAMEBUFFER_EXT, texture_ref);
3400 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3401 framebuffer_state_.bound_draw_framebuffer
3402 ->UnbindTexture(GL_DRAW_FRAMEBUFFER_EXT, texture_ref);
3404 } else {
3405 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3406 framebuffer_state_.bound_draw_framebuffer
3407 ->UnbindTexture(GL_FRAMEBUFFER, texture_ref);
3410 #if defined(OS_MACOSX)
3411 GLuint service_id = texture->service_id();
3412 if (texture->target() == GL_TEXTURE_RECTANGLE_ARB) {
3413 ReleaseIOSurfaceForTexture(service_id);
3415 #endif
3416 RemoveTexture(client_ids[ii]);
3421 // } // anonymous namespace
3423 bool GLES2DecoderImpl::MakeCurrent() {
3424 if (!context_.get())
3425 return false;
3427 if (WasContextLost()) {
3428 LOG(ERROR) << " GLES2DecoderImpl: Trying to make lost context current.";
3429 return false;
3432 if (!context_->MakeCurrent(surface_.get())) {
3433 LOG(ERROR) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
3434 MarkContextLost(error::kMakeCurrentFailed);
3435 group_->LoseContexts(error::kUnknown);
3436 return false;
3439 if (CheckResetStatus()) {
3440 LOG(ERROR)
3441 << " GLES2DecoderImpl: Context reset detected after MakeCurrent.";
3442 group_->LoseContexts(error::kUnknown);
3443 return false;
3446 ProcessFinishedAsyncTransfers();
3448 // Rebind the FBO if it was unbound by the context.
3449 if (workarounds().unbind_fbo_on_context_switch)
3450 RestoreFramebufferBindings();
3452 framebuffer_state_.clear_state_dirty = true;
3454 return true;
3457 void GLES2DecoderImpl::ProcessFinishedAsyncTransfers() {
3458 ProcessPendingReadPixels();
3459 if (engine() && query_manager_.get())
3460 query_manager_->ProcessPendingTransferQueries();
3462 // TODO(epenner): Is there a better place to do this?
3463 // This needs to occur before we execute any batch of commands
3464 // from the client, as the client may have recieved an async
3465 // completion while issuing those commands.
3466 // "DidFlushStart" would be ideal if we had such a callback.
3467 async_pixel_transfer_manager_->BindCompletedAsyncTransfers();
3470 static void RebindCurrentFramebuffer(
3471 GLenum target,
3472 Framebuffer* framebuffer,
3473 GLuint back_buffer_service_id) {
3474 GLuint framebuffer_id = framebuffer ? framebuffer->service_id() : 0;
3476 if (framebuffer_id == 0) {
3477 framebuffer_id = back_buffer_service_id;
3480 glBindFramebufferEXT(target, framebuffer_id);
3483 void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
3484 framebuffer_state_.clear_state_dirty = true;
3486 if (!features().chromium_framebuffer_multisample) {
3487 RebindCurrentFramebuffer(
3488 GL_FRAMEBUFFER,
3489 framebuffer_state_.bound_draw_framebuffer.get(),
3490 GetBackbufferServiceId());
3491 } else {
3492 RebindCurrentFramebuffer(
3493 GL_READ_FRAMEBUFFER_EXT,
3494 framebuffer_state_.bound_read_framebuffer.get(),
3495 GetBackbufferServiceId());
3496 RebindCurrentFramebuffer(
3497 GL_DRAW_FRAMEBUFFER_EXT,
3498 framebuffer_state_.bound_draw_framebuffer.get(),
3499 GetBackbufferServiceId());
3501 OnFboChanged();
3504 bool GLES2DecoderImpl::CheckFramebufferValid(
3505 Framebuffer* framebuffer,
3506 GLenum target, const char* func_name) {
3507 if (!framebuffer) {
3508 if (surfaceless_)
3509 return false;
3510 if (backbuffer_needs_clear_bits_) {
3511 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3512 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1.f);
3513 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3514 glClearStencil(0);
3515 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
3516 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
3517 glClearDepth(1.0f);
3518 state_.SetDeviceDepthMask(GL_TRUE);
3519 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
3520 bool reset_draw_buffer = false;
3521 if ((backbuffer_needs_clear_bits_ & GL_COLOR_BUFFER_BIT) != 0 &&
3522 group_->draw_buffer() == GL_NONE) {
3523 reset_draw_buffer = true;
3524 GLenum buf = GL_BACK;
3525 if (GetBackbufferServiceId() != 0) // emulated backbuffer
3526 buf = GL_COLOR_ATTACHMENT0;
3527 glDrawBuffersARB(1, &buf);
3529 glClear(backbuffer_needs_clear_bits_);
3530 if (reset_draw_buffer) {
3531 GLenum buf = GL_NONE;
3532 glDrawBuffersARB(1, &buf);
3534 backbuffer_needs_clear_bits_ = 0;
3535 RestoreClearState();
3537 return true;
3540 if (framebuffer_manager()->IsComplete(framebuffer)) {
3541 return true;
3544 GLenum completeness = framebuffer->IsPossiblyComplete();
3545 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
3546 LOCAL_SET_GL_ERROR(
3547 GL_INVALID_FRAMEBUFFER_OPERATION, func_name, "framebuffer incomplete");
3548 return false;
3551 // Are all the attachments cleared?
3552 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
3553 texture_manager()->HaveUnclearedMips()) {
3554 if (!framebuffer->IsCleared()) {
3555 // Can we clear them?
3556 if (framebuffer->GetStatus(texture_manager(), target) !=
3557 GL_FRAMEBUFFER_COMPLETE) {
3558 LOCAL_SET_GL_ERROR(
3559 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
3560 "framebuffer incomplete (clear)");
3561 return false;
3563 ClearUnclearedAttachments(target, framebuffer);
3567 if (!framebuffer_manager()->IsComplete(framebuffer)) {
3568 if (framebuffer->GetStatus(texture_manager(), target) !=
3569 GL_FRAMEBUFFER_COMPLETE) {
3570 LOCAL_SET_GL_ERROR(
3571 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
3572 "framebuffer incomplete (check)");
3573 return false;
3575 framebuffer_manager()->MarkAsComplete(framebuffer);
3578 // NOTE: At this point we don't know if the framebuffer is complete but
3579 // we DO know that everything that needs to be cleared has been cleared.
3580 return true;
3583 bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name) {
3584 if (!features().chromium_framebuffer_multisample) {
3585 bool valid = CheckFramebufferValid(
3586 framebuffer_state_.bound_draw_framebuffer.get(), GL_FRAMEBUFFER_EXT,
3587 func_name);
3589 if (valid)
3590 OnUseFramebuffer();
3592 return valid;
3594 return CheckFramebufferValid(framebuffer_state_.bound_draw_framebuffer.get(),
3595 GL_DRAW_FRAMEBUFFER_EXT,
3596 func_name) &&
3597 CheckFramebufferValid(framebuffer_state_.bound_read_framebuffer.get(),
3598 GL_READ_FRAMEBUFFER_EXT,
3599 func_name);
3602 bool GLES2DecoderImpl::CheckBoundReadFramebufferColorAttachment(
3603 const char* func_name) {
3604 Framebuffer* framebuffer = features().chromium_framebuffer_multisample ?
3605 framebuffer_state_.bound_read_framebuffer.get() :
3606 framebuffer_state_.bound_draw_framebuffer.get();
3607 if (!framebuffer)
3608 return true;
3609 if (framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0) == NULL) {
3610 LOCAL_SET_GL_ERROR(
3611 GL_INVALID_OPERATION, func_name, "no color image attached");
3612 return false;
3614 return true;
3617 bool GLES2DecoderImpl::FormsTextureCopyingFeedbackLoop(
3618 TextureRef* texture, GLint level) {
3619 Framebuffer* framebuffer = features().chromium_framebuffer_multisample ?
3620 framebuffer_state_.bound_read_framebuffer.get() :
3621 framebuffer_state_.bound_draw_framebuffer.get();
3622 if (!framebuffer)
3623 return false;
3624 const Framebuffer::Attachment* attachment = framebuffer->GetAttachment(
3625 GL_COLOR_ATTACHMENT0);
3626 if (!attachment)
3627 return false;
3628 return attachment->FormsFeedbackLoop(texture, level);
3631 gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
3632 Framebuffer* framebuffer =
3633 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3634 if (framebuffer != NULL) {
3635 const Framebuffer::Attachment* attachment =
3636 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
3637 if (attachment) {
3638 return gfx::Size(attachment->width(), attachment->height());
3640 return gfx::Size(0, 0);
3641 } else if (offscreen_target_frame_buffer_.get()) {
3642 return offscreen_size_;
3643 } else {
3644 return surface_->GetSize();
3648 GLenum GLES2DecoderImpl::GetBoundReadFrameBufferTextureType() {
3649 Framebuffer* framebuffer =
3650 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3651 if (framebuffer != NULL) {
3652 return framebuffer->GetColorAttachmentTextureType();
3653 } else {
3654 return GL_UNSIGNED_BYTE;
3658 GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
3659 Framebuffer* framebuffer =
3660 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3661 if (framebuffer != NULL) {
3662 return framebuffer->GetColorAttachmentFormat();
3663 } else if (offscreen_target_frame_buffer_.get()) {
3664 return offscreen_target_color_format_;
3665 } else {
3666 return back_buffer_color_format_;
3670 GLenum GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
3671 Framebuffer* framebuffer =
3672 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3673 if (framebuffer != NULL) {
3674 return framebuffer->GetColorAttachmentFormat();
3675 } else if (offscreen_target_frame_buffer_.get()) {
3676 return offscreen_target_color_format_;
3677 } else {
3678 return back_buffer_color_format_;
3682 void GLES2DecoderImpl::UpdateParentTextureInfo() {
3683 if (!offscreen_saved_color_texture_info_.get())
3684 return;
3685 GLenum target = offscreen_saved_color_texture_info_->texture()->target();
3686 glBindTexture(target, offscreen_saved_color_texture_info_->service_id());
3687 texture_manager()->SetLevelInfo(
3688 offscreen_saved_color_texture_info_.get(),
3689 GL_TEXTURE_2D,
3690 0, // level
3691 GL_RGBA,
3692 offscreen_size_.width(),
3693 offscreen_size_.height(),
3694 1, // depth
3695 0, // border
3696 GL_RGBA,
3697 GL_UNSIGNED_BYTE,
3698 true);
3699 texture_manager()->SetParameteri(
3700 "UpdateParentTextureInfo",
3701 GetErrorState(),
3702 offscreen_saved_color_texture_info_.get(),
3703 GL_TEXTURE_MAG_FILTER,
3704 GL_LINEAR);
3705 texture_manager()->SetParameteri(
3706 "UpdateParentTextureInfo",
3707 GetErrorState(),
3708 offscreen_saved_color_texture_info_.get(),
3709 GL_TEXTURE_MIN_FILTER,
3710 GL_LINEAR);
3711 texture_manager()->SetParameteri(
3712 "UpdateParentTextureInfo",
3713 GetErrorState(),
3714 offscreen_saved_color_texture_info_.get(),
3715 GL_TEXTURE_WRAP_S,
3716 GL_CLAMP_TO_EDGE);
3717 texture_manager()->SetParameteri(
3718 "UpdateParentTextureInfo",
3719 GetErrorState(),
3720 offscreen_saved_color_texture_info_.get(),
3721 GL_TEXTURE_WRAP_T,
3722 GL_CLAMP_TO_EDGE);
3723 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
3724 &state_, target);
3725 glBindTexture(target, texture_ref ? texture_ref->service_id() : 0);
3728 void GLES2DecoderImpl::SetResizeCallback(
3729 const base::Callback<void(gfx::Size, float)>& callback) {
3730 resize_callback_ = callback;
3733 Logger* GLES2DecoderImpl::GetLogger() {
3734 return &logger_;
3737 void GLES2DecoderImpl::BeginDecoding() {
3738 gpu_tracer_->BeginDecoding();
3739 gpu_trace_commands_ = gpu_tracer_->IsTracing() && *gpu_decoder_category_;
3740 gpu_debug_commands_ = log_commands() || debug() || gpu_trace_commands_ ||
3741 (*cb_command_trace_category_ != 0);
3744 void GLES2DecoderImpl::EndDecoding() {
3745 gpu_tracer_->EndDecoding();
3748 ErrorState* GLES2DecoderImpl::GetErrorState() {
3749 return state_.GetErrorState();
3752 void GLES2DecoderImpl::SetShaderCacheCallback(
3753 const ShaderCacheCallback& callback) {
3754 shader_cache_callback_ = callback;
3757 void GLES2DecoderImpl::SetWaitSyncPointCallback(
3758 const WaitSyncPointCallback& callback) {
3759 wait_sync_point_callback_ = callback;
3762 AsyncPixelTransferManager*
3763 GLES2DecoderImpl::GetAsyncPixelTransferManager() {
3764 return async_pixel_transfer_manager_.get();
3767 void GLES2DecoderImpl::ResetAsyncPixelTransferManagerForTest() {
3768 async_pixel_transfer_manager_.reset();
3771 void GLES2DecoderImpl::SetAsyncPixelTransferManagerForTest(
3772 AsyncPixelTransferManager* manager) {
3773 async_pixel_transfer_manager_ = make_scoped_ptr(manager);
3776 bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
3777 uint32* service_texture_id) {
3778 TextureRef* texture_ref = texture_manager()->GetTexture(client_texture_id);
3779 if (texture_ref) {
3780 *service_texture_id = texture_ref->service_id();
3781 return true;
3783 return false;
3786 uint32 GLES2DecoderImpl::GetTextureUploadCount() {
3787 return texture_state_.texture_upload_count +
3788 async_pixel_transfer_manager_->GetTextureUploadCount();
3791 base::TimeDelta GLES2DecoderImpl::GetTotalTextureUploadTime() {
3792 return texture_state_.total_texture_upload_time +
3793 async_pixel_transfer_manager_->GetTotalTextureUploadTime();
3796 base::TimeDelta GLES2DecoderImpl::GetTotalProcessingCommandsTime() {
3797 return total_processing_commands_time_;
3800 void GLES2DecoderImpl::AddProcessingCommandsTime(base::TimeDelta time) {
3801 total_processing_commands_time_ += time;
3804 void GLES2DecoderImpl::Destroy(bool have_context) {
3805 if (!initialized())
3806 return;
3808 DCHECK(!have_context || context_->IsCurrent(NULL));
3810 // Unbind everything.
3811 state_.vertex_attrib_manager = NULL;
3812 state_.default_vertex_attrib_manager = NULL;
3813 state_.texture_units.clear();
3814 state_.bound_array_buffer = NULL;
3815 state_.bound_copy_read_buffer = NULL;
3816 state_.bound_copy_write_buffer = NULL;
3817 state_.bound_pixel_pack_buffer = NULL;
3818 state_.bound_pixel_unpack_buffer = NULL;
3819 state_.bound_transform_feedback_buffer = NULL;
3820 state_.bound_uniform_buffer = NULL;
3821 state_.current_queries.clear();
3822 framebuffer_state_.bound_read_framebuffer = NULL;
3823 framebuffer_state_.bound_draw_framebuffer = NULL;
3824 state_.bound_renderbuffer = NULL;
3825 state_.bound_valuebuffer = NULL;
3827 if (offscreen_saved_color_texture_info_.get()) {
3828 DCHECK(offscreen_target_color_texture_);
3829 DCHECK_EQ(offscreen_saved_color_texture_info_->service_id(),
3830 offscreen_saved_color_texture_->id());
3831 offscreen_saved_color_texture_->Invalidate();
3832 offscreen_saved_color_texture_info_ = NULL;
3834 if (have_context) {
3835 if (copy_texture_CHROMIUM_.get()) {
3836 copy_texture_CHROMIUM_->Destroy();
3837 copy_texture_CHROMIUM_.reset();
3840 clear_framebuffer_blit_.reset();
3842 if (state_.current_program.get()) {
3843 program_manager()->UnuseProgram(shader_manager(),
3844 state_.current_program.get());
3847 if (attrib_0_buffer_id_) {
3848 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
3850 if (fixed_attrib_buffer_id_) {
3851 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_);
3854 if (validation_texture_) {
3855 glDeleteTextures(1, &validation_texture_);
3856 glDeleteFramebuffersEXT(1, &validation_fbo_multisample_);
3857 glDeleteFramebuffersEXT(1, &validation_fbo_);
3860 if (offscreen_target_frame_buffer_.get())
3861 offscreen_target_frame_buffer_->Destroy();
3862 if (offscreen_target_color_texture_.get())
3863 offscreen_target_color_texture_->Destroy();
3864 if (offscreen_target_color_render_buffer_.get())
3865 offscreen_target_color_render_buffer_->Destroy();
3866 if (offscreen_target_depth_render_buffer_.get())
3867 offscreen_target_depth_render_buffer_->Destroy();
3868 if (offscreen_target_stencil_render_buffer_.get())
3869 offscreen_target_stencil_render_buffer_->Destroy();
3870 if (offscreen_saved_frame_buffer_.get())
3871 offscreen_saved_frame_buffer_->Destroy();
3872 if (offscreen_saved_color_texture_.get())
3873 offscreen_saved_color_texture_->Destroy();
3874 if (offscreen_resolved_frame_buffer_.get())
3875 offscreen_resolved_frame_buffer_->Destroy();
3876 if (offscreen_resolved_color_texture_.get())
3877 offscreen_resolved_color_texture_->Destroy();
3878 } else {
3879 if (offscreen_target_frame_buffer_.get())
3880 offscreen_target_frame_buffer_->Invalidate();
3881 if (offscreen_target_color_texture_.get())
3882 offscreen_target_color_texture_->Invalidate();
3883 if (offscreen_target_color_render_buffer_.get())
3884 offscreen_target_color_render_buffer_->Invalidate();
3885 if (offscreen_target_depth_render_buffer_.get())
3886 offscreen_target_depth_render_buffer_->Invalidate();
3887 if (offscreen_target_stencil_render_buffer_.get())
3888 offscreen_target_stencil_render_buffer_->Invalidate();
3889 if (offscreen_saved_frame_buffer_.get())
3890 offscreen_saved_frame_buffer_->Invalidate();
3891 if (offscreen_saved_color_texture_.get())
3892 offscreen_saved_color_texture_->Invalidate();
3893 if (offscreen_resolved_frame_buffer_.get())
3894 offscreen_resolved_frame_buffer_->Invalidate();
3895 if (offscreen_resolved_color_texture_.get())
3896 offscreen_resolved_color_texture_->Invalidate();
3899 // Current program must be cleared after calling ProgramManager::UnuseProgram.
3900 // Otherwise, we can leak objects. http://crbug.com/258772.
3901 // state_.current_program must be reset before group_ is reset because
3902 // the later deletes the ProgramManager object that referred by
3903 // state_.current_program object.
3904 state_.current_program = NULL;
3906 copy_texture_CHROMIUM_.reset();
3907 clear_framebuffer_blit_.reset();
3909 if (query_manager_.get()) {
3910 query_manager_->Destroy(have_context);
3911 query_manager_.reset();
3914 if (vertex_array_manager_ .get()) {
3915 vertex_array_manager_->Destroy(have_context);
3916 vertex_array_manager_.reset();
3919 if (image_manager_.get()) {
3920 image_manager_->Destroy(have_context);
3921 image_manager_.reset();
3924 offscreen_target_frame_buffer_.reset();
3925 offscreen_target_color_texture_.reset();
3926 offscreen_target_color_render_buffer_.reset();
3927 offscreen_target_depth_render_buffer_.reset();
3928 offscreen_target_stencil_render_buffer_.reset();
3929 offscreen_saved_frame_buffer_.reset();
3930 offscreen_saved_color_texture_.reset();
3931 offscreen_resolved_frame_buffer_.reset();
3932 offscreen_resolved_color_texture_.reset();
3934 // Need to release these before releasing |group_| which may own the
3935 // ShaderTranslatorCache.
3936 fragment_translator_ = NULL;
3937 vertex_translator_ = NULL;
3939 // Should destroy the transfer manager before the texture manager held
3940 // by the context group.
3941 async_pixel_transfer_manager_.reset();
3943 // Destroy the GPU Tracer which may own some in process GPU Timings.
3944 if (gpu_tracer_) {
3945 gpu_tracer_->Destroy(have_context);
3946 gpu_tracer_.reset();
3949 if (group_.get()) {
3950 framebuffer_manager()->RemoveObserver(this);
3951 group_->Destroy(this, have_context);
3952 group_ = NULL;
3955 if (context_.get()) {
3956 context_->ReleaseCurrent(NULL);
3957 context_ = NULL;
3960 #if defined(OS_MACOSX)
3961 for (TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.begin();
3962 it != texture_to_io_surface_map_.end(); ++it) {
3963 CFRelease(it->second);
3965 texture_to_io_surface_map_.clear();
3966 #endif
3969 void GLES2DecoderImpl::SetSurface(
3970 const scoped_refptr<gfx::GLSurface>& surface) {
3971 DCHECK(context_->IsCurrent(NULL));
3972 DCHECK(surface_.get());
3973 surface_ = surface;
3974 RestoreCurrentFramebufferBindings();
3977 void GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox& mailbox) {
3978 if (!offscreen_saved_color_texture_.get()) {
3979 LOG(ERROR) << "Called ProduceFrontBuffer on a non-offscreen context";
3980 return;
3982 if (!offscreen_saved_color_texture_info_.get()) {
3983 GLuint service_id = offscreen_saved_color_texture_->id();
3984 offscreen_saved_color_texture_info_ = TextureRef::Create(
3985 texture_manager(), 0, service_id);
3986 texture_manager()->SetTarget(offscreen_saved_color_texture_info_.get(),
3987 GL_TEXTURE_2D);
3988 UpdateParentTextureInfo();
3990 mailbox_manager()->ProduceTexture(
3991 mailbox, offscreen_saved_color_texture_info_->texture());
3994 bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
3995 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
3996 if (!is_offscreen) {
3997 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
3998 << " with an onscreen framebuffer.";
3999 return false;
4002 if (offscreen_size_ == size)
4003 return true;
4005 offscreen_size_ = size;
4006 int w = offscreen_size_.width();
4007 int h = offscreen_size_.height();
4008 if (w < 0 || h < 0 || h >= (INT_MAX / 4) / (w ? w : 1)) {
4009 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4010 << "to allocate storage due to excessive dimensions.";
4011 return false;
4014 // Reallocate the offscreen target buffers.
4015 DCHECK(offscreen_target_color_format_);
4016 if (IsOffscreenBufferMultisampled()) {
4017 if (!offscreen_target_color_render_buffer_->AllocateStorage(
4018 feature_info_.get(),
4019 offscreen_size_,
4020 offscreen_target_color_format_,
4021 offscreen_target_samples_)) {
4022 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4023 << "to allocate storage for offscreen target color buffer.";
4024 return false;
4026 } else {
4027 if (!offscreen_target_color_texture_->AllocateStorage(
4028 offscreen_size_, offscreen_target_color_format_, false)) {
4029 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4030 << "to allocate storage for offscreen target color texture.";
4031 return false;
4034 if (offscreen_target_depth_format_ &&
4035 !offscreen_target_depth_render_buffer_->AllocateStorage(
4036 feature_info_.get(),
4037 offscreen_size_,
4038 offscreen_target_depth_format_,
4039 offscreen_target_samples_)) {
4040 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4041 << "to allocate storage for offscreen target depth buffer.";
4042 return false;
4044 if (offscreen_target_stencil_format_ &&
4045 !offscreen_target_stencil_render_buffer_->AllocateStorage(
4046 feature_info_.get(),
4047 offscreen_size_,
4048 offscreen_target_stencil_format_,
4049 offscreen_target_samples_)) {
4050 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4051 << "to allocate storage for offscreen target stencil buffer.";
4052 return false;
4055 // Attach the offscreen target buffers to the target frame buffer.
4056 if (IsOffscreenBufferMultisampled()) {
4057 offscreen_target_frame_buffer_->AttachRenderBuffer(
4058 GL_COLOR_ATTACHMENT0,
4059 offscreen_target_color_render_buffer_.get());
4060 } else {
4061 offscreen_target_frame_buffer_->AttachRenderTexture(
4062 offscreen_target_color_texture_.get());
4064 if (offscreen_target_depth_format_) {
4065 offscreen_target_frame_buffer_->AttachRenderBuffer(
4066 GL_DEPTH_ATTACHMENT,
4067 offscreen_target_depth_render_buffer_.get());
4069 const bool packed_depth_stencil =
4070 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
4071 if (packed_depth_stencil) {
4072 offscreen_target_frame_buffer_->AttachRenderBuffer(
4073 GL_STENCIL_ATTACHMENT,
4074 offscreen_target_depth_render_buffer_.get());
4075 } else if (offscreen_target_stencil_format_) {
4076 offscreen_target_frame_buffer_->AttachRenderBuffer(
4077 GL_STENCIL_ATTACHMENT,
4078 offscreen_target_stencil_render_buffer_.get());
4081 if (offscreen_target_frame_buffer_->CheckStatus() !=
4082 GL_FRAMEBUFFER_COMPLETE) {
4083 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4084 << "because offscreen FBO was incomplete.";
4085 return false;
4088 // Clear the target frame buffer.
4090 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
4091 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
4092 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1.f);
4093 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4094 glClearStencil(0);
4095 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
4096 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
4097 glClearDepth(0);
4098 state_.SetDeviceDepthMask(GL_TRUE);
4099 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
4100 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
4101 RestoreClearState();
4104 // Destroy the offscreen resolved framebuffers.
4105 if (offscreen_resolved_frame_buffer_.get())
4106 offscreen_resolved_frame_buffer_->Destroy();
4107 if (offscreen_resolved_color_texture_.get())
4108 offscreen_resolved_color_texture_->Destroy();
4109 offscreen_resolved_color_texture_.reset();
4110 offscreen_resolved_frame_buffer_.reset();
4112 return true;
4115 error::Error GLES2DecoderImpl::HandleResizeCHROMIUM(uint32 immediate_data_size,
4116 const void* cmd_data) {
4117 const gles2::cmds::ResizeCHROMIUM& c =
4118 *static_cast<const gles2::cmds::ResizeCHROMIUM*>(cmd_data);
4119 if (!offscreen_target_frame_buffer_.get() && surface_->DeferDraws())
4120 return error::kDeferCommandUntilLater;
4122 GLuint width = static_cast<GLuint>(c.width);
4123 GLuint height = static_cast<GLuint>(c.height);
4124 GLfloat scale_factor = c.scale_factor;
4125 TRACE_EVENT2("gpu", "glResizeChromium", "width", width, "height", height);
4127 width = std::max(1U, width);
4128 height = std::max(1U, height);
4130 #if defined(OS_POSIX) && !defined(OS_MACOSX) && \
4131 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
4132 // Make sure that we are done drawing to the back buffer before resizing.
4133 glFinish();
4134 #endif
4135 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
4136 if (is_offscreen) {
4137 if (!ResizeOffscreenFrameBuffer(gfx::Size(width, height))) {
4138 LOG(ERROR) << "GLES2DecoderImpl: Context lost because "
4139 << "ResizeOffscreenFrameBuffer failed.";
4140 return error::kLostContext;
4144 if (!resize_callback_.is_null()) {
4145 resize_callback_.Run(gfx::Size(width, height), scale_factor);
4146 DCHECK(context_->IsCurrent(surface_.get()));
4147 if (!context_->IsCurrent(surface_.get())) {
4148 LOG(ERROR) << "GLES2DecoderImpl: Context lost because context no longer "
4149 << "current after resize callback.";
4150 return error::kLostContext;
4154 return error::kNoError;
4157 const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
4158 if (command_id > kStartPoint && command_id < kNumCommands) {
4159 return gles2::GetCommandName(static_cast<CommandId>(command_id));
4161 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
4164 // Decode a command, and call the corresponding GL functions.
4165 // NOTE: DoCommand() is slower than calling DoCommands() on larger batches
4166 // of commands at once, and is now only used for tests that need to track
4167 // individual commands.
4168 error::Error GLES2DecoderImpl::DoCommand(unsigned int command,
4169 unsigned int arg_count,
4170 const void* cmd_data) {
4171 return DoCommands(1, cmd_data, arg_count + 1, 0);
4174 // Decode multiple commands, and call the corresponding GL functions.
4175 // NOTE: 'buffer' is a pointer to the command buffer. As such, it could be
4176 // changed by a (malicious) client at any time, so if validation has to happen,
4177 // it should operate on a copy of them.
4178 // NOTE: This is duplicating code from AsyncAPIInterface::DoCommands() in the
4179 // interest of performance in this critical execution loop.
4180 template <bool DebugImpl>
4181 error::Error GLES2DecoderImpl::DoCommandsImpl(unsigned int num_commands,
4182 const void* buffer,
4183 int num_entries,
4184 int* entries_processed) {
4185 commands_to_process_ = num_commands;
4186 error::Error result = error::kNoError;
4187 const CommandBufferEntry* cmd_data =
4188 static_cast<const CommandBufferEntry*>(buffer);
4189 int process_pos = 0;
4190 unsigned int command = 0;
4192 while (process_pos < num_entries && result == error::kNoError &&
4193 commands_to_process_--) {
4194 const unsigned int size = cmd_data->value_header.size;
4195 command = cmd_data->value_header.command;
4197 if (size == 0) {
4198 result = error::kInvalidSize;
4199 break;
4202 if (static_cast<int>(size) + process_pos > num_entries) {
4203 result = error::kOutOfBounds;
4204 break;
4207 if (DebugImpl) {
4208 TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
4209 GetCommandName(command));
4211 if (log_commands()) {
4212 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "]"
4213 << "cmd: " << GetCommandName(command);
4217 const unsigned int arg_count = size - 1;
4218 unsigned int command_index = command - kStartPoint - 1;
4219 if (command_index < arraysize(command_info)) {
4220 const CommandInfo& info = command_info[command_index];
4221 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
4222 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
4223 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
4224 bool doing_gpu_trace = false;
4225 if (DebugImpl && gpu_trace_commands_) {
4226 if (CMD_FLAG_GET_TRACE_LEVEL(info.cmd_flags) <= gpu_trace_level_) {
4227 doing_gpu_trace = true;
4228 gpu_tracer_->Begin(TRACE_DISABLED_BY_DEFAULT("gpu_decoder"),
4229 GetCommandName(command),
4230 kTraceDecoder);
4234 uint32 immediate_data_size = (arg_count - info_arg_count) *
4235 sizeof(CommandBufferEntry); // NOLINT
4237 result = (this->*info.cmd_handler)(immediate_data_size, cmd_data);
4239 if (DebugImpl && doing_gpu_trace)
4240 gpu_tracer_->End(kTraceDecoder);
4242 if (DebugImpl && debug()) {
4243 GLenum error;
4244 while ((error = glGetError()) != GL_NO_ERROR) {
4245 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "] "
4246 << "GL ERROR: " << GLES2Util::GetStringEnum(error)
4247 << " : " << GetCommandName(command);
4248 LOCAL_SET_GL_ERROR(error, "DoCommand", "GL error from driver");
4251 } else {
4252 result = error::kInvalidArguments;
4254 } else {
4255 result = DoCommonCommand(command, arg_count, cmd_data);
4258 if (DebugImpl) {
4259 TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
4260 GetCommandName(command));
4263 if (result == error::kNoError &&
4264 current_decoder_error_ != error::kNoError) {
4265 result = current_decoder_error_;
4266 current_decoder_error_ = error::kNoError;
4269 if (result != error::kDeferCommandUntilLater) {
4270 process_pos += size;
4271 cmd_data += size;
4275 if (entries_processed)
4276 *entries_processed = process_pos;
4278 if (error::IsError(result)) {
4279 LOG(ERROR) << "Error: " << result << " for Command "
4280 << GetCommandName(command);
4283 return result;
4286 error::Error GLES2DecoderImpl::DoCommands(unsigned int num_commands,
4287 const void* buffer,
4288 int num_entries,
4289 int* entries_processed) {
4290 if (gpu_debug_commands_) {
4291 return DoCommandsImpl<true>(
4292 num_commands, buffer, num_entries, entries_processed);
4293 } else {
4294 return DoCommandsImpl<false>(
4295 num_commands, buffer, num_entries, entries_processed);
4299 void GLES2DecoderImpl::RemoveBuffer(GLuint client_id) {
4300 buffer_manager()->RemoveBuffer(client_id);
4303 void GLES2DecoderImpl::DoFinish() {
4304 glFinish();
4305 ProcessPendingReadPixels();
4306 ProcessPendingQueries(true);
4309 void GLES2DecoderImpl::DoFlush() {
4310 glFlush();
4311 ProcessPendingQueries(false);
4314 void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
4315 GLuint texture_index = texture_unit - GL_TEXTURE0;
4316 if (texture_index >= state_.texture_units.size()) {
4317 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4318 "glActiveTexture", texture_unit, "texture_unit");
4319 return;
4321 state_.active_texture_unit = texture_index;
4322 glActiveTexture(texture_unit);
4325 void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
4326 Buffer* buffer = NULL;
4327 GLuint service_id = 0;
4328 if (client_id != 0) {
4329 buffer = GetBuffer(client_id);
4330 if (!buffer) {
4331 if (!group_->bind_generates_resource()) {
4332 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4333 "glBindBuffer",
4334 "id not generated by glGenBuffers");
4335 return;
4338 // It's a new id so make a buffer buffer for it.
4339 glGenBuffersARB(1, &service_id);
4340 CreateBuffer(client_id, service_id);
4341 buffer = GetBuffer(client_id);
4344 LogClientServiceForInfo(buffer, client_id, "glBindBuffer");
4345 if (buffer) {
4346 if (!buffer_manager()->SetTarget(buffer, target)) {
4347 LOCAL_SET_GL_ERROR(
4348 GL_INVALID_OPERATION,
4349 "glBindBuffer", "buffer bound to more than 1 target");
4350 return;
4352 service_id = buffer->service_id();
4354 state_.SetBoundBuffer(target, buffer);
4355 glBindBuffer(target, service_id);
4358 bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha(
4359 bool all_draw_buffers) {
4360 Framebuffer* framebuffer =
4361 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4362 if (!all_draw_buffers || !framebuffer) {
4363 return (GLES2Util::GetChannelsForFormat(
4364 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
4366 return framebuffer->HasAlphaMRT();
4369 bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
4370 Framebuffer* framebuffer =
4371 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4372 if (framebuffer) {
4373 return framebuffer->HasDepthAttachment();
4375 if (offscreen_target_frame_buffer_.get()) {
4376 return offscreen_target_depth_format_ != 0;
4378 return back_buffer_has_depth_;
4381 bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
4382 Framebuffer* framebuffer =
4383 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4384 if (framebuffer) {
4385 return framebuffer->HasStencilAttachment();
4387 if (offscreen_target_frame_buffer_.get()) {
4388 return offscreen_target_stencil_format_ != 0 ||
4389 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
4391 return back_buffer_has_stencil_;
4394 void GLES2DecoderImpl::ApplyDirtyState() {
4395 if (framebuffer_state_.clear_state_dirty) {
4396 bool have_alpha = BoundFramebufferHasColorAttachmentWithAlpha(true);
4397 state_.SetDeviceColorMask(state_.color_mask_red,
4398 state_.color_mask_green,
4399 state_.color_mask_blue,
4400 state_.color_mask_alpha && have_alpha);
4402 bool have_depth = BoundFramebufferHasDepthAttachment();
4403 state_.SetDeviceDepthMask(state_.depth_mask && have_depth);
4405 bool have_stencil = BoundFramebufferHasStencilAttachment();
4406 state_.SetDeviceStencilMaskSeparate(
4407 GL_FRONT, have_stencil ? state_.stencil_front_writemask : 0);
4408 state_.SetDeviceStencilMaskSeparate(
4409 GL_BACK, have_stencil ? state_.stencil_back_writemask : 0);
4411 state_.SetDeviceCapabilityState(
4412 GL_DEPTH_TEST, state_.enable_flags.depth_test && have_depth);
4413 state_.SetDeviceCapabilityState(
4414 GL_STENCIL_TEST, state_.enable_flags.stencil_test && have_stencil);
4415 framebuffer_state_.clear_state_dirty = false;
4419 GLuint GLES2DecoderImpl::GetBackbufferServiceId() const {
4420 return (offscreen_target_frame_buffer_.get())
4421 ? offscreen_target_frame_buffer_->id()
4422 : (surface_.get() ? surface_->GetBackingFrameBufferObject() : 0);
4425 void GLES2DecoderImpl::RestoreState(const ContextState* prev_state) {
4426 TRACE_EVENT1("gpu", "GLES2DecoderImpl::RestoreState",
4427 "context", logger_.GetLogPrefix());
4428 // Restore the Framebuffer first because of bugs in Intel drivers.
4429 // Intel drivers incorrectly clip the viewport settings to
4430 // the size of the current framebuffer object.
4431 RestoreFramebufferBindings();
4432 state_.RestoreState(prev_state);
4435 void GLES2DecoderImpl::RestoreFramebufferBindings() const {
4436 GLuint service_id =
4437 framebuffer_state_.bound_draw_framebuffer.get()
4438 ? framebuffer_state_.bound_draw_framebuffer->service_id()
4439 : GetBackbufferServiceId();
4440 if (!features().chromium_framebuffer_multisample) {
4441 glBindFramebufferEXT(GL_FRAMEBUFFER, service_id);
4442 } else {
4443 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, service_id);
4444 service_id = framebuffer_state_.bound_read_framebuffer.get()
4445 ? framebuffer_state_.bound_read_framebuffer->service_id()
4446 : GetBackbufferServiceId();
4447 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, service_id);
4449 OnFboChanged();
4452 void GLES2DecoderImpl::RestoreRenderbufferBindings() {
4453 state_.RestoreRenderbufferBindings();
4456 void GLES2DecoderImpl::RestoreTextureState(unsigned service_id) const {
4457 Texture* texture = texture_manager()->GetTextureForServiceId(service_id);
4458 if (texture) {
4459 GLenum target = texture->target();
4460 glBindTexture(target, service_id);
4461 glTexParameteri(
4462 target, GL_TEXTURE_WRAP_S, texture->wrap_s());
4463 glTexParameteri(
4464 target, GL_TEXTURE_WRAP_T, texture->wrap_t());
4465 glTexParameteri(
4466 target, GL_TEXTURE_MIN_FILTER, texture->min_filter());
4467 glTexParameteri(
4468 target, GL_TEXTURE_MAG_FILTER, texture->mag_filter());
4469 RestoreTextureUnitBindings(state_.active_texture_unit);
4473 void GLES2DecoderImpl::ClearAllAttributes() const {
4474 // Must use native VAO 0, as RestoreAllAttributes can't fully restore
4475 // other VAOs.
4476 if (feature_info_->feature_flags().native_vertex_array_object)
4477 glBindVertexArrayOES(0);
4479 for (uint32 i = 0; i < group_->max_vertex_attribs(); ++i) {
4480 if (i != 0) // Never disable attribute 0
4481 glDisableVertexAttribArray(i);
4482 if (features().angle_instanced_arrays)
4483 glVertexAttribDivisorANGLE(i, 0);
4487 void GLES2DecoderImpl::RestoreAllAttributes() const {
4488 state_.RestoreVertexAttribs();
4491 void GLES2DecoderImpl::SetIgnoreCachedStateForTest(bool ignore) {
4492 state_.SetIgnoreCachedStateForTest(ignore);
4495 void GLES2DecoderImpl::OnFboChanged() const {
4496 if (workarounds().restore_scissor_on_fbo_change)
4497 state_.fbo_binding_for_scissor_workaround_dirty = true;
4499 if (workarounds().gl_begin_gl_end_on_fbo_change_to_backbuffer) {
4500 GLint bound_fbo_unsigned = -1;
4501 glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &bound_fbo_unsigned);
4502 GLuint bound_fbo = static_cast<GLuint>(bound_fbo_unsigned);
4503 if (surface_ && surface_->GetBackingFrameBufferObject() == bound_fbo)
4504 surface_->NotifyWasBound();
4508 // Called after the FBO is checked for completeness.
4509 void GLES2DecoderImpl::OnUseFramebuffer() const {
4510 if (state_.fbo_binding_for_scissor_workaround_dirty) {
4511 state_.fbo_binding_for_scissor_workaround_dirty = false;
4512 // The driver forgets the correct scissor when modifying the FBO binding.
4513 glScissor(state_.scissor_x,
4514 state_.scissor_y,
4515 state_.scissor_width,
4516 state_.scissor_height);
4518 // crbug.com/222018 - Also on QualComm, the flush here avoids flicker,
4519 // it's unclear how this bug works.
4520 glFlush();
4524 void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
4525 Framebuffer* framebuffer = NULL;
4526 GLuint service_id = 0;
4527 if (client_id != 0) {
4528 framebuffer = GetFramebuffer(client_id);
4529 if (!framebuffer) {
4530 if (!group_->bind_generates_resource()) {
4531 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4532 "glBindFramebuffer",
4533 "id not generated by glGenFramebuffers");
4534 return;
4537 // It's a new id so make a framebuffer framebuffer for it.
4538 glGenFramebuffersEXT(1, &service_id);
4539 CreateFramebuffer(client_id, service_id);
4540 framebuffer = GetFramebuffer(client_id);
4541 } else {
4542 service_id = framebuffer->service_id();
4544 framebuffer->MarkAsValid();
4546 LogClientServiceForInfo(framebuffer, client_id, "glBindFramebuffer");
4548 if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) {
4549 framebuffer_state_.bound_draw_framebuffer = framebuffer;
4552 // vmiura: This looks like dup code
4553 if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) {
4554 framebuffer_state_.bound_read_framebuffer = framebuffer;
4557 framebuffer_state_.clear_state_dirty = true;
4559 // If we are rendering to the backbuffer get the FBO id for any simulated
4560 // backbuffer.
4561 if (framebuffer == NULL) {
4562 service_id = GetBackbufferServiceId();
4565 glBindFramebufferEXT(target, service_id);
4566 OnFboChanged();
4569 void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
4570 Renderbuffer* renderbuffer = NULL;
4571 GLuint service_id = 0;
4572 if (client_id != 0) {
4573 renderbuffer = GetRenderbuffer(client_id);
4574 if (!renderbuffer) {
4575 if (!group_->bind_generates_resource()) {
4576 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4577 "glBindRenderbuffer",
4578 "id not generated by glGenRenderbuffers");
4579 return;
4582 // It's a new id so make a renderbuffer for it.
4583 glGenRenderbuffersEXT(1, &service_id);
4584 CreateRenderbuffer(client_id, service_id);
4585 renderbuffer = GetRenderbuffer(client_id);
4586 } else {
4587 service_id = renderbuffer->service_id();
4589 renderbuffer->MarkAsValid();
4591 LogClientServiceForInfo(renderbuffer, client_id, "glBindRenderbuffer");
4592 state_.bound_renderbuffer = renderbuffer;
4593 state_.bound_renderbuffer_valid = true;
4594 glBindRenderbufferEXT(GL_RENDERBUFFER, service_id);
4597 void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
4598 TextureRef* texture_ref = NULL;
4599 GLuint service_id = 0;
4600 if (client_id != 0) {
4601 texture_ref = GetTexture(client_id);
4602 if (!texture_ref) {
4603 if (!group_->bind_generates_resource()) {
4604 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4605 "glBindTexture",
4606 "id not generated by glGenTextures");
4607 return;
4610 // It's a new id so make a texture texture for it.
4611 glGenTextures(1, &service_id);
4612 DCHECK_NE(0u, service_id);
4613 CreateTexture(client_id, service_id);
4614 texture_ref = GetTexture(client_id);
4616 } else {
4617 texture_ref = texture_manager()->GetDefaultTextureInfo(target);
4620 // Check the texture exists
4621 if (texture_ref) {
4622 Texture* texture = texture_ref->texture();
4623 // Check that we are not trying to bind it to a different target.
4624 if (texture->target() != 0 && texture->target() != target) {
4625 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4626 "glBindTexture",
4627 "texture bound to more than 1 target.");
4628 return;
4630 LogClientServiceForInfo(texture, client_id, "glBindTexture");
4631 if (texture->target() == 0) {
4632 texture_manager()->SetTarget(texture_ref, target);
4634 glBindTexture(target, texture->service_id());
4635 } else {
4636 glBindTexture(target, 0);
4639 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4640 unit.bind_target = target;
4641 switch (target) {
4642 case GL_TEXTURE_2D:
4643 unit.bound_texture_2d = texture_ref;
4644 break;
4645 case GL_TEXTURE_CUBE_MAP:
4646 unit.bound_texture_cube_map = texture_ref;
4647 break;
4648 case GL_TEXTURE_EXTERNAL_OES:
4649 unit.bound_texture_external_oes = texture_ref;
4650 break;
4651 case GL_TEXTURE_RECTANGLE_ARB:
4652 unit.bound_texture_rectangle_arb = texture_ref;
4653 break;
4654 case GL_TEXTURE_3D:
4655 unit.bound_texture_3d = texture_ref;
4656 break;
4657 case GL_TEXTURE_2D_ARRAY:
4658 unit.bound_texture_2d_array = texture_ref;
4659 break;
4660 default:
4661 NOTREACHED(); // Validation should prevent us getting here.
4662 break;
4666 void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
4667 if (state_.vertex_attrib_manager->Enable(index, false)) {
4668 if (index != 0 ||
4669 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
4670 glDisableVertexAttribArray(index);
4672 } else {
4673 LOCAL_SET_GL_ERROR(
4674 GL_INVALID_VALUE,
4675 "glDisableVertexAttribArray", "index out of range");
4679 void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target,
4680 GLsizei numAttachments,
4681 const GLenum* attachments) {
4682 if (workarounds().disable_discard_framebuffer)
4683 return;
4685 Framebuffer* framebuffer =
4686 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4688 // Validates the attachments. If one of them fails
4689 // the whole command fails.
4690 for (GLsizei i = 0; i < numAttachments; ++i) {
4691 if ((framebuffer &&
4692 !validators_->attachment.IsValid(attachments[i])) ||
4693 (!framebuffer &&
4694 !validators_->backbuffer_attachment.IsValid(attachments[i]))) {
4695 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4696 "glDiscardFramebufferEXT", attachments[i], "attachments");
4697 return;
4701 // Marks each one of them as not cleared
4702 for (GLsizei i = 0; i < numAttachments; ++i) {
4703 if (framebuffer) {
4704 framebuffer->MarkAttachmentAsCleared(renderbuffer_manager(),
4705 texture_manager(),
4706 attachments[i],
4707 false);
4708 } else {
4709 switch (attachments[i]) {
4710 case GL_COLOR_EXT:
4711 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
4712 break;
4713 case GL_DEPTH_EXT:
4714 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
4715 case GL_STENCIL_EXT:
4716 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
4717 break;
4718 default:
4719 NOTREACHED();
4720 break;
4725 // If the default framebuffer is bound but we are still rendering to an
4726 // FBO, translate attachment names that refer to default framebuffer
4727 // channels to corresponding framebuffer attachments.
4728 scoped_ptr<GLenum[]> translated_attachments(new GLenum[numAttachments]);
4729 for (GLsizei i = 0; i < numAttachments; ++i) {
4730 GLenum attachment = attachments[i];
4731 if (!framebuffer && GetBackbufferServiceId()) {
4732 switch (attachment) {
4733 case GL_COLOR_EXT:
4734 attachment = GL_COLOR_ATTACHMENT0;
4735 break;
4736 case GL_DEPTH_EXT:
4737 attachment = GL_DEPTH_ATTACHMENT;
4738 break;
4739 case GL_STENCIL_EXT:
4740 attachment = GL_STENCIL_ATTACHMENT;
4741 break;
4742 default:
4743 NOTREACHED();
4744 return;
4747 translated_attachments[i] = attachment;
4750 ScopedRenderTo do_render(framebuffer);
4751 if (feature_info_->gl_version_info().is_es3) {
4752 glInvalidateFramebuffer(
4753 target, numAttachments, translated_attachments.get());
4754 } else {
4755 glDiscardFramebufferEXT(
4756 target, numAttachments, translated_attachments.get());
4760 void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
4761 if (state_.vertex_attrib_manager->Enable(index, true)) {
4762 glEnableVertexAttribArray(index);
4763 } else {
4764 LOCAL_SET_GL_ERROR(
4765 GL_INVALID_VALUE, "glEnableVertexAttribArray", "index out of range");
4769 void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
4770 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
4771 &state_, target);
4772 if (!texture_ref ||
4773 !texture_manager()->CanGenerateMipmaps(texture_ref)) {
4774 LOCAL_SET_GL_ERROR(
4775 GL_INVALID_OPERATION, "glGenerateMipmap", "Can not generate mips");
4776 return;
4779 if (target == GL_TEXTURE_CUBE_MAP) {
4780 for (int i = 0; i < 6; ++i) {
4781 GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;
4782 if (!texture_manager()->ClearTextureLevel(this, texture_ref, face, 0)) {
4783 LOCAL_SET_GL_ERROR(
4784 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
4785 return;
4788 } else {
4789 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, 0)) {
4790 LOCAL_SET_GL_ERROR(
4791 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
4792 return;
4796 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glGenerateMipmap");
4797 // Workaround for Mac driver bug. In the large scheme of things setting
4798 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
4799 // hit so there's probably no need to make this conditional. The bug appears
4800 // to be that if the filtering mode is set to something that doesn't require
4801 // mipmaps for rendering, or is never set to something other than the default,
4802 // then glGenerateMipmap misbehaves.
4803 if (workarounds().set_texture_filter_before_generating_mipmap) {
4804 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
4806 glGenerateMipmapEXT(target);
4807 if (workarounds().set_texture_filter_before_generating_mipmap) {
4808 glTexParameteri(target, GL_TEXTURE_MIN_FILTER,
4809 texture_ref->texture()->min_filter());
4811 GLenum error = LOCAL_PEEK_GL_ERROR("glGenerateMipmap");
4812 if (error == GL_NO_ERROR) {
4813 texture_manager()->MarkMipmapsGenerated(texture_ref);
4817 bool GLES2DecoderImpl::GetHelper(
4818 GLenum pname, GLint* params, GLsizei* num_written) {
4819 DCHECK(num_written);
4820 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
4821 switch (pname) {
4822 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
4823 *num_written = 1;
4824 // Return the GL implementation's preferred format and (see below type)
4825 // if we have the GL extension that exposes this. This allows the GPU
4826 // client to use the implementation's preferred format for glReadPixels
4827 // for optimisation.
4829 // A conflicting extension (GL_ARB_ES2_compatibility) specifies an error
4830 // case when requested on integer/floating point buffers but which is
4831 // acceptable on GLES2 and with the GL_OES_read_format extension.
4833 // Therefore if an error occurs we swallow the error and use the
4834 // internal implementation.
4835 if (params) {
4836 if (context_->HasExtension("GL_OES_read_format")) {
4837 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper",
4838 GetErrorState());
4839 glGetIntegerv(pname, params);
4840 if (glGetError() == GL_NO_ERROR)
4841 return true;
4843 *params = GLES2Util::GetPreferredGLReadPixelsFormat(
4844 GetBoundReadFrameBufferInternalFormat());
4846 return true;
4847 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
4848 *num_written = 1;
4849 if (params) {
4850 if (context_->HasExtension("GL_OES_read_format")) {
4851 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper",
4852 GetErrorState());
4853 glGetIntegerv(pname, params);
4854 if (glGetError() == GL_NO_ERROR)
4855 return true;
4857 *params = GLES2Util::GetPreferredGLReadPixelsType(
4858 GetBoundReadFrameBufferInternalFormat(),
4859 GetBoundReadFrameBufferTextureType());
4861 return true;
4862 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
4863 *num_written = 1;
4864 if (params) {
4865 *params = group_->max_fragment_uniform_vectors();
4867 return true;
4868 case GL_MAX_VARYING_VECTORS:
4869 *num_written = 1;
4870 if (params) {
4871 *params = group_->max_varying_vectors();
4873 return true;
4874 case GL_MAX_VERTEX_UNIFORM_VECTORS:
4875 *num_written = 1;
4876 if (params) {
4877 *params = group_->max_vertex_uniform_vectors();
4879 return true;
4882 if (unsafe_es3_apis_enabled()) {
4883 switch (pname) {
4884 case GL_MAX_VARYING_COMPONENTS: {
4885 if (feature_info_->gl_version_info().is_es) {
4886 // We can just delegate this query to the driver.
4887 return false;
4890 // GL_MAX_VARYING_COMPONENTS is deprecated in the desktop
4891 // OpenGL core profile, so for simplicity, just compute it
4892 // from GL_MAX_VARYING_VECTORS on non-OpenGL ES
4893 // configurations.
4894 GLint max_varying_vectors = 0;
4895 glGetIntegerv(GL_MAX_VARYING_VECTORS, &max_varying_vectors);
4896 *num_written = 1;
4897 if (params) {
4898 *params = max_varying_vectors * 4;
4900 return true;
4904 switch (pname) {
4905 case GL_MAX_VIEWPORT_DIMS:
4906 if (offscreen_target_frame_buffer_.get()) {
4907 *num_written = 2;
4908 if (params) {
4909 params[0] = renderbuffer_manager()->max_renderbuffer_size();
4910 params[1] = renderbuffer_manager()->max_renderbuffer_size();
4912 return true;
4914 return false;
4915 case GL_MAX_SAMPLES:
4916 *num_written = 1;
4917 if (params) {
4918 params[0] = renderbuffer_manager()->max_samples();
4920 return true;
4921 case GL_MAX_RENDERBUFFER_SIZE:
4922 *num_written = 1;
4923 if (params) {
4924 params[0] = renderbuffer_manager()->max_renderbuffer_size();
4926 return true;
4927 case GL_MAX_TEXTURE_SIZE:
4928 *num_written = 1;
4929 if (params) {
4930 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D);
4932 return true;
4933 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
4934 *num_written = 1;
4935 if (params) {
4936 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP);
4938 return true;
4939 case GL_MAX_COLOR_ATTACHMENTS_EXT:
4940 *num_written = 1;
4941 if (params) {
4942 params[0] = group_->max_color_attachments();
4944 return true;
4945 case GL_MAX_DRAW_BUFFERS_ARB:
4946 *num_written = 1;
4947 if (params) {
4948 params[0] = group_->max_draw_buffers();
4950 return true;
4951 case GL_ALPHA_BITS:
4952 *num_written = 1;
4953 if (params) {
4954 GLint v = 0;
4955 if (feature_info_->gl_version_info().is_desktop_core_profile) {
4956 Framebuffer* framebuffer =
4957 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4958 if (framebuffer) {
4959 glGetFramebufferAttachmentParameterivEXT(
4960 GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
4961 GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE, &v);
4962 } else {
4963 v = (back_buffer_color_format_ == GL_RGBA ? 8 : 0);
4965 } else {
4966 glGetIntegerv(GL_ALPHA_BITS, &v);
4968 params[0] =
4969 BoundFramebufferHasColorAttachmentWithAlpha(false) ? v : 0;
4971 return true;
4972 case GL_DEPTH_BITS:
4973 *num_written = 1;
4974 if (params) {
4975 GLint v = 0;
4976 if (feature_info_->gl_version_info().is_desktop_core_profile) {
4977 Framebuffer* framebuffer =
4978 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4979 if (framebuffer) {
4980 glGetFramebufferAttachmentParameterivEXT(
4981 GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
4982 GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE, &v);
4983 } else {
4984 v = (back_buffer_has_depth_ ? 24 : 0);
4986 } else {
4987 glGetIntegerv(GL_DEPTH_BITS, &v);
4989 params[0] = BoundFramebufferHasDepthAttachment() ? v : 0;
4991 return true;
4992 case GL_RED_BITS:
4993 case GL_GREEN_BITS:
4994 case GL_BLUE_BITS:
4995 *num_written = 1;
4996 if (params) {
4997 GLint v = 0;
4998 if (feature_info_->gl_version_info().is_desktop_core_profile) {
4999 Framebuffer* framebuffer =
5000 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
5001 if (framebuffer) {
5002 GLenum framebuffer_enum = 0;
5003 switch (pname) {
5004 case GL_RED_BITS:
5005 framebuffer_enum = GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE;
5006 break;
5007 case GL_GREEN_BITS:
5008 framebuffer_enum = GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE;
5009 break;
5010 case GL_BLUE_BITS:
5011 framebuffer_enum = GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE;
5012 break;
5014 glGetFramebufferAttachmentParameterivEXT(
5015 GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, framebuffer_enum, &v);
5016 } else {
5017 v = 8;
5019 } else {
5020 glGetIntegerv(pname, &v);
5022 params[0] = v;
5024 return true;
5025 case GL_STENCIL_BITS:
5026 *num_written = 1;
5027 if (params) {
5028 GLint v = 0;
5029 if (feature_info_->gl_version_info().is_desktop_core_profile) {
5030 Framebuffer* framebuffer =
5031 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
5032 if (framebuffer) {
5033 glGetFramebufferAttachmentParameterivEXT(
5034 GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
5035 GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE, &v);
5036 } else {
5037 v = (back_buffer_has_stencil_ ? 8 : 0);
5039 } else {
5040 glGetIntegerv(GL_STENCIL_BITS, &v);
5042 params[0] = BoundFramebufferHasStencilAttachment() ? v : 0;
5044 return true;
5045 case GL_COMPRESSED_TEXTURE_FORMATS:
5046 *num_written = validators_->compressed_texture_format.GetValues().size();
5047 if (params) {
5048 for (GLint ii = 0; ii < *num_written; ++ii) {
5049 params[ii] = validators_->compressed_texture_format.GetValues()[ii];
5052 return true;
5053 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
5054 *num_written = 1;
5055 if (params) {
5056 *params = validators_->compressed_texture_format.GetValues().size();
5058 return true;
5059 case GL_NUM_SHADER_BINARY_FORMATS:
5060 *num_written = 1;
5061 if (params) {
5062 *params = validators_->shader_binary_format.GetValues().size();
5064 return true;
5065 case GL_SHADER_BINARY_FORMATS:
5066 *num_written = validators_->shader_binary_format.GetValues().size();
5067 if (params) {
5068 for (GLint ii = 0; ii < *num_written; ++ii) {
5069 params[ii] = validators_->shader_binary_format.GetValues()[ii];
5072 return true;
5073 case GL_SHADER_COMPILER:
5074 *num_written = 1;
5075 if (params) {
5076 *params = GL_TRUE;
5078 return true;
5079 case GL_ARRAY_BUFFER_BINDING:
5080 *num_written = 1;
5081 if (params) {
5082 *params = GetClientId(
5083 buffer_manager(), state_.bound_array_buffer.get());
5085 return true;
5086 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
5087 *num_written = 1;
5088 if (params) {
5089 *params = GetClientId(
5090 buffer_manager(),
5091 state_.vertex_attrib_manager->element_array_buffer());
5093 return true;
5094 case GL_COPY_READ_BUFFER_BINDING:
5095 *num_written = 1;
5096 if (params) {
5097 *params = GetClientId(
5098 buffer_manager(), state_.bound_copy_read_buffer.get());
5100 return true;
5101 case GL_COPY_WRITE_BUFFER_BINDING:
5102 *num_written = 1;
5103 if (params) {
5104 *params = GetClientId(
5105 buffer_manager(), state_.bound_copy_write_buffer.get());
5107 return true;
5108 case GL_PIXEL_PACK_BUFFER_BINDING:
5109 *num_written = 1;
5110 if (params) {
5111 *params = GetClientId(
5112 buffer_manager(), state_.bound_pixel_pack_buffer.get());
5114 return true;
5115 case GL_PIXEL_UNPACK_BUFFER_BINDING:
5116 *num_written = 1;
5117 if (params) {
5118 *params = GetClientId(
5119 buffer_manager(), state_.bound_pixel_unpack_buffer.get());
5121 return true;
5122 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
5123 *num_written = 1;
5124 if (params) {
5125 *params = GetClientId(
5126 buffer_manager(), state_.bound_transform_feedback_buffer.get());
5128 return true;
5129 case GL_UNIFORM_BUFFER_BINDING:
5130 *num_written = 1;
5131 if (params) {
5132 *params = GetClientId(
5133 buffer_manager(), state_.bound_uniform_buffer.get());
5135 return true;
5136 case GL_FRAMEBUFFER_BINDING:
5137 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
5138 *num_written = 1;
5139 if (params) {
5140 *params = GetClientId(
5141 framebuffer_manager(),
5142 GetFramebufferInfoForTarget(GL_FRAMEBUFFER));
5144 return true;
5145 case GL_READ_FRAMEBUFFER_BINDING_EXT:
5146 *num_written = 1;
5147 if (params) {
5148 *params = GetClientId(
5149 framebuffer_manager(),
5150 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT));
5152 return true;
5153 case GL_RENDERBUFFER_BINDING:
5154 *num_written = 1;
5155 if (params) {
5156 Renderbuffer* renderbuffer =
5157 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5158 if (renderbuffer) {
5159 *params = renderbuffer->client_id();
5160 } else {
5161 *params = 0;
5164 return true;
5165 case GL_CURRENT_PROGRAM:
5166 *num_written = 1;
5167 if (params) {
5168 *params = GetClientId(program_manager(), state_.current_program.get());
5170 return true;
5171 case GL_VERTEX_ARRAY_BINDING_OES:
5172 *num_written = 1;
5173 if (params) {
5174 if (state_.vertex_attrib_manager.get() !=
5175 state_.default_vertex_attrib_manager.get()) {
5176 GLuint client_id = 0;
5177 vertex_array_manager_->GetClientId(
5178 state_.vertex_attrib_manager->service_id(), &client_id);
5179 *params = client_id;
5180 } else {
5181 *params = 0;
5184 return true;
5185 case GL_TEXTURE_BINDING_2D:
5186 *num_written = 1;
5187 if (params) {
5188 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
5189 if (unit.bound_texture_2d.get()) {
5190 *params = unit.bound_texture_2d->client_id();
5191 } else {
5192 *params = 0;
5195 return true;
5196 case GL_TEXTURE_BINDING_CUBE_MAP:
5197 *num_written = 1;
5198 if (params) {
5199 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
5200 if (unit.bound_texture_cube_map.get()) {
5201 *params = unit.bound_texture_cube_map->client_id();
5202 } else {
5203 *params = 0;
5206 return true;
5207 case GL_TEXTURE_BINDING_EXTERNAL_OES:
5208 *num_written = 1;
5209 if (params) {
5210 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
5211 if (unit.bound_texture_external_oes.get()) {
5212 *params = unit.bound_texture_external_oes->client_id();
5213 } else {
5214 *params = 0;
5217 return true;
5218 case GL_TEXTURE_BINDING_RECTANGLE_ARB:
5219 *num_written = 1;
5220 if (params) {
5221 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
5222 if (unit.bound_texture_rectangle_arb.get()) {
5223 *params = unit.bound_texture_rectangle_arb->client_id();
5224 } else {
5225 *params = 0;
5228 return true;
5229 case GL_UNPACK_FLIP_Y_CHROMIUM:
5230 *num_written = 1;
5231 if (params) {
5232 params[0] = unpack_flip_y_;
5234 return true;
5235 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
5236 *num_written = 1;
5237 if (params) {
5238 params[0] = unpack_premultiply_alpha_;
5240 return true;
5241 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM:
5242 *num_written = 1;
5243 if (params) {
5244 params[0] = unpack_unpremultiply_alpha_;
5246 return true;
5247 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
5248 *num_written = 1;
5249 if (params) {
5250 params[0] = group_->bind_generates_resource() ? 1 : 0;
5252 return true;
5253 default:
5254 if (pname >= GL_DRAW_BUFFER0_ARB &&
5255 pname < GL_DRAW_BUFFER0_ARB + group_->max_draw_buffers()) {
5256 *num_written = 1;
5257 if (params) {
5258 Framebuffer* framebuffer =
5259 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
5260 if (framebuffer) {
5261 params[0] = framebuffer->GetDrawBuffer(pname);
5262 } else { // backbuffer
5263 if (pname == GL_DRAW_BUFFER0_ARB)
5264 params[0] = group_->draw_buffer();
5265 else
5266 params[0] = GL_NONE;
5269 return true;
5271 *num_written = util_.GLGetNumValuesReturned(pname);
5272 return false;
5276 bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
5277 GLenum pname, GLsizei* num_values) {
5278 if (state_.GetStateAsGLint(pname, NULL, num_values)) {
5279 return true;
5281 return GetHelper(pname, NULL, num_values);
5284 GLenum GLES2DecoderImpl::AdjustGetPname(GLenum pname) {
5285 if (GL_MAX_SAMPLES == pname &&
5286 features().use_img_for_multisampled_render_to_texture) {
5287 return GL_MAX_SAMPLES_IMG;
5289 return pname;
5292 void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
5293 DCHECK(params);
5294 GLsizei num_written = 0;
5295 if (GetNumValuesReturnedForGLGet(pname, &num_written)) {
5296 scoped_ptr<GLint[]> values(new GLint[num_written]);
5297 if (!state_.GetStateAsGLint(pname, values.get(), &num_written)) {
5298 GetHelper(pname, values.get(), &num_written);
5300 for (GLsizei ii = 0; ii < num_written; ++ii) {
5301 params[ii] = static_cast<GLboolean>(values[ii]);
5303 } else {
5304 pname = AdjustGetPname(pname);
5305 glGetBooleanv(pname, params);
5309 void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
5310 DCHECK(params);
5311 GLsizei num_written = 0;
5312 if (!state_.GetStateAsGLfloat(pname, params, &num_written)) {
5313 if (GetHelper(pname, NULL, &num_written)) {
5314 scoped_ptr<GLint[]> values(new GLint[num_written]);
5315 GetHelper(pname, values.get(), &num_written);
5316 for (GLsizei ii = 0; ii < num_written; ++ii) {
5317 params[ii] = static_cast<GLfloat>(values[ii]);
5319 } else {
5320 pname = AdjustGetPname(pname);
5321 glGetFloatv(pname, params);
5326 void GLES2DecoderImpl::DoGetInteger64v(GLenum pname, GLint64* params) {
5327 DCHECK(params);
5328 if (unsafe_es3_apis_enabled()) {
5329 switch (pname) {
5330 case GL_MAX_ELEMENT_INDEX: {
5331 if (feature_info_->gl_version_info().IsAtLeastGLES(3, 0) ||
5332 feature_info_->gl_version_info().IsAtLeastGL(4, 3)) {
5333 glGetInteger64v(GL_MAX_ELEMENT_INDEX, params);
5334 } else {
5335 // Assume that desktop GL implementations can generally support
5336 // 32-bit indices.
5337 if (params) {
5338 *params = std::numeric_limits<unsigned int>::max();
5341 return;
5345 pname = AdjustGetPname(pname);
5346 glGetInteger64v(pname, params);
5349 void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
5350 DCHECK(params);
5351 GLsizei num_written;
5352 if (!state_.GetStateAsGLint(pname, params, &num_written) &&
5353 !GetHelper(pname, params, &num_written)) {
5354 pname = AdjustGetPname(pname);
5355 glGetIntegerv(pname, params);
5359 void GLES2DecoderImpl::DoGetProgramiv(
5360 GLuint program_id, GLenum pname, GLint* params) {
5361 Program* program = GetProgramInfoNotShader(program_id, "glGetProgramiv");
5362 if (!program) {
5363 return;
5365 program->GetProgramiv(pname, params);
5368 void GLES2DecoderImpl::DoGetBufferParameteriv(
5369 GLenum target, GLenum pname, GLint* params) {
5370 // Just delegate it. Some validation is actually done before this.
5371 buffer_manager()->ValidateAndDoGetBufferParameteriv(
5372 &state_, target, pname, params);
5375 void GLES2DecoderImpl::DoBindAttribLocation(
5376 GLuint program_id, GLuint index, const char* name) {
5377 if (!StringIsValidForGLES(name)) {
5378 LOCAL_SET_GL_ERROR(
5379 GL_INVALID_VALUE, "glBindAttribLocation", "Invalid character");
5380 return;
5382 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
5383 LOCAL_SET_GL_ERROR(
5384 GL_INVALID_OPERATION, "glBindAttribLocation", "reserved prefix");
5385 return;
5387 if (index >= group_->max_vertex_attribs()) {
5388 LOCAL_SET_GL_ERROR(
5389 GL_INVALID_VALUE, "glBindAttribLocation", "index out of range");
5390 return;
5392 Program* program = GetProgramInfoNotShader(
5393 program_id, "glBindAttribLocation");
5394 if (!program) {
5395 return;
5397 // At this point, the program's shaders may not be translated yet,
5398 // therefore, we may not find the hashed attribute name.
5399 // glBindAttribLocation call with original name is useless.
5400 // So instead, we should simply cache the binding, and then call
5401 // Program::ExecuteBindAttribLocationCalls() right before link.
5402 program->SetAttribLocationBinding(name, static_cast<GLint>(index));
5403 // TODO(zmo): Get rid of the following glBindAttribLocation call.
5404 glBindAttribLocation(program->service_id(), index, name);
5407 error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
5408 uint32 immediate_data_size,
5409 const void* cmd_data) {
5410 const gles2::cmds::BindAttribLocationBucket& c =
5411 *static_cast<const gles2::cmds::BindAttribLocationBucket*>(cmd_data);
5412 GLuint program = static_cast<GLuint>(c.program);
5413 GLuint index = static_cast<GLuint>(c.index);
5414 Bucket* bucket = GetBucket(c.name_bucket_id);
5415 if (!bucket || bucket->size() == 0) {
5416 return error::kInvalidArguments;
5418 std::string name_str;
5419 if (!bucket->GetAsString(&name_str)) {
5420 return error::kInvalidArguments;
5422 DoBindAttribLocation(program, index, name_str.c_str());
5423 return error::kNoError;
5426 void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM(
5427 GLuint program_id, GLint location, const char* name) {
5428 if (!StringIsValidForGLES(name)) {
5429 LOCAL_SET_GL_ERROR(
5430 GL_INVALID_VALUE,
5431 "glBindUniformLocationCHROMIUM", "Invalid character");
5432 return;
5434 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
5435 LOCAL_SET_GL_ERROR(
5436 GL_INVALID_OPERATION,
5437 "glBindUniformLocationCHROMIUM", "reserved prefix");
5438 return;
5440 if (location < 0 || static_cast<uint32>(location) >=
5441 (group_->max_fragment_uniform_vectors() +
5442 group_->max_vertex_uniform_vectors()) * 4) {
5443 LOCAL_SET_GL_ERROR(
5444 GL_INVALID_VALUE,
5445 "glBindUniformLocationCHROMIUM", "location out of range");
5446 return;
5448 Program* program = GetProgramInfoNotShader(
5449 program_id, "glBindUniformLocationCHROMIUM");
5450 if (!program) {
5451 return;
5453 if (!program->SetUniformLocationBinding(name, location)) {
5454 LOCAL_SET_GL_ERROR(
5455 GL_INVALID_VALUE,
5456 "glBindUniformLocationCHROMIUM", "location out of range");
5460 error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMBucket(
5461 uint32 immediate_data_size,
5462 const void* cmd_data) {
5463 const gles2::cmds::BindUniformLocationCHROMIUMBucket& c =
5464 *static_cast<const gles2::cmds::BindUniformLocationCHROMIUMBucket*>(
5465 cmd_data);
5466 GLuint program = static_cast<GLuint>(c.program);
5467 GLint location = static_cast<GLint>(c.location);
5468 Bucket* bucket = GetBucket(c.name_bucket_id);
5469 if (!bucket || bucket->size() == 0) {
5470 return error::kInvalidArguments;
5472 std::string name_str;
5473 if (!bucket->GetAsString(&name_str)) {
5474 return error::kInvalidArguments;
5476 DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
5477 return error::kNoError;
5480 error::Error GLES2DecoderImpl::HandleDeleteShader(uint32 immediate_data_size,
5481 const void* cmd_data) {
5482 const gles2::cmds::DeleteShader& c =
5483 *static_cast<const gles2::cmds::DeleteShader*>(cmd_data);
5484 GLuint client_id = c.shader;
5485 if (client_id) {
5486 Shader* shader = GetShader(client_id);
5487 if (shader) {
5488 if (!shader->IsDeleted()) {
5489 shader_manager()->Delete(shader);
5491 } else {
5492 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glDeleteShader", "unknown shader");
5495 return error::kNoError;
5498 error::Error GLES2DecoderImpl::HandleDeleteProgram(uint32 immediate_data_size,
5499 const void* cmd_data) {
5500 const gles2::cmds::DeleteProgram& c =
5501 *static_cast<const gles2::cmds::DeleteProgram*>(cmd_data);
5502 GLuint client_id = c.program;
5503 if (client_id) {
5504 Program* program = GetProgram(client_id);
5505 if (program) {
5506 if (!program->IsDeleted()) {
5507 program_manager()->MarkAsDeleted(shader_manager(), program);
5509 } else {
5510 LOCAL_SET_GL_ERROR(
5511 GL_INVALID_VALUE, "glDeleteProgram", "unknown program");
5514 return error::kNoError;
5517 error::Error GLES2DecoderImpl::DoClear(GLbitfield mask) {
5518 DCHECK(!ShouldDeferDraws());
5519 if (CheckBoundFramebuffersValid("glClear")) {
5520 ApplyDirtyState();
5521 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
5522 if (workarounds().gl_clear_broken) {
5523 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::ClearWorkaround",
5524 GetErrorState());
5525 if (!BoundFramebufferHasDepthAttachment())
5526 mask &= ~GL_DEPTH_BUFFER_BIT;
5527 if (!BoundFramebufferHasStencilAttachment())
5528 mask &= ~GL_STENCIL_BUFFER_BIT;
5529 clear_framebuffer_blit_->ClearFramebuffer(
5530 this, GetBoundReadFrameBufferSize(), mask, state_.color_clear_red,
5531 state_.color_clear_green, state_.color_clear_blue,
5532 state_.color_clear_alpha, state_.depth_clear, state_.stencil_clear);
5533 return error::kNoError;
5535 glClear(mask);
5537 return error::kNoError;
5540 void GLES2DecoderImpl::DoFramebufferRenderbuffer(
5541 GLenum target, GLenum attachment, GLenum renderbuffertarget,
5542 GLuint client_renderbuffer_id) {
5543 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5544 if (!framebuffer) {
5545 LOCAL_SET_GL_ERROR(
5546 GL_INVALID_OPERATION,
5547 "glFramebufferRenderbuffer", "no framebuffer bound");
5548 return;
5550 GLuint service_id = 0;
5551 Renderbuffer* renderbuffer = NULL;
5552 if (client_renderbuffer_id) {
5553 renderbuffer = GetRenderbuffer(client_renderbuffer_id);
5554 if (!renderbuffer) {
5555 LOCAL_SET_GL_ERROR(
5556 GL_INVALID_OPERATION,
5557 "glFramebufferRenderbuffer", "unknown renderbuffer");
5558 return;
5560 service_id = renderbuffer->service_id();
5562 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glFramebufferRenderbuffer");
5563 glFramebufferRenderbufferEXT(
5564 target, attachment, renderbuffertarget, service_id);
5565 GLenum error = LOCAL_PEEK_GL_ERROR("glFramebufferRenderbuffer");
5566 if (error == GL_NO_ERROR) {
5567 framebuffer->AttachRenderbuffer(attachment, renderbuffer);
5569 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
5570 framebuffer_state_.clear_state_dirty = true;
5572 OnFboChanged();
5575 void GLES2DecoderImpl::DoDisable(GLenum cap) {
5576 if (SetCapabilityState(cap, false)) {
5577 glDisable(cap);
5581 void GLES2DecoderImpl::DoEnable(GLenum cap) {
5582 if (SetCapabilityState(cap, true)) {
5583 glEnable(cap);
5587 void GLES2DecoderImpl::DoDepthRangef(GLclampf znear, GLclampf zfar) {
5588 state_.z_near = std::min(1.0f, std::max(0.0f, znear));
5589 state_.z_far = std::min(1.0f, std::max(0.0f, zfar));
5590 glDepthRange(znear, zfar);
5593 void GLES2DecoderImpl::DoSampleCoverage(GLclampf value, GLboolean invert) {
5594 state_.sample_coverage_value = std::min(1.0f, std::max(0.0f, value));
5595 state_.sample_coverage_invert = (invert != 0);
5596 glSampleCoverage(state_.sample_coverage_value, invert);
5599 // Assumes framebuffer is complete.
5600 void GLES2DecoderImpl::ClearUnclearedAttachments(
5601 GLenum target, Framebuffer* framebuffer) {
5602 if (target == GL_READ_FRAMEBUFFER_EXT) {
5603 // bind this to the DRAW point, clear then bind back to READ
5604 // TODO(gman): I don't think there is any guarantee that an FBO that
5605 // is complete on the READ attachment will be complete as a DRAW
5606 // attachment.
5607 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
5608 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, framebuffer->service_id());
5610 GLbitfield clear_bits = 0;
5611 if (framebuffer->HasUnclearedColorAttachments()) {
5612 glClearColor(
5613 0.0f, 0.0f, 0.0f,
5614 (GLES2Util::GetChannelsForFormat(
5615 framebuffer->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0.0f :
5616 1.0f);
5617 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
5618 clear_bits |= GL_COLOR_BUFFER_BIT;
5619 if (feature_info_->feature_flags().ext_draw_buffers)
5620 framebuffer->PrepareDrawBuffersForClear();
5623 if (framebuffer->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) ||
5624 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
5625 glClearStencil(0);
5626 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
5627 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
5628 clear_bits |= GL_STENCIL_BUFFER_BIT;
5631 if (framebuffer->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
5632 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
5633 glClearDepth(1.0f);
5634 state_.SetDeviceDepthMask(GL_TRUE);
5635 clear_bits |= GL_DEPTH_BUFFER_BIT;
5638 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
5639 glClear(clear_bits);
5641 if ((clear_bits & GL_COLOR_BUFFER_BIT) != 0 &&
5642 feature_info_->feature_flags().ext_draw_buffers)
5643 framebuffer->RestoreDrawBuffersAfterClear();
5645 framebuffer_manager()->MarkAttachmentsAsCleared(
5646 framebuffer, renderbuffer_manager(), texture_manager());
5648 RestoreClearState();
5650 if (target == GL_READ_FRAMEBUFFER_EXT) {
5651 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, framebuffer->service_id());
5652 Framebuffer* draw_framebuffer =
5653 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
5654 GLuint service_id = draw_framebuffer ? draw_framebuffer->service_id() :
5655 GetBackbufferServiceId();
5656 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, service_id);
5660 void GLES2DecoderImpl::RestoreClearState() {
5661 framebuffer_state_.clear_state_dirty = true;
5662 glClearColor(
5663 state_.color_clear_red, state_.color_clear_green, state_.color_clear_blue,
5664 state_.color_clear_alpha);
5665 glClearStencil(state_.stencil_clear);
5666 glClearDepth(state_.depth_clear);
5667 if (state_.enable_flags.scissor_test) {
5668 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
5672 GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
5673 Framebuffer* framebuffer =
5674 GetFramebufferInfoForTarget(target);
5675 if (!framebuffer) {
5676 return GL_FRAMEBUFFER_COMPLETE;
5678 GLenum completeness = framebuffer->IsPossiblyComplete();
5679 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
5680 return completeness;
5682 return framebuffer->GetStatus(texture_manager(), target);
5685 void GLES2DecoderImpl::DoFramebufferTexture2D(
5686 GLenum target, GLenum attachment, GLenum textarget,
5687 GLuint client_texture_id, GLint level) {
5688 DoFramebufferTexture2DCommon(
5689 "glFramebufferTexture2D", target, attachment,
5690 textarget, client_texture_id, level, 0);
5693 void GLES2DecoderImpl::DoFramebufferTexture2DMultisample(
5694 GLenum target, GLenum attachment, GLenum textarget,
5695 GLuint client_texture_id, GLint level, GLsizei samples) {
5696 DoFramebufferTexture2DCommon(
5697 "glFramebufferTexture2DMultisample", target, attachment,
5698 textarget, client_texture_id, level, samples);
5701 void GLES2DecoderImpl::DoFramebufferTexture2DCommon(
5702 const char* name, GLenum target, GLenum attachment, GLenum textarget,
5703 GLuint client_texture_id, GLint level, GLsizei samples) {
5704 if (samples > renderbuffer_manager()->max_samples()) {
5705 LOCAL_SET_GL_ERROR(
5706 GL_INVALID_VALUE,
5707 "glFramebufferTexture2DMultisample", "samples too large");
5708 return;
5710 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5711 if (!framebuffer) {
5712 LOCAL_SET_GL_ERROR(
5713 GL_INVALID_OPERATION,
5714 name, "no framebuffer bound.");
5715 return;
5717 GLuint service_id = 0;
5718 TextureRef* texture_ref = NULL;
5719 if (client_texture_id) {
5720 texture_ref = GetTexture(client_texture_id);
5721 if (!texture_ref) {
5722 LOCAL_SET_GL_ERROR(
5723 GL_INVALID_OPERATION,
5724 name, "unknown texture_ref");
5725 return;
5727 service_id = texture_ref->service_id();
5730 if (!texture_manager()->ValidForTarget(textarget, level, 0, 0, 1)) {
5731 LOCAL_SET_GL_ERROR(
5732 GL_INVALID_VALUE,
5733 name, "level out of range");
5734 return;
5737 if (texture_ref)
5738 DoWillUseTexImageIfNeeded(texture_ref->texture(), textarget);
5740 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(name);
5741 if (0 == samples) {
5742 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
5743 } else {
5744 if (features().use_img_for_multisampled_render_to_texture) {
5745 glFramebufferTexture2DMultisampleIMG(target, attachment, textarget,
5746 service_id, level, samples);
5747 } else {
5748 glFramebufferTexture2DMultisampleEXT(target, attachment, textarget,
5749 service_id, level, samples);
5752 GLenum error = LOCAL_PEEK_GL_ERROR(name);
5753 if (error == GL_NO_ERROR) {
5754 framebuffer->AttachTexture(attachment, texture_ref, textarget, level,
5755 samples);
5757 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
5758 framebuffer_state_.clear_state_dirty = true;
5761 if (texture_ref)
5762 DoDidUseTexImageIfNeeded(texture_ref->texture(), textarget);
5764 OnFboChanged();
5767 void GLES2DecoderImpl::DoFramebufferTextureLayer(
5768 GLenum target, GLenum attachment, GLuint client_texture_id,
5769 GLint level, GLint layer) {
5770 // TODO(zmo): Unsafe ES3 API, missing states update.
5771 GLuint service_id = 0;
5772 TextureRef* texture_ref = NULL;
5773 if (client_texture_id) {
5774 texture_ref = GetTexture(client_texture_id);
5775 if (!texture_ref) {
5776 LOCAL_SET_GL_ERROR(
5777 GL_INVALID_OPERATION,
5778 "glFramebufferTextureLayer", "unknown texture_ref");
5779 return;
5781 service_id = texture_ref->service_id();
5783 glFramebufferTextureLayer(target, attachment, service_id, level, layer);
5786 void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
5787 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
5788 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5789 if (!framebuffer) {
5790 LOCAL_SET_GL_ERROR(
5791 GL_INVALID_OPERATION,
5792 "glGetFramebufferAttachmentParameteriv", "no framebuffer bound");
5793 return;
5795 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
5796 const Framebuffer::Attachment* attachment_object =
5797 framebuffer->GetAttachment(attachment);
5798 *params = attachment_object ? attachment_object->object_name() : 0;
5799 } else {
5800 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT &&
5801 features().use_img_for_multisampled_render_to_texture) {
5802 pname = GL_TEXTURE_SAMPLES_IMG;
5804 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
5808 void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
5809 GLenum target, GLenum pname, GLint* params) {
5810 Renderbuffer* renderbuffer =
5811 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5812 if (!renderbuffer) {
5813 LOCAL_SET_GL_ERROR(
5814 GL_INVALID_OPERATION,
5815 "glGetRenderbufferParameteriv", "no renderbuffer bound");
5816 return;
5819 EnsureRenderbufferBound();
5820 switch (pname) {
5821 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5822 *params = renderbuffer->internal_format();
5823 break;
5824 case GL_RENDERBUFFER_WIDTH:
5825 *params = renderbuffer->width();
5826 break;
5827 case GL_RENDERBUFFER_HEIGHT:
5828 *params = renderbuffer->height();
5829 break;
5830 case GL_RENDERBUFFER_SAMPLES_EXT:
5831 if (features().use_img_for_multisampled_render_to_texture) {
5832 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_IMG,
5833 params);
5834 } else {
5835 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_EXT,
5836 params);
5838 default:
5839 glGetRenderbufferParameterivEXT(target, pname, params);
5840 break;
5844 void GLES2DecoderImpl::DoBlitFramebufferCHROMIUM(
5845 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
5846 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
5847 GLbitfield mask, GLenum filter) {
5848 DCHECK(!ShouldDeferReads() && !ShouldDeferDraws());
5850 if (!CheckBoundFramebuffersValid("glBlitFramebufferCHROMIUM")) {
5851 return;
5854 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
5855 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
5856 BlitFramebufferHelper(
5857 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5858 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST,
5859 state_.enable_flags.scissor_test);
5862 void GLES2DecoderImpl::EnsureRenderbufferBound() {
5863 if (!state_.bound_renderbuffer_valid) {
5864 state_.bound_renderbuffer_valid = true;
5865 glBindRenderbufferEXT(GL_RENDERBUFFER,
5866 state_.bound_renderbuffer.get()
5867 ? state_.bound_renderbuffer->service_id()
5868 : 0);
5872 void GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(
5873 const FeatureInfo* feature_info,
5874 GLenum target,
5875 GLsizei samples,
5876 GLenum internal_format,
5877 GLsizei width,
5878 GLsizei height) {
5879 // TODO(sievers): This could be resolved at the GL binding level, but the
5880 // binding process is currently a bit too 'brute force'.
5881 if (feature_info->gl_version_info().is_angle) {
5882 glRenderbufferStorageMultisampleANGLE(
5883 target, samples, internal_format, width, height);
5884 } else if (feature_info->feature_flags().use_core_framebuffer_multisample) {
5885 glRenderbufferStorageMultisample(
5886 target, samples, internal_format, width, height);
5887 } else {
5888 glRenderbufferStorageMultisampleEXT(
5889 target, samples, internal_format, width, height);
5893 void GLES2DecoderImpl::BlitFramebufferHelper(GLint srcX0,
5894 GLint srcY0,
5895 GLint srcX1,
5896 GLint srcY1,
5897 GLint dstX0,
5898 GLint dstY0,
5899 GLint dstX1,
5900 GLint dstY1,
5901 GLbitfield mask,
5902 GLenum filter) {
5903 // TODO(sievers): This could be resolved at the GL binding level, but the
5904 // binding process is currently a bit too 'brute force'.
5905 if (feature_info_->gl_version_info().is_angle) {
5906 glBlitFramebufferANGLE(
5907 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5908 } else if (feature_info_->feature_flags().use_core_framebuffer_multisample) {
5909 glBlitFramebuffer(
5910 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5911 } else {
5912 glBlitFramebufferEXT(
5913 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5917 bool GLES2DecoderImpl::ValidateRenderbufferStorageMultisample(
5918 GLsizei samples,
5919 GLenum internalformat,
5920 GLsizei width,
5921 GLsizei height) {
5922 if (samples > renderbuffer_manager()->max_samples()) {
5923 LOCAL_SET_GL_ERROR(
5924 GL_INVALID_VALUE,
5925 "glRenderbufferStorageMultisample", "samples too large");
5926 return false;
5929 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
5930 height > renderbuffer_manager()->max_renderbuffer_size()) {
5931 LOCAL_SET_GL_ERROR(
5932 GL_INVALID_VALUE,
5933 "glRenderbufferStorageMultisample", "dimensions too large");
5934 return false;
5937 uint32 estimated_size = 0;
5938 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
5939 width, height, samples, internalformat, &estimated_size)) {
5940 LOCAL_SET_GL_ERROR(
5941 GL_OUT_OF_MEMORY,
5942 "glRenderbufferStorageMultisample", "dimensions too large");
5943 return false;
5946 if (!EnsureGPUMemoryAvailable(estimated_size)) {
5947 LOCAL_SET_GL_ERROR(
5948 GL_OUT_OF_MEMORY,
5949 "glRenderbufferStorageMultisample", "out of memory");
5950 return false;
5953 return true;
5956 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleCHROMIUM(
5957 GLenum target, GLsizei samples, GLenum internalformat,
5958 GLsizei width, GLsizei height) {
5959 Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5960 if (!renderbuffer) {
5961 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
5962 "glRenderbufferStorageMultisampleCHROMIUM",
5963 "no renderbuffer bound");
5964 return;
5967 if (!ValidateRenderbufferStorageMultisample(
5968 samples, internalformat, width, height)) {
5969 return;
5972 EnsureRenderbufferBound();
5973 GLenum impl_format =
5974 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5975 internalformat);
5976 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(
5977 "glRenderbufferStorageMultisampleCHROMIUM");
5978 RenderbufferStorageMultisampleHelper(
5979 feature_info_.get(), target, samples, impl_format, width, height);
5980 GLenum error =
5981 LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleCHROMIUM");
5982 if (error == GL_NO_ERROR) {
5983 if (workarounds().validate_multisample_buffer_allocation) {
5984 if (!VerifyMultisampleRenderbufferIntegrity(
5985 renderbuffer->service_id(), impl_format)) {
5986 LOCAL_SET_GL_ERROR(
5987 GL_OUT_OF_MEMORY,
5988 "glRenderbufferStorageMultisampleCHROMIUM", "out of memory");
5989 return;
5993 // TODO(gman): If renderbuffers tracked which framebuffers they were
5994 // attached to we could just mark those framebuffers as not complete.
5995 framebuffer_manager()->IncFramebufferStateChangeCount();
5996 renderbuffer_manager()->SetInfo(
5997 renderbuffer, samples, internalformat, width, height);
6001 // This is the handler for multisampled_render_to_texture extensions.
6002 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleEXT(
6003 GLenum target, GLsizei samples, GLenum internalformat,
6004 GLsizei width, GLsizei height) {
6005 Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
6006 if (!renderbuffer) {
6007 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
6008 "glRenderbufferStorageMultisampleEXT",
6009 "no renderbuffer bound");
6010 return;
6013 if (!ValidateRenderbufferStorageMultisample(
6014 samples, internalformat, width, height)) {
6015 return;
6018 EnsureRenderbufferBound();
6019 GLenum impl_format =
6020 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
6021 internalformat);
6022 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorageMultisampleEXT");
6023 if (features().use_img_for_multisampled_render_to_texture) {
6024 glRenderbufferStorageMultisampleIMG(
6025 target, samples, impl_format, width, height);
6026 } else {
6027 glRenderbufferStorageMultisampleEXT(
6028 target, samples, impl_format, width, height);
6030 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleEXT");
6031 if (error == GL_NO_ERROR) {
6032 // TODO(gman): If renderbuffers tracked which framebuffers they were
6033 // attached to we could just mark those framebuffers as not complete.
6034 framebuffer_manager()->IncFramebufferStateChangeCount();
6035 renderbuffer_manager()->SetInfo(
6036 renderbuffer, samples, internalformat, width, height);
6040 // This function validates the allocation of a multisampled renderbuffer
6041 // by clearing it to a key color, blitting the contents to a texture, and
6042 // reading back the color to ensure it matches the key.
6043 bool GLES2DecoderImpl::VerifyMultisampleRenderbufferIntegrity(
6044 GLuint renderbuffer, GLenum format) {
6046 // Only validate color buffers.
6047 // These formats have been selected because they are very common or are known
6048 // to be used by the WebGL backbuffer. If problems are observed with other
6049 // color formats they can be added here.
6050 switch (format) {
6051 case GL_RGB:
6052 case GL_RGB8:
6053 case GL_RGBA:
6054 case GL_RGBA8:
6055 break;
6056 default:
6057 return true;
6060 GLint draw_framebuffer, read_framebuffer;
6062 // Cache framebuffer and texture bindings.
6063 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &draw_framebuffer);
6064 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &read_framebuffer);
6066 if (!validation_texture_) {
6067 GLint bound_texture;
6068 glGetIntegerv(GL_TEXTURE_BINDING_2D, &bound_texture);
6070 // Create additional resources needed for the verification.
6071 glGenTextures(1, &validation_texture_);
6072 glGenFramebuffersEXT(1, &validation_fbo_multisample_);
6073 glGenFramebuffersEXT(1, &validation_fbo_);
6075 // Texture only needs to be 1x1.
6076 glBindTexture(GL_TEXTURE_2D, validation_texture_);
6077 // TODO(erikchen): When Chrome on Mac is linked against an OSX 10.9+ SDK, a
6078 // multisample will fail if the color format of the source and destination
6079 // do not match. Here, we assume that the source is GL_RGBA, and make the
6080 // destination GL_RGBA. http://crbug.com/484203
6081 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA,
6082 GL_UNSIGNED_BYTE, NULL);
6084 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
6085 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
6086 GL_TEXTURE_2D, validation_texture_, 0);
6088 glBindTexture(GL_TEXTURE_2D, bound_texture);
6091 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
6092 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
6093 GL_RENDERBUFFER, renderbuffer);
6095 // Cache current state and reset it to the values we require.
6096 GLboolean scissor_enabled = false;
6097 glGetBooleanv(GL_SCISSOR_TEST, &scissor_enabled);
6098 if (scissor_enabled)
6099 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
6101 GLboolean color_mask[4] = {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE};
6102 glGetBooleanv(GL_COLOR_WRITEMASK, color_mask);
6103 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
6105 GLfloat clear_color[4] = {0.0f, 0.0f, 0.0f, 0.0f};
6106 glGetFloatv(GL_COLOR_CLEAR_VALUE, clear_color);
6107 glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
6109 // Clear the buffer to the desired key color.
6110 glClear(GL_COLOR_BUFFER_BIT);
6112 // Blit from the multisample buffer to a standard texture.
6113 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, validation_fbo_multisample_);
6114 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, validation_fbo_);
6116 BlitFramebufferHelper(
6117 0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
6119 // Read a pixel from the buffer.
6120 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
6122 unsigned char pixel[3] = {0, 0, 0};
6123 glReadPixels(0, 0, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &pixel);
6125 // Detach the renderbuffer.
6126 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
6127 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
6128 GL_RENDERBUFFER, 0);
6130 // Restore cached state.
6131 if (scissor_enabled)
6132 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
6134 state_.SetDeviceColorMask(
6135 color_mask[0], color_mask[1], color_mask[2], color_mask[3]);
6136 glClearColor(clear_color[0], clear_color[1], clear_color[2], clear_color[3]);
6137 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, draw_framebuffer);
6138 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, read_framebuffer);
6140 // Return true if the pixel matched the desired key color.
6141 return (pixel[0] == 0xFF &&
6142 pixel[1] == 0x00 &&
6143 pixel[2] == 0xFF);
6146 void GLES2DecoderImpl::DoRenderbufferStorage(
6147 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
6148 Renderbuffer* renderbuffer =
6149 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
6150 if (!renderbuffer) {
6151 LOCAL_SET_GL_ERROR(
6152 GL_INVALID_OPERATION,
6153 "glRenderbufferStorage", "no renderbuffer bound");
6154 return;
6157 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
6158 height > renderbuffer_manager()->max_renderbuffer_size()) {
6159 LOCAL_SET_GL_ERROR(
6160 GL_INVALID_VALUE, "glRenderbufferStorage", "dimensions too large");
6161 return;
6164 uint32 estimated_size = 0;
6165 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
6166 width, height, 1, internalformat, &estimated_size)) {
6167 LOCAL_SET_GL_ERROR(
6168 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "dimensions too large");
6169 return;
6172 if (!EnsureGPUMemoryAvailable(estimated_size)) {
6173 LOCAL_SET_GL_ERROR(
6174 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "out of memory");
6175 return;
6178 EnsureRenderbufferBound();
6179 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorage");
6180 glRenderbufferStorageEXT(
6181 target,
6182 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
6183 internalformat),
6184 width,
6185 height);
6186 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorage");
6187 if (error == GL_NO_ERROR) {
6188 // TODO(gman): If tetxures tracked which framebuffers they were attached to
6189 // we could just mark those framebuffers as not complete.
6190 framebuffer_manager()->IncFramebufferStateChangeCount();
6191 renderbuffer_manager()->SetInfo(
6192 renderbuffer, 1, internalformat, width, height);
6196 void GLES2DecoderImpl::DoLinkProgram(GLuint program_id) {
6197 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
6198 Program* program = GetProgramInfoNotShader(
6199 program_id, "glLinkProgram");
6200 if (!program) {
6201 return;
6204 LogClientServiceForInfo(program, program_id, "glLinkProgram");
6205 if (program->Link(shader_manager(),
6206 workarounds().count_all_in_varyings_packing ?
6207 Program::kCountAll : Program::kCountOnlyStaticallyUsed,
6208 shader_cache_callback_)) {
6209 if (program == state_.current_program.get()) {
6210 if (workarounds().use_current_program_after_successful_link)
6211 glUseProgram(program->service_id());
6212 if (workarounds().clear_uniforms_before_first_program_use)
6213 program_manager()->ClearUniforms(program);
6217 // LinkProgram can be very slow. Exit command processing to allow for
6218 // context preemption and GPU watchdog checks.
6219 ExitCommandProcessingEarly();
6222 void GLES2DecoderImpl::DoSamplerParameterfv(
6223 GLuint sampler, GLenum pname, const GLfloat* params) {
6224 DCHECK(params);
6225 glSamplerParameterf(sampler, pname, params[0]);
6228 void GLES2DecoderImpl::DoSamplerParameteriv(
6229 GLuint sampler, GLenum pname, const GLint* params) {
6230 DCHECK(params);
6231 glSamplerParameteri(sampler, pname, params[0]);
6234 void GLES2DecoderImpl::DoTexParameterf(
6235 GLenum target, GLenum pname, GLfloat param) {
6236 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
6237 &state_, target);
6238 if (!texture) {
6239 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterf", "unknown texture");
6240 return;
6243 texture_manager()->SetParameterf(
6244 "glTexParameterf", GetErrorState(), texture, pname, param);
6247 void GLES2DecoderImpl::DoTexParameteri(
6248 GLenum target, GLenum pname, GLint param) {
6249 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
6250 &state_, target);
6251 if (!texture) {
6252 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameteri", "unknown texture");
6253 return;
6256 texture_manager()->SetParameteri(
6257 "glTexParameteri", GetErrorState(), texture, pname, param);
6260 void GLES2DecoderImpl::DoTexParameterfv(
6261 GLenum target, GLenum pname, const GLfloat* params) {
6262 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
6263 &state_, target);
6264 if (!texture) {
6265 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterfv", "unknown texture");
6266 return;
6269 texture_manager()->SetParameterf(
6270 "glTexParameterfv", GetErrorState(), texture, pname, *params);
6273 void GLES2DecoderImpl::DoTexParameteriv(
6274 GLenum target, GLenum pname, const GLint* params) {
6275 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
6276 &state_, target);
6277 if (!texture) {
6278 LOCAL_SET_GL_ERROR(
6279 GL_INVALID_VALUE, "glTexParameteriv", "unknown texture");
6280 return;
6283 texture_manager()->SetParameteri(
6284 "glTexParameteriv", GetErrorState(), texture, pname, *params);
6287 bool GLES2DecoderImpl::CheckCurrentValuebuffer(const char* function_name) {
6288 if (!state_.bound_valuebuffer.get()) {
6289 // There is no valuebuffer bound
6290 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
6291 "no valuebuffer in use");
6292 return false;
6294 return true;
6297 bool GLES2DecoderImpl::CheckCurrentValuebufferForSubscription(
6298 GLenum subscription,
6299 const char* function_name) {
6300 if (!CheckCurrentValuebuffer(function_name)) {
6301 return false;
6303 if (!state_.bound_valuebuffer.get()->IsSubscribed(subscription)) {
6304 // The valuebuffer is not subscribed to the target
6305 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
6306 "valuebuffer is not subscribed");
6307 return false;
6309 return true;
6312 bool GLES2DecoderImpl::CheckSubscriptionTarget(GLint location,
6313 GLenum subscription,
6314 const char* function_name) {
6315 if (!CheckCurrentProgramForUniform(location, function_name)) {
6316 return false;
6318 GLint real_location = -1;
6319 GLint array_index = -1;
6320 const Program::UniformInfo* info =
6321 state_.current_program->GetUniformInfoByFakeLocation(
6322 location, &real_location, &array_index);
6323 if (!info) {
6324 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, "unknown location");
6325 return false;
6327 if ((ValuebufferManager::ApiTypeForSubscriptionTarget(subscription) &
6328 info->accepts_api_type) == 0) {
6329 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
6330 "wrong type for subscription");
6331 return false;
6333 return true;
6336 bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
6337 if (!state_.current_program.get()) {
6338 // The program does not exist.
6339 LOCAL_SET_GL_ERROR(
6340 GL_INVALID_OPERATION, function_name, "no program in use");
6341 return false;
6343 if (!state_.current_program->InUse()) {
6344 LOCAL_SET_GL_ERROR(
6345 GL_INVALID_OPERATION, function_name, "program not linked");
6346 return false;
6348 return true;
6351 bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
6352 GLint location, const char* function_name) {
6353 if (!CheckCurrentProgram(function_name)) {
6354 return false;
6356 return location != -1;
6359 bool GLES2DecoderImpl::CheckDrawingFeedbackLoops() {
6360 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
6361 if (!framebuffer)
6362 return false;
6363 const Framebuffer::Attachment* attachment =
6364 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
6365 if (!attachment)
6366 return false;
6368 DCHECK(state_.current_program.get());
6369 const Program::SamplerIndices& sampler_indices =
6370 state_.current_program->sampler_indices();
6371 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6372 const Program::UniformInfo* uniform_info =
6373 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6374 DCHECK(uniform_info);
6375 if (uniform_info->type != GL_SAMPLER_2D)
6376 continue;
6377 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6378 GLuint texture_unit_index = uniform_info->texture_units[jj];
6379 if (texture_unit_index >= state_.texture_units.size())
6380 continue;
6381 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6382 TextureRef* texture_ref =
6383 texture_unit.GetInfoForSamplerType(GL_SAMPLER_2D).get();
6384 if (attachment->IsTexture(texture_ref))
6385 return true;
6388 return false;
6391 bool GLES2DecoderImpl::CheckUniformForApiType(
6392 const Program::UniformInfo* info,
6393 const char* function_name,
6394 Program::UniformApiType api_type) {
6395 DCHECK(info);
6396 if ((api_type & info->accepts_api_type) == 0) {
6397 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
6398 "wrong uniform function for type");
6399 return false;
6401 return true;
6404 bool GLES2DecoderImpl::PrepForSetUniformByLocation(
6405 GLint fake_location,
6406 const char* function_name,
6407 Program::UniformApiType api_type,
6408 GLint* real_location,
6409 GLenum* type,
6410 GLsizei* count) {
6411 DCHECK(type);
6412 DCHECK(count);
6413 DCHECK(real_location);
6415 if (!CheckCurrentProgramForUniform(fake_location, function_name)) {
6416 return false;
6418 GLint array_index = -1;
6419 const Program::UniformInfo* info =
6420 state_.current_program->GetUniformInfoByFakeLocation(
6421 fake_location, real_location, &array_index);
6422 if (!info) {
6423 LOCAL_SET_GL_ERROR(
6424 GL_INVALID_OPERATION, function_name, "unknown location");
6425 return false;
6427 if (!CheckUniformForApiType(info, function_name, api_type)) {
6428 return false;
6430 if (*count > 1 && !info->is_array) {
6431 LOCAL_SET_GL_ERROR(
6432 GL_INVALID_OPERATION, function_name, "count > 1 for non-array");
6433 return false;
6435 *count = std::min(info->size - array_index, *count);
6436 if (*count <= 0) {
6437 return false;
6439 *type = info->type;
6440 return true;
6443 void GLES2DecoderImpl::DoUniform1i(GLint fake_location, GLint v0) {
6444 GLenum type = 0;
6445 GLsizei count = 1;
6446 GLint real_location = -1;
6447 if (!PrepForSetUniformByLocation(fake_location,
6448 "glUniform1i",
6449 Program::kUniform1i,
6450 &real_location,
6451 &type,
6452 &count)) {
6453 return;
6455 if (!state_.current_program->SetSamplers(
6456 state_.texture_units.size(), fake_location, 1, &v0)) {
6457 LOCAL_SET_GL_ERROR(
6458 GL_INVALID_VALUE, "glUniform1i", "texture unit out of range");
6459 return;
6461 glUniform1i(real_location, v0);
6464 void GLES2DecoderImpl::DoUniform1iv(
6465 GLint fake_location, GLsizei count, const GLint *value) {
6466 GLenum type = 0;
6467 GLint real_location = -1;
6468 if (!PrepForSetUniformByLocation(fake_location,
6469 "glUniform1iv",
6470 Program::kUniform1i,
6471 &real_location,
6472 &type,
6473 &count)) {
6474 return;
6476 if (type == GL_SAMPLER_2D || type == GL_SAMPLER_2D_RECT_ARB ||
6477 type == GL_SAMPLER_CUBE || type == GL_SAMPLER_EXTERNAL_OES) {
6478 if (!state_.current_program->SetSamplers(
6479 state_.texture_units.size(), fake_location, count, value)) {
6480 LOCAL_SET_GL_ERROR(
6481 GL_INVALID_VALUE, "glUniform1iv", "texture unit out of range");
6482 return;
6485 glUniform1iv(real_location, count, value);
6488 void GLES2DecoderImpl::DoUniform1fv(
6489 GLint fake_location, GLsizei count, const GLfloat* value) {
6490 GLenum type = 0;
6491 GLint real_location = -1;
6492 if (!PrepForSetUniformByLocation(fake_location,
6493 "glUniform1fv",
6494 Program::kUniform1f,
6495 &real_location,
6496 &type,
6497 &count)) {
6498 return;
6500 if (type == GL_BOOL) {
6501 scoped_ptr<GLint[]> temp(new GLint[count]);
6502 for (GLsizei ii = 0; ii < count; ++ii) {
6503 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6505 DoUniform1iv(real_location, count, temp.get());
6506 } else {
6507 glUniform1fv(real_location, count, value);
6511 void GLES2DecoderImpl::DoUniform2fv(
6512 GLint fake_location, GLsizei count, const GLfloat* value) {
6513 GLenum type = 0;
6514 GLint real_location = -1;
6515 if (!PrepForSetUniformByLocation(fake_location,
6516 "glUniform2fv",
6517 Program::kUniform2f,
6518 &real_location,
6519 &type,
6520 &count)) {
6521 return;
6523 if (type == GL_BOOL_VEC2) {
6524 GLsizei num_values = count * 2;
6525 scoped_ptr<GLint[]> temp(new GLint[num_values]);
6526 for (GLsizei ii = 0; ii < num_values; ++ii) {
6527 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6529 glUniform2iv(real_location, count, temp.get());
6530 } else {
6531 glUniform2fv(real_location, count, value);
6535 void GLES2DecoderImpl::DoUniform3fv(
6536 GLint fake_location, GLsizei count, const GLfloat* value) {
6537 GLenum type = 0;
6538 GLint real_location = -1;
6539 if (!PrepForSetUniformByLocation(fake_location,
6540 "glUniform3fv",
6541 Program::kUniform3f,
6542 &real_location,
6543 &type,
6544 &count)) {
6545 return;
6547 if (type == GL_BOOL_VEC3) {
6548 GLsizei num_values = count * 3;
6549 scoped_ptr<GLint[]> temp(new GLint[num_values]);
6550 for (GLsizei ii = 0; ii < num_values; ++ii) {
6551 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6553 glUniform3iv(real_location, count, temp.get());
6554 } else {
6555 glUniform3fv(real_location, count, value);
6559 void GLES2DecoderImpl::DoUniform4fv(
6560 GLint fake_location, GLsizei count, const GLfloat* value) {
6561 GLenum type = 0;
6562 GLint real_location = -1;
6563 if (!PrepForSetUniformByLocation(fake_location,
6564 "glUniform4fv",
6565 Program::kUniform4f,
6566 &real_location,
6567 &type,
6568 &count)) {
6569 return;
6571 if (type == GL_BOOL_VEC4) {
6572 GLsizei num_values = count * 4;
6573 scoped_ptr<GLint[]> temp(new GLint[num_values]);
6574 for (GLsizei ii = 0; ii < num_values; ++ii) {
6575 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6577 glUniform4iv(real_location, count, temp.get());
6578 } else {
6579 glUniform4fv(real_location, count, value);
6583 void GLES2DecoderImpl::DoUniform2iv(
6584 GLint fake_location, GLsizei count, const GLint* value) {
6585 GLenum type = 0;
6586 GLint real_location = -1;
6587 if (!PrepForSetUniformByLocation(fake_location,
6588 "glUniform2iv",
6589 Program::kUniform2i,
6590 &real_location,
6591 &type,
6592 &count)) {
6593 return;
6595 glUniform2iv(real_location, count, value);
6598 void GLES2DecoderImpl::DoUniform3iv(
6599 GLint fake_location, GLsizei count, const GLint* value) {
6600 GLenum type = 0;
6601 GLint real_location = -1;
6602 if (!PrepForSetUniformByLocation(fake_location,
6603 "glUniform3iv",
6604 Program::kUniform3i,
6605 &real_location,
6606 &type,
6607 &count)) {
6608 return;
6610 glUniform3iv(real_location, count, value);
6613 void GLES2DecoderImpl::DoUniform4iv(
6614 GLint fake_location, GLsizei count, const GLint* value) {
6615 GLenum type = 0;
6616 GLint real_location = -1;
6617 if (!PrepForSetUniformByLocation(fake_location,
6618 "glUniform4iv",
6619 Program::kUniform4i,
6620 &real_location,
6621 &type,
6622 &count)) {
6623 return;
6625 glUniform4iv(real_location, count, value);
6628 void GLES2DecoderImpl::DoUniformMatrix2fv(
6629 GLint fake_location, GLsizei count, GLboolean transpose,
6630 const GLfloat* value) {
6631 GLenum type = 0;
6632 GLint real_location = -1;
6633 if (!PrepForSetUniformByLocation(fake_location,
6634 "glUniformMatrix2fv",
6635 Program::kUniformMatrix2f,
6636 &real_location,
6637 &type,
6638 &count)) {
6639 return;
6641 glUniformMatrix2fv(real_location, count, transpose, value);
6644 void GLES2DecoderImpl::DoUniformMatrix3fv(
6645 GLint fake_location, GLsizei count, GLboolean transpose,
6646 const GLfloat* value) {
6647 GLenum type = 0;
6648 GLint real_location = -1;
6649 if (!PrepForSetUniformByLocation(fake_location,
6650 "glUniformMatrix3fv",
6651 Program::kUniformMatrix3f,
6652 &real_location,
6653 &type,
6654 &count)) {
6655 return;
6657 glUniformMatrix3fv(real_location, count, transpose, value);
6660 void GLES2DecoderImpl::DoUniformMatrix4fv(
6661 GLint fake_location, GLsizei count, GLboolean transpose,
6662 const GLfloat* value) {
6663 GLenum type = 0;
6664 GLint real_location = -1;
6665 if (!PrepForSetUniformByLocation(fake_location,
6666 "glUniformMatrix4fv",
6667 Program::kUniformMatrix4f,
6668 &real_location,
6669 &type,
6670 &count)) {
6671 return;
6673 glUniformMatrix4fv(real_location, count, transpose, value);
6676 void GLES2DecoderImpl::DoUseProgram(GLuint program_id) {
6677 GLuint service_id = 0;
6678 Program* program = NULL;
6679 if (program_id) {
6680 program = GetProgramInfoNotShader(program_id, "glUseProgram");
6681 if (!program) {
6682 return;
6684 if (!program->IsValid()) {
6685 // Program was not linked successfully. (ie, glLinkProgram)
6686 LOCAL_SET_GL_ERROR(
6687 GL_INVALID_OPERATION, "glUseProgram", "program not linked");
6688 return;
6690 service_id = program->service_id();
6692 if (state_.current_program.get()) {
6693 program_manager()->UnuseProgram(shader_manager(),
6694 state_.current_program.get());
6696 state_.current_program = program;
6697 LogClientServiceMapping("glUseProgram", program_id, service_id);
6698 glUseProgram(service_id);
6699 if (state_.current_program.get()) {
6700 program_manager()->UseProgram(state_.current_program.get());
6701 if (workarounds().clear_uniforms_before_first_program_use)
6702 program_manager()->ClearUniforms(program);
6706 void GLES2DecoderImpl::RenderWarning(
6707 const char* filename, int line, const std::string& msg) {
6708 logger_.LogMessage(filename, line, std::string("RENDER WARNING: ") + msg);
6711 void GLES2DecoderImpl::PerformanceWarning(
6712 const char* filename, int line, const std::string& msg) {
6713 logger_.LogMessage(filename, line,
6714 std::string("PERFORMANCE WARNING: ") + msg);
6717 void GLES2DecoderImpl::DoWillUseTexImageIfNeeded(
6718 Texture* texture, GLenum textarget) {
6719 // Image is already in use if texture is attached to a framebuffer.
6720 if (texture && !texture->IsAttachedToFramebuffer()) {
6721 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6722 if (image) {
6723 ScopedGLErrorSuppressor suppressor(
6724 "GLES2DecoderImpl::DoWillUseTexImageIfNeeded",
6725 GetErrorState());
6726 glBindTexture(textarget, texture->service_id());
6727 image->WillUseTexImage();
6728 RestoreCurrentTextureBindings(&state_, textarget);
6733 void GLES2DecoderImpl::DoDidUseTexImageIfNeeded(
6734 Texture* texture, GLenum textarget) {
6735 // Image is still in use if texture is attached to a framebuffer.
6736 if (texture && !texture->IsAttachedToFramebuffer()) {
6737 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6738 if (image) {
6739 ScopedGLErrorSuppressor suppressor(
6740 "GLES2DecoderImpl::DoDidUseTexImageIfNeeded",
6741 GetErrorState());
6742 glBindTexture(textarget, texture->service_id());
6743 image->DidUseTexImage();
6744 RestoreCurrentTextureBindings(&state_, textarget);
6749 bool GLES2DecoderImpl::PrepareTexturesForRender() {
6750 DCHECK(state_.current_program.get());
6751 if (!texture_manager()->HaveUnrenderableTextures() &&
6752 !texture_manager()->HaveImages()) {
6753 return true;
6756 bool textures_set = false;
6757 const Program::SamplerIndices& sampler_indices =
6758 state_.current_program->sampler_indices();
6759 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6760 const Program::UniformInfo* uniform_info =
6761 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6762 DCHECK(uniform_info);
6763 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6764 GLuint texture_unit_index = uniform_info->texture_units[jj];
6765 if (texture_unit_index < state_.texture_units.size()) {
6766 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6767 TextureRef* texture_ref =
6768 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6769 GLenum textarget = GetBindTargetForSamplerType(uniform_info->type);
6770 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
6771 textures_set = true;
6772 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6773 glBindTexture(
6774 textarget,
6775 texture_manager()->black_texture_id(uniform_info->type));
6776 if (!texture_ref) {
6777 LOCAL_RENDER_WARNING(
6778 std::string("there is no texture bound to the unit ") +
6779 base::IntToString(texture_unit_index));
6780 } else {
6781 LOCAL_RENDER_WARNING(
6782 std::string("texture bound to texture unit ") +
6783 base::IntToString(texture_unit_index) +
6784 " is not renderable. It maybe non-power-of-2 and have"
6785 " incompatible texture filtering.");
6787 continue;
6790 if (textarget != GL_TEXTURE_CUBE_MAP) {
6791 Texture* texture = texture_ref->texture();
6792 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6793 if (image && !texture->IsAttachedToFramebuffer()) {
6794 ScopedGLErrorSuppressor suppressor(
6795 "GLES2DecoderImpl::PrepareTexturesForRender", GetErrorState());
6796 textures_set = true;
6797 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6798 image->WillUseTexImage();
6799 continue;
6803 // else: should this be an error?
6806 return !textures_set;
6809 void GLES2DecoderImpl::RestoreStateForTextures() {
6810 DCHECK(state_.current_program.get());
6811 const Program::SamplerIndices& sampler_indices =
6812 state_.current_program->sampler_indices();
6813 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6814 const Program::UniformInfo* uniform_info =
6815 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6816 DCHECK(uniform_info);
6817 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6818 GLuint texture_unit_index = uniform_info->texture_units[jj];
6819 if (texture_unit_index < state_.texture_units.size()) {
6820 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6821 TextureRef* texture_ref =
6822 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6823 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
6824 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6825 // Get the texture_ref info that was previously bound here.
6826 texture_ref = texture_unit.bind_target == GL_TEXTURE_2D
6827 ? texture_unit.bound_texture_2d.get()
6828 : texture_unit.bound_texture_cube_map.get();
6829 glBindTexture(texture_unit.bind_target,
6830 texture_ref ? texture_ref->service_id() : 0);
6831 continue;
6834 if (texture_unit.bind_target != GL_TEXTURE_CUBE_MAP) {
6835 Texture* texture = texture_ref->texture();
6836 gfx::GLImage* image =
6837 texture->GetLevelImage(texture_unit.bind_target, 0);
6838 if (image && !texture->IsAttachedToFramebuffer()) {
6839 ScopedGLErrorSuppressor suppressor(
6840 "GLES2DecoderImpl::RestoreStateForTextures", GetErrorState());
6841 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6842 image->DidUseTexImage();
6843 continue;
6849 // Set the active texture back to whatever the user had it as.
6850 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
6853 bool GLES2DecoderImpl::ClearUnclearedTextures() {
6854 // Only check if there are some uncleared textures.
6855 if (!texture_manager()->HaveUnsafeTextures()) {
6856 return true;
6859 // 1: Check all textures we are about to render with.
6860 if (state_.current_program.get()) {
6861 const Program::SamplerIndices& sampler_indices =
6862 state_.current_program->sampler_indices();
6863 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6864 const Program::UniformInfo* uniform_info =
6865 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6866 DCHECK(uniform_info);
6867 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6868 GLuint texture_unit_index = uniform_info->texture_units[jj];
6869 if (texture_unit_index < state_.texture_units.size()) {
6870 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6871 TextureRef* texture_ref =
6872 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6873 if (texture_ref && !texture_ref->texture()->SafeToRenderFrom()) {
6874 if (!texture_manager()->ClearRenderableLevels(this, texture_ref)) {
6875 return false;
6882 return true;
6885 bool GLES2DecoderImpl::IsDrawValid(
6886 const char* function_name, GLuint max_vertex_accessed, bool instanced,
6887 GLsizei primcount) {
6888 DCHECK(instanced || primcount == 1);
6890 // NOTE: We specifically do not check current_program->IsValid() because
6891 // it could never be invalid since glUseProgram would have failed. While
6892 // glLinkProgram could later mark the program as invalid the previous
6893 // valid program will still function if it is still the current program.
6894 if (!state_.current_program.get()) {
6895 // The program does not exist.
6896 // But GL says no ERROR.
6897 LOCAL_RENDER_WARNING("Drawing with no current shader program.");
6898 return false;
6901 if (CheckDrawingFeedbackLoops()) {
6902 LOCAL_SET_GL_ERROR(
6903 GL_INVALID_OPERATION, function_name,
6904 "Source and destination textures of the draw are the same.");
6905 return false;
6908 return state_.vertex_attrib_manager
6909 ->ValidateBindings(function_name,
6910 this,
6911 feature_info_.get(),
6912 state_.current_program.get(),
6913 max_vertex_accessed,
6914 instanced,
6915 primcount);
6918 bool GLES2DecoderImpl::SimulateAttrib0(
6919 const char* function_name, GLuint max_vertex_accessed, bool* simulated) {
6920 DCHECK(simulated);
6921 *simulated = false;
6923 if (feature_info_->gl_version_info().BehavesLikeGLES())
6924 return true;
6926 const VertexAttrib* attrib =
6927 state_.vertex_attrib_manager->GetVertexAttrib(0);
6928 // If it's enabled or it's not used then we don't need to do anything.
6929 bool attrib_0_used =
6930 state_.current_program->GetAttribInfoByLocation(0) != NULL;
6931 if (attrib->enabled() && attrib_0_used) {
6932 return true;
6935 // Make a buffer with a single repeated vec4 value enough to
6936 // simulate the constant value that is supposed to be here.
6937 // This is required to emulate GLES2 on GL.
6938 GLuint num_vertices = max_vertex_accessed + 1;
6939 uint32 size_needed = 0;
6941 if (num_vertices == 0 ||
6942 !SafeMultiplyUint32(num_vertices, sizeof(Vec4f), &size_needed) ||
6943 size_needed > 0x7FFFFFFFU) {
6944 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6945 return false;
6948 LOCAL_PERFORMANCE_WARNING(
6949 "Attribute 0 is disabled. This has signficant performance penalty");
6951 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
6952 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
6954 bool new_buffer = static_cast<GLsizei>(size_needed) > attrib_0_size_;
6955 if (new_buffer) {
6956 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
6957 GLenum error = glGetError();
6958 if (error != GL_NO_ERROR) {
6959 LOCAL_SET_GL_ERROR(
6960 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6961 return false;
6965 const Vec4& value = state_.attrib_values[0];
6966 if (new_buffer ||
6967 (attrib_0_used &&
6968 (!attrib_0_buffer_matches_value_ || !value.Equal(attrib_0_value_)))){
6969 // TODO(zmo): This is not 100% correct because we might lose data when
6970 // casting to float type, but it is a corner case and once we migrate to
6971 // core profiles on desktop GL, it is no longer relevant.
6972 Vec4f fvalue(value);
6973 std::vector<Vec4f> temp(num_vertices, fvalue);
6974 glBufferSubData(GL_ARRAY_BUFFER, 0, size_needed, &temp[0].v[0]);
6975 attrib_0_buffer_matches_value_ = true;
6976 attrib_0_value_ = value;
6977 attrib_0_size_ = size_needed;
6980 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
6982 if (attrib->divisor())
6983 glVertexAttribDivisorANGLE(0, 0);
6985 *simulated = true;
6986 return true;
6989 void GLES2DecoderImpl::RestoreStateForAttrib(
6990 GLuint attrib_index, bool restore_array_binding) {
6991 const VertexAttrib* attrib =
6992 state_.vertex_attrib_manager->GetVertexAttrib(attrib_index);
6993 if (restore_array_binding) {
6994 const void* ptr = reinterpret_cast<const void*>(attrib->offset());
6995 Buffer* buffer = attrib->buffer();
6996 glBindBuffer(GL_ARRAY_BUFFER, buffer ? buffer->service_id() : 0);
6997 glVertexAttribPointer(
6998 attrib_index, attrib->size(), attrib->type(), attrib->normalized(),
6999 attrib->gl_stride(), ptr);
7001 if (attrib->divisor())
7002 glVertexAttribDivisorANGLE(attrib_index, attrib->divisor());
7003 glBindBuffer(
7004 GL_ARRAY_BUFFER, state_.bound_array_buffer.get() ?
7005 state_.bound_array_buffer->service_id() : 0);
7007 // Never touch vertex attribute 0's state (in particular, never
7008 // disable it) when running on desktop GL because it will never be
7009 // re-enabled.
7010 if (attrib_index != 0 ||
7011 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
7012 if (attrib->enabled()) {
7013 glEnableVertexAttribArray(attrib_index);
7014 } else {
7015 glDisableVertexAttribArray(attrib_index);
7020 bool GLES2DecoderImpl::SimulateFixedAttribs(
7021 const char* function_name,
7022 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount) {
7023 DCHECK(simulated);
7024 *simulated = false;
7025 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
7026 return true;
7028 if (!state_.vertex_attrib_manager->HaveFixedAttribs()) {
7029 return true;
7032 LOCAL_PERFORMANCE_WARNING(
7033 "GL_FIXED attributes have a signficant performance penalty");
7035 // NOTE: we could be smart and try to check if a buffer is used
7036 // twice in 2 different attribs, find the overlapping parts and therefore
7037 // duplicate the minimum amount of data but this whole code path is not meant
7038 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
7039 // tests so we just add to the buffer attrib used.
7041 GLuint elements_needed = 0;
7042 const VertexAttribManager::VertexAttribList& enabled_attribs =
7043 state_.vertex_attrib_manager->GetEnabledVertexAttribs();
7044 for (VertexAttribManager::VertexAttribList::const_iterator it =
7045 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
7046 const VertexAttrib* attrib = *it;
7047 const Program::VertexAttrib* attrib_info =
7048 state_.current_program->GetAttribInfoByLocation(attrib->index());
7049 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
7050 max_vertex_accessed);
7051 GLuint num_vertices = max_accessed + 1;
7052 if (num_vertices == 0) {
7053 LOCAL_SET_GL_ERROR(
7054 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
7055 return false;
7057 if (attrib_info &&
7058 attrib->CanAccess(max_accessed) &&
7059 attrib->type() == GL_FIXED) {
7060 uint32 elements_used = 0;
7061 if (!SafeMultiplyUint32(num_vertices, attrib->size(), &elements_used) ||
7062 !SafeAddUint32(elements_needed, elements_used, &elements_needed)) {
7063 LOCAL_SET_GL_ERROR(
7064 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
7065 return false;
7070 const uint32 kSizeOfFloat = sizeof(float); // NOLINT
7071 uint32 size_needed = 0;
7072 if (!SafeMultiplyUint32(elements_needed, kSizeOfFloat, &size_needed) ||
7073 size_needed > 0x7FFFFFFFU) {
7074 LOCAL_SET_GL_ERROR(
7075 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
7076 return false;
7079 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
7081 glBindBuffer(GL_ARRAY_BUFFER, fixed_attrib_buffer_id_);
7082 if (static_cast<GLsizei>(size_needed) > fixed_attrib_buffer_size_) {
7083 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
7084 GLenum error = glGetError();
7085 if (error != GL_NO_ERROR) {
7086 LOCAL_SET_GL_ERROR(
7087 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
7088 return false;
7092 // Copy the elements and convert to float
7093 GLintptr offset = 0;
7094 for (VertexAttribManager::VertexAttribList::const_iterator it =
7095 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
7096 const VertexAttrib* attrib = *it;
7097 const Program::VertexAttrib* attrib_info =
7098 state_.current_program->GetAttribInfoByLocation(attrib->index());
7099 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
7100 max_vertex_accessed);
7101 GLuint num_vertices = max_accessed + 1;
7102 if (num_vertices == 0) {
7103 LOCAL_SET_GL_ERROR(
7104 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
7105 return false;
7107 if (attrib_info &&
7108 attrib->CanAccess(max_accessed) &&
7109 attrib->type() == GL_FIXED) {
7110 int num_elements = attrib->size() * num_vertices;
7111 const int src_size = num_elements * sizeof(int32);
7112 const int dst_size = num_elements * sizeof(float);
7113 scoped_ptr<float[]> data(new float[num_elements]);
7114 const int32* src = reinterpret_cast<const int32 *>(
7115 attrib->buffer()->GetRange(attrib->offset(), src_size));
7116 const int32* end = src + num_elements;
7117 float* dst = data.get();
7118 while (src != end) {
7119 *dst++ = static_cast<float>(*src++) / 65536.0f;
7121 glBufferSubData(GL_ARRAY_BUFFER, offset, dst_size, data.get());
7122 glVertexAttribPointer(
7123 attrib->index(), attrib->size(), GL_FLOAT, false, 0,
7124 reinterpret_cast<GLvoid*>(offset));
7125 offset += dst_size;
7128 *simulated = true;
7129 return true;
7132 void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
7133 // There's no need to call glVertexAttribPointer because we shadow all the
7134 // settings and passing GL_FIXED to it will not work.
7135 glBindBuffer(
7136 GL_ARRAY_BUFFER,
7137 state_.bound_array_buffer.get() ? state_.bound_array_buffer->service_id()
7138 : 0);
7141 error::Error GLES2DecoderImpl::DoDrawArrays(
7142 const char* function_name,
7143 bool instanced,
7144 GLenum mode,
7145 GLint first,
7146 GLsizei count,
7147 GLsizei primcount) {
7148 error::Error error = WillAccessBoundFramebufferForDraw();
7149 if (error != error::kNoError)
7150 return error;
7151 if (!validators_->draw_mode.IsValid(mode)) {
7152 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
7153 return error::kNoError;
7155 if (count < 0) {
7156 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
7157 return error::kNoError;
7159 if (primcount < 0) {
7160 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
7161 return error::kNoError;
7163 if (!CheckBoundFramebuffersValid(function_name)) {
7164 return error::kNoError;
7166 // We have to check this here because the prototype for glDrawArrays
7167 // is GLint not GLsizei.
7168 if (first < 0) {
7169 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "first < 0");
7170 return error::kNoError;
7173 if (count == 0 || primcount == 0) {
7174 LOCAL_RENDER_WARNING("Render count or primcount is 0.");
7175 return error::kNoError;
7178 GLuint max_vertex_accessed = first + count - 1;
7179 if (IsDrawValid(function_name, max_vertex_accessed, instanced, primcount)) {
7180 if (!ClearUnclearedTextures()) {
7181 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
7182 return error::kNoError;
7184 bool simulated_attrib_0 = false;
7185 if (!SimulateAttrib0(
7186 function_name, max_vertex_accessed, &simulated_attrib_0)) {
7187 return error::kNoError;
7189 bool simulated_fixed_attribs = false;
7190 if (SimulateFixedAttribs(
7191 function_name, max_vertex_accessed, &simulated_fixed_attribs,
7192 primcount)) {
7193 bool textures_set = !PrepareTexturesForRender();
7194 ApplyDirtyState();
7195 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
7196 if (!instanced) {
7197 glDrawArrays(mode, first, count);
7198 } else {
7199 glDrawArraysInstancedANGLE(mode, first, count, primcount);
7201 if (textures_set) {
7202 RestoreStateForTextures();
7204 if (simulated_fixed_attribs) {
7205 RestoreStateForSimulatedFixedAttribs();
7208 if (simulated_attrib_0) {
7209 // We don't have to restore attrib 0 generic data at the end of this
7210 // function even if it is simulated. This is because we will simulate
7211 // it in each draw call, and attrib 0 generic data queries use cached
7212 // values instead of passing down to the underlying driver.
7213 RestoreStateForAttrib(0, false);
7216 return error::kNoError;
7219 error::Error GLES2DecoderImpl::HandleDrawArrays(uint32 immediate_data_size,
7220 const void* cmd_data) {
7221 // TODO(zmo): crbug.com/481184
7222 // On Desktop GL with versions lower than 4.3, we need to emulate
7223 // GL_PRIMITIVE_RESTART_FIXED_INDEX using glPrimitiveRestartIndex().
7224 const cmds::DrawArrays& c = *static_cast<const cmds::DrawArrays*>(cmd_data);
7225 return DoDrawArrays("glDrawArrays",
7226 false,
7227 static_cast<GLenum>(c.mode),
7228 static_cast<GLint>(c.first),
7229 static_cast<GLsizei>(c.count),
7233 error::Error GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
7234 uint32 immediate_data_size,
7235 const void* cmd_data) {
7236 const gles2::cmds::DrawArraysInstancedANGLE& c =
7237 *static_cast<const gles2::cmds::DrawArraysInstancedANGLE*>(cmd_data);
7238 if (!features().angle_instanced_arrays) {
7239 LOCAL_SET_GL_ERROR(
7240 GL_INVALID_OPERATION,
7241 "glDrawArraysInstancedANGLE", "function not available");
7242 return error::kNoError;
7244 return DoDrawArrays("glDrawArraysIntancedANGLE",
7245 true,
7246 static_cast<GLenum>(c.mode),
7247 static_cast<GLint>(c.first),
7248 static_cast<GLsizei>(c.count),
7249 static_cast<GLsizei>(c.primcount));
7252 error::Error GLES2DecoderImpl::DoDrawElements(
7253 const char* function_name,
7254 bool instanced,
7255 GLenum mode,
7256 GLsizei count,
7257 GLenum type,
7258 int32 offset,
7259 GLsizei primcount) {
7260 error::Error error = WillAccessBoundFramebufferForDraw();
7261 if (error != error::kNoError)
7262 return error;
7263 if (!state_.vertex_attrib_manager->element_array_buffer()) {
7264 LOCAL_SET_GL_ERROR(
7265 GL_INVALID_OPERATION, function_name, "No element array buffer bound");
7266 return error::kNoError;
7269 if (count < 0) {
7270 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
7271 return error::kNoError;
7273 if (offset < 0) {
7274 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "offset < 0");
7275 return error::kNoError;
7277 if (!validators_->draw_mode.IsValid(mode)) {
7278 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
7279 return error::kNoError;
7281 if (!validators_->index_type.IsValid(type)) {
7282 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, type, "type");
7283 return error::kNoError;
7285 if (primcount < 0) {
7286 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
7287 return error::kNoError;
7290 if (!CheckBoundFramebuffersValid(function_name)) {
7291 return error::kNoError;
7294 if (count == 0 || primcount == 0) {
7295 return error::kNoError;
7298 GLuint max_vertex_accessed;
7299 Buffer* element_array_buffer =
7300 state_.vertex_attrib_manager->element_array_buffer();
7302 if (!element_array_buffer->GetMaxValueForRange(
7303 offset, count, type, &max_vertex_accessed)) {
7304 LOCAL_SET_GL_ERROR(
7305 GL_INVALID_OPERATION, function_name, "range out of bounds for buffer");
7306 return error::kNoError;
7309 if (IsDrawValid(function_name, max_vertex_accessed, instanced, primcount)) {
7310 if (!ClearUnclearedTextures()) {
7311 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
7312 return error::kNoError;
7314 bool simulated_attrib_0 = false;
7315 if (!SimulateAttrib0(
7316 function_name, max_vertex_accessed, &simulated_attrib_0)) {
7317 return error::kNoError;
7319 bool simulated_fixed_attribs = false;
7320 if (SimulateFixedAttribs(
7321 function_name, max_vertex_accessed, &simulated_fixed_attribs,
7322 primcount)) {
7323 bool textures_set = !PrepareTexturesForRender();
7324 ApplyDirtyState();
7325 // TODO(gman): Refactor to hide these details in BufferManager or
7326 // VertexAttribManager.
7327 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
7328 bool used_client_side_array = false;
7329 if (element_array_buffer->IsClientSideArray()) {
7330 used_client_side_array = true;
7331 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
7332 indices = element_array_buffer->GetRange(offset, 0);
7335 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
7336 if (!instanced) {
7337 glDrawElements(mode, count, type, indices);
7338 } else {
7339 glDrawElementsInstancedANGLE(mode, count, type, indices, primcount);
7342 if (used_client_side_array) {
7343 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
7344 element_array_buffer->service_id());
7347 if (textures_set) {
7348 RestoreStateForTextures();
7350 if (simulated_fixed_attribs) {
7351 RestoreStateForSimulatedFixedAttribs();
7354 if (simulated_attrib_0) {
7355 // We don't have to restore attrib 0 generic data at the end of this
7356 // function even if it is simulated. This is because we will simulate
7357 // it in each draw call, and attrib 0 generic data queries use cached
7358 // values instead of passing down to the underlying driver.
7359 RestoreStateForAttrib(0, false);
7362 return error::kNoError;
7365 error::Error GLES2DecoderImpl::HandleDrawElements(uint32 immediate_data_size,
7366 const void* cmd_data) {
7367 // TODO(zmo): crbug.com/481184
7368 // On Desktop GL with versions lower than 4.3, we need to emulate
7369 // GL_PRIMITIVE_RESTART_FIXED_INDEX using glPrimitiveRestartIndex().
7370 const gles2::cmds::DrawElements& c =
7371 *static_cast<const gles2::cmds::DrawElements*>(cmd_data);
7372 return DoDrawElements("glDrawElements",
7373 false,
7374 static_cast<GLenum>(c.mode),
7375 static_cast<GLsizei>(c.count),
7376 static_cast<GLenum>(c.type),
7377 static_cast<int32>(c.index_offset),
7381 error::Error GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
7382 uint32 immediate_data_size,
7383 const void* cmd_data) {
7384 const gles2::cmds::DrawElementsInstancedANGLE& c =
7385 *static_cast<const gles2::cmds::DrawElementsInstancedANGLE*>(cmd_data);
7386 if (!features().angle_instanced_arrays) {
7387 LOCAL_SET_GL_ERROR(
7388 GL_INVALID_OPERATION,
7389 "glDrawElementsInstancedANGLE", "function not available");
7390 return error::kNoError;
7392 return DoDrawElements("glDrawElementsInstancedANGLE",
7393 true,
7394 static_cast<GLenum>(c.mode),
7395 static_cast<GLsizei>(c.count),
7396 static_cast<GLenum>(c.type),
7397 static_cast<int32>(c.index_offset),
7398 static_cast<GLsizei>(c.primcount));
7401 GLuint GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
7402 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
7403 GLuint max_vertex_accessed = 0;
7404 Buffer* buffer = GetBuffer(buffer_id);
7405 if (!buffer) {
7406 // TODO(gman): Should this be a GL error or a command buffer error?
7407 LOCAL_SET_GL_ERROR(
7408 GL_INVALID_VALUE, "GetMaxValueInBufferCHROMIUM", "unknown buffer");
7409 } else {
7410 if (!buffer->GetMaxValueForRange(
7411 offset, count, type, &max_vertex_accessed)) {
7412 // TODO(gman): Should this be a GL error or a command buffer error?
7413 LOCAL_SET_GL_ERROR(
7414 GL_INVALID_OPERATION,
7415 "GetMaxValueInBufferCHROMIUM", "range out of bounds for buffer");
7418 return max_vertex_accessed;
7421 void GLES2DecoderImpl::DoShaderSource(
7422 GLuint client_id, GLsizei count, const char** data, const GLint* length) {
7423 std::string str;
7424 for (GLsizei ii = 0; ii < count; ++ii) {
7425 if (length && length[ii] > 0)
7426 str.append(data[ii], length[ii]);
7427 else
7428 str.append(data[ii]);
7430 Shader* shader = GetShaderInfoNotProgram(client_id, "glShaderSource");
7431 if (!shader) {
7432 return;
7434 // Note: We don't actually call glShaderSource here. We wait until
7435 // we actually compile the shader.
7436 shader->set_source(str);
7439 void GLES2DecoderImpl::DoTransformFeedbackVaryings(
7440 GLuint client_program_id, GLsizei count, const char* const* varyings,
7441 GLenum buffer_mode) {
7442 Program* program = GetProgramInfoNotShader(
7443 client_program_id, "glTransformFeedbackVaryings");
7444 if (!program) {
7445 return;
7447 program->TransformFeedbackVaryings(count, varyings, buffer_mode);
7448 glTransformFeedbackVaryings(
7449 program->service_id(), count, varyings, buffer_mode);
7452 void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
7453 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
7454 Shader* shader = GetShaderInfoNotProgram(client_id, "glCompileShader");
7455 if (!shader) {
7456 return;
7459 scoped_refptr<ShaderTranslatorInterface> translator;
7460 if (use_shader_translator_) {
7461 translator = shader->shader_type() == GL_VERTEX_SHADER ?
7462 vertex_translator_ : fragment_translator_;
7465 const Shader::TranslatedShaderSourceType source_type =
7466 feature_info_->feature_flags().angle_translated_shader_source ?
7467 Shader::kANGLE : Shader::kGL;
7468 shader->RequestCompile(translator, source_type);
7471 void GLES2DecoderImpl::DoGetShaderiv(
7472 GLuint shader_id, GLenum pname, GLint* params) {
7473 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderiv");
7474 if (!shader) {
7475 return;
7478 // Compile now for statuses that require it.
7479 switch (pname) {
7480 case GL_COMPILE_STATUS:
7481 case GL_INFO_LOG_LENGTH:
7482 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
7483 shader->DoCompile();
7484 break;
7486 default:
7487 break;
7490 switch (pname) {
7491 case GL_SHADER_SOURCE_LENGTH:
7492 *params = shader->source().size();
7493 if (*params)
7494 ++(*params);
7495 return;
7496 case GL_COMPILE_STATUS:
7497 *params = compile_shader_always_succeeds_ ? true : shader->valid();
7498 return;
7499 case GL_INFO_LOG_LENGTH:
7500 *params = shader->log_info().size();
7501 if (*params)
7502 ++(*params);
7503 return;
7504 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
7505 *params = shader->translated_source().size();
7506 if (*params)
7507 ++(*params);
7508 return;
7509 default:
7510 break;
7512 glGetShaderiv(shader->service_id(), pname, params);
7515 error::Error GLES2DecoderImpl::HandleGetShaderSource(uint32 immediate_data_size,
7516 const void* cmd_data) {
7517 const gles2::cmds::GetShaderSource& c =
7518 *static_cast<const gles2::cmds::GetShaderSource*>(cmd_data);
7519 GLuint shader_id = c.shader;
7520 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
7521 Bucket* bucket = CreateBucket(bucket_id);
7522 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderSource");
7523 if (!shader || shader->source().empty()) {
7524 bucket->SetSize(0);
7525 return error::kNoError;
7527 bucket->SetFromString(shader->source().c_str());
7528 return error::kNoError;
7531 error::Error GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
7532 uint32 immediate_data_size,
7533 const void* cmd_data) {
7534 const gles2::cmds::GetTranslatedShaderSourceANGLE& c =
7535 *static_cast<const gles2::cmds::GetTranslatedShaderSourceANGLE*>(
7536 cmd_data);
7537 GLuint shader_id = c.shader;
7538 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
7539 Bucket* bucket = CreateBucket(bucket_id);
7540 Shader* shader = GetShaderInfoNotProgram(
7541 shader_id, "glGetTranslatedShaderSourceANGLE");
7542 if (!shader) {
7543 bucket->SetSize(0);
7544 return error::kNoError;
7547 // Make sure translator has been utilized in compile.
7548 shader->DoCompile();
7550 bucket->SetFromString(shader->translated_source().c_str());
7551 return error::kNoError;
7554 error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
7555 uint32 immediate_data_size,
7556 const void* cmd_data) {
7557 const gles2::cmds::GetProgramInfoLog& c =
7558 *static_cast<const gles2::cmds::GetProgramInfoLog*>(cmd_data);
7559 GLuint program_id = c.program;
7560 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
7561 Bucket* bucket = CreateBucket(bucket_id);
7562 Program* program = GetProgramInfoNotShader(
7563 program_id, "glGetProgramInfoLog");
7564 if (!program || !program->log_info()) {
7565 bucket->SetFromString("");
7566 return error::kNoError;
7568 bucket->SetFromString(program->log_info()->c_str());
7569 return error::kNoError;
7572 error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
7573 uint32 immediate_data_size,
7574 const void* cmd_data) {
7575 const gles2::cmds::GetShaderInfoLog& c =
7576 *static_cast<const gles2::cmds::GetShaderInfoLog*>(cmd_data);
7577 GLuint shader_id = c.shader;
7578 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
7579 Bucket* bucket = CreateBucket(bucket_id);
7580 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderInfoLog");
7581 if (!shader) {
7582 bucket->SetFromString("");
7583 return error::kNoError;
7586 // Shader must be compiled in order to get the info log.
7587 shader->DoCompile();
7589 bucket->SetFromString(shader->log_info().c_str());
7590 return error::kNoError;
7593 bool GLES2DecoderImpl::DoIsEnabled(GLenum cap) {
7594 return state_.GetEnabled(cap);
7597 bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
7598 const Buffer* buffer = GetBuffer(client_id);
7599 return buffer && buffer->IsValid() && !buffer->IsDeleted();
7602 bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
7603 const Framebuffer* framebuffer =
7604 GetFramebuffer(client_id);
7605 return framebuffer && framebuffer->IsValid() && !framebuffer->IsDeleted();
7608 bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
7609 // IsProgram is true for programs as soon as they are created, until they are
7610 // deleted and no longer in use.
7611 const Program* program = GetProgram(client_id);
7612 return program != NULL && !program->IsDeleted();
7615 bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
7616 const Renderbuffer* renderbuffer =
7617 GetRenderbuffer(client_id);
7618 return renderbuffer && renderbuffer->IsValid() && !renderbuffer->IsDeleted();
7621 bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
7622 // IsShader is true for shaders as soon as they are created, until they
7623 // are deleted and not attached to any programs.
7624 const Shader* shader = GetShader(client_id);
7625 return shader != NULL && !shader->IsDeleted();
7628 bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
7629 const TextureRef* texture_ref = GetTexture(client_id);
7630 return texture_ref && texture_ref->texture()->IsValid();
7633 void GLES2DecoderImpl::DoAttachShader(
7634 GLuint program_client_id, GLint shader_client_id) {
7635 Program* program = GetProgramInfoNotShader(
7636 program_client_id, "glAttachShader");
7637 if (!program) {
7638 return;
7640 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glAttachShader");
7641 if (!shader) {
7642 return;
7644 if (!program->AttachShader(shader_manager(), shader)) {
7645 LOCAL_SET_GL_ERROR(
7646 GL_INVALID_OPERATION,
7647 "glAttachShader",
7648 "can not attach more than one shader of the same type.");
7649 return;
7651 glAttachShader(program->service_id(), shader->service_id());
7654 void GLES2DecoderImpl::DoDetachShader(
7655 GLuint program_client_id, GLint shader_client_id) {
7656 Program* program = GetProgramInfoNotShader(
7657 program_client_id, "glDetachShader");
7658 if (!program) {
7659 return;
7661 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glDetachShader");
7662 if (!shader) {
7663 return;
7665 if (!program->DetachShader(shader_manager(), shader)) {
7666 LOCAL_SET_GL_ERROR(
7667 GL_INVALID_OPERATION,
7668 "glDetachShader", "shader not attached to program");
7669 return;
7671 glDetachShader(program->service_id(), shader->service_id());
7674 void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
7675 Program* program = GetProgramInfoNotShader(
7676 program_client_id, "glValidateProgram");
7677 if (!program) {
7678 return;
7680 program->Validate();
7683 void GLES2DecoderImpl::GetVertexAttribHelper(
7684 const VertexAttrib* attrib, GLenum pname, GLint* params) {
7685 switch (pname) {
7686 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
7688 Buffer* buffer = attrib->buffer();
7689 if (buffer && !buffer->IsDeleted()) {
7690 GLuint client_id;
7691 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
7692 *params = client_id;
7694 break;
7696 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
7697 *params = attrib->enabled();
7698 break;
7699 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
7700 *params = attrib->size();
7701 break;
7702 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
7703 *params = attrib->gl_stride();
7704 break;
7705 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
7706 *params = attrib->type();
7707 break;
7708 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
7709 *params = attrib->normalized();
7710 break;
7711 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
7712 *params = attrib->divisor();
7713 break;
7714 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
7715 *params = attrib->integer();
7716 break;
7717 default:
7718 NOTREACHED();
7719 break;
7723 void GLES2DecoderImpl::DoGetTexParameterfv(
7724 GLenum target, GLenum pname, GLfloat* params) {
7725 InitTextureMaxAnisotropyIfNeeded(target, pname);
7726 glGetTexParameterfv(target, pname, params);
7729 void GLES2DecoderImpl::DoGetTexParameteriv(
7730 GLenum target, GLenum pname, GLint* params) {
7731 InitTextureMaxAnisotropyIfNeeded(target, pname);
7732 glGetTexParameteriv(target, pname, params);
7735 void GLES2DecoderImpl::InitTextureMaxAnisotropyIfNeeded(
7736 GLenum target, GLenum pname) {
7737 if (!workarounds().init_texture_max_anisotropy)
7738 return;
7739 if (pname != GL_TEXTURE_MAX_ANISOTROPY_EXT ||
7740 !validators_->texture_parameter.IsValid(pname)) {
7741 return;
7744 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
7745 &state_, target);
7746 if (!texture_ref) {
7747 LOCAL_SET_GL_ERROR(
7748 GL_INVALID_OPERATION,
7749 "glGetTexParamter{fi}v", "unknown texture for target");
7750 return;
7752 Texture* texture = texture_ref->texture();
7753 texture->InitTextureMaxAnisotropyIfNeeded(target);
7756 template <typename T>
7757 void GLES2DecoderImpl::DoGetVertexAttribImpl(
7758 GLuint index, GLenum pname, T* params) {
7759 VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(index);
7760 if (!attrib) {
7761 LOCAL_SET_GL_ERROR(
7762 GL_INVALID_VALUE, "glGetVertexAttrib", "index out of range");
7763 return;
7765 switch (pname) {
7766 case GL_CURRENT_VERTEX_ATTRIB:
7767 state_.attrib_values[index].GetValues(params);
7768 break;
7769 default: {
7770 GLint value = 0;
7771 GetVertexAttribHelper(attrib, pname, &value);
7772 *params = static_cast<T>(value);
7773 break;
7778 void GLES2DecoderImpl::DoGetVertexAttribfv(
7779 GLuint index, GLenum pname, GLfloat* params) {
7780 DoGetVertexAttribImpl<GLfloat>(index, pname, params);
7783 void GLES2DecoderImpl::DoGetVertexAttribiv(
7784 GLuint index, GLenum pname, GLint* params) {
7785 DoGetVertexAttribImpl<GLint>(index, pname, params);
7788 void GLES2DecoderImpl::DoGetVertexAttribIiv(
7789 GLuint index, GLenum pname, GLint* params) {
7790 DoGetVertexAttribImpl<GLint>(index, pname, params);
7793 void GLES2DecoderImpl::DoGetVertexAttribIuiv(
7794 GLuint index, GLenum pname, GLuint* params) {
7795 DoGetVertexAttribImpl<GLuint>(index, pname, params);
7798 template <typename T>
7799 bool GLES2DecoderImpl::SetVertexAttribValue(
7800 const char* function_name, GLuint index, const T* value) {
7801 if (index >= state_.attrib_values.size()) {
7802 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "index out of range");
7803 return false;
7805 state_.attrib_values[index].SetValues(value);
7806 return true;
7809 void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
7810 GLfloat v[4] = { v0, 0.0f, 0.0f, 1.0f, };
7811 if (SetVertexAttribValue("glVertexAttrib1f", index, v)) {
7812 glVertexAttrib1f(index, v0);
7816 void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
7817 GLfloat v[4] = { v0, v1, 0.0f, 1.0f, };
7818 if (SetVertexAttribValue("glVertexAttrib2f", index, v)) {
7819 glVertexAttrib2f(index, v0, v1);
7823 void GLES2DecoderImpl::DoVertexAttrib3f(
7824 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
7825 GLfloat v[4] = { v0, v1, v2, 1.0f, };
7826 if (SetVertexAttribValue("glVertexAttrib3f", index, v)) {
7827 glVertexAttrib3f(index, v0, v1, v2);
7831 void GLES2DecoderImpl::DoVertexAttrib4f(
7832 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
7833 GLfloat v[4] = { v0, v1, v2, v3, };
7834 if (SetVertexAttribValue("glVertexAttrib4f", index, v)) {
7835 glVertexAttrib4f(index, v0, v1, v2, v3);
7839 void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
7840 GLfloat t[4] = { v[0], 0.0f, 0.0f, 1.0f, };
7841 if (SetVertexAttribValue("glVertexAttrib1fv", index, t)) {
7842 glVertexAttrib1fv(index, v);
7846 void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
7847 GLfloat t[4] = { v[0], v[1], 0.0f, 1.0f, };
7848 if (SetVertexAttribValue("glVertexAttrib2fv", index, t)) {
7849 glVertexAttrib2fv(index, v);
7853 void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
7854 GLfloat t[4] = { v[0], v[1], v[2], 1.0f, };
7855 if (SetVertexAttribValue("glVertexAttrib3fv", index, t)) {
7856 glVertexAttrib3fv(index, v);
7860 void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
7861 if (SetVertexAttribValue("glVertexAttrib4fv", index, v)) {
7862 glVertexAttrib4fv(index, v);
7866 void GLES2DecoderImpl::DoVertexAttribI4i(
7867 GLuint index, GLint v0, GLint v1, GLint v2, GLint v3) {
7868 GLint v[4] = { v0, v1, v2, v3 };
7869 if (SetVertexAttribValue("glVertexAttribI4i", index, v)) {
7870 glVertexAttribI4i(index, v0, v1, v2, v3);
7874 void GLES2DecoderImpl::DoVertexAttribI4iv(GLuint index, const GLint* v) {
7875 if (SetVertexAttribValue("glVertexAttribI4iv", index, v)) {
7876 glVertexAttribI4iv(index, v);
7880 void GLES2DecoderImpl::DoVertexAttribI4ui(
7881 GLuint index, GLuint v0, GLuint v1, GLuint v2, GLuint v3) {
7882 GLuint v[4] = { v0, v1, v2, v3 };
7883 if (SetVertexAttribValue("glVertexAttribI4ui", index, v)) {
7884 glVertexAttribI4ui(index, v0, v1, v2, v3);
7888 void GLES2DecoderImpl::DoVertexAttribI4uiv(GLuint index, const GLuint* v) {
7889 if (SetVertexAttribValue("glVertexAttribI4uiv", index, v)) {
7890 glVertexAttribI4uiv(index, v);
7894 error::Error GLES2DecoderImpl::HandleVertexAttribIPointer(
7895 uint32 immediate_data_size,
7896 const void* cmd_data) {
7897 if (!unsafe_es3_apis_enabled())
7898 return error::kUnknownCommand;
7899 const gles2::cmds::VertexAttribIPointer& c =
7900 *static_cast<const gles2::cmds::VertexAttribIPointer*>(cmd_data);
7902 if (!state_.bound_array_buffer.get() ||
7903 state_.bound_array_buffer->IsDeleted()) {
7904 if (state_.vertex_attrib_manager.get() ==
7905 state_.default_vertex_attrib_manager.get()) {
7906 LOCAL_SET_GL_ERROR(
7907 GL_INVALID_VALUE, "glVertexAttribIPointer", "no array buffer bound");
7908 return error::kNoError;
7909 } else if (c.offset != 0) {
7910 LOCAL_SET_GL_ERROR(
7911 GL_INVALID_VALUE,
7912 "glVertexAttribIPointer", "client side arrays are not allowed");
7913 return error::kNoError;
7917 GLuint indx = c.indx;
7918 GLint size = c.size;
7919 GLenum type = c.type;
7920 GLsizei stride = c.stride;
7921 GLsizei offset = c.offset;
7922 const void* ptr = reinterpret_cast<const void*>(offset);
7923 if (!validators_->vertex_attrib_i_type.IsValid(type)) {
7924 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribIPointer", type, "type");
7925 return error::kNoError;
7927 if (!validators_->vertex_attrib_size.IsValid(size)) {
7928 LOCAL_SET_GL_ERROR(
7929 GL_INVALID_VALUE, "glVertexAttribIPointer", "size GL_INVALID_VALUE");
7930 return error::kNoError;
7932 if (indx >= group_->max_vertex_attribs()) {
7933 LOCAL_SET_GL_ERROR(
7934 GL_INVALID_VALUE, "glVertexAttribIPointer", "index out of range");
7935 return error::kNoError;
7937 if (stride < 0) {
7938 LOCAL_SET_GL_ERROR(
7939 GL_INVALID_VALUE, "glVertexAttribIPointer", "stride < 0");
7940 return error::kNoError;
7942 if (stride > 255) {
7943 LOCAL_SET_GL_ERROR(
7944 GL_INVALID_VALUE, "glVertexAttribIPointer", "stride > 255");
7945 return error::kNoError;
7947 if (offset < 0) {
7948 LOCAL_SET_GL_ERROR(
7949 GL_INVALID_VALUE, "glVertexAttribIPointer", "offset < 0");
7950 return error::kNoError;
7952 GLsizei component_size =
7953 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
7954 // component_size must be a power of two to use & as optimized modulo.
7955 DCHECK(GLES2Util::IsPOT(component_size));
7956 if (offset & (component_size - 1)) {
7957 LOCAL_SET_GL_ERROR(
7958 GL_INVALID_OPERATION,
7959 "glVertexAttribIPointer", "offset not valid for type");
7960 return error::kNoError;
7962 if (stride & (component_size - 1)) {
7963 LOCAL_SET_GL_ERROR(
7964 GL_INVALID_OPERATION,
7965 "glVertexAttribIPointer", "stride not valid for type");
7966 return error::kNoError;
7968 state_.vertex_attrib_manager
7969 ->SetAttribInfo(indx,
7970 state_.bound_array_buffer.get(),
7971 size,
7972 type,
7973 GL_FALSE,
7974 stride,
7975 stride != 0 ? stride : component_size * size,
7976 offset,
7977 GL_TRUE);
7978 glVertexAttribIPointer(indx, size, type, stride, ptr);
7979 return error::kNoError;
7982 error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
7983 uint32 immediate_data_size,
7984 const void* cmd_data) {
7985 const gles2::cmds::VertexAttribPointer& c =
7986 *static_cast<const gles2::cmds::VertexAttribPointer*>(cmd_data);
7988 if (!state_.bound_array_buffer.get() ||
7989 state_.bound_array_buffer->IsDeleted()) {
7990 if (state_.vertex_attrib_manager.get() ==
7991 state_.default_vertex_attrib_manager.get()) {
7992 LOCAL_SET_GL_ERROR(
7993 GL_INVALID_VALUE, "glVertexAttribPointer", "no array buffer bound");
7994 return error::kNoError;
7995 } else if (c.offset != 0) {
7996 LOCAL_SET_GL_ERROR(
7997 GL_INVALID_VALUE,
7998 "glVertexAttribPointer", "client side arrays are not allowed");
7999 return error::kNoError;
8003 GLuint indx = c.indx;
8004 GLint size = c.size;
8005 GLenum type = c.type;
8006 GLboolean normalized = static_cast<GLboolean>(c.normalized);
8007 GLsizei stride = c.stride;
8008 GLsizei offset = c.offset;
8009 const void* ptr = reinterpret_cast<const void*>(offset);
8010 if (!validators_->vertex_attrib_type.IsValid(type)) {
8011 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribPointer", type, "type");
8012 return error::kNoError;
8014 if (!validators_->vertex_attrib_size.IsValid(size)) {
8015 LOCAL_SET_GL_ERROR(
8016 GL_INVALID_VALUE, "glVertexAttribPointer", "size GL_INVALID_VALUE");
8017 return error::kNoError;
8019 if (indx >= group_->max_vertex_attribs()) {
8020 LOCAL_SET_GL_ERROR(
8021 GL_INVALID_VALUE, "glVertexAttribPointer", "index out of range");
8022 return error::kNoError;
8024 if (stride < 0) {
8025 LOCAL_SET_GL_ERROR(
8026 GL_INVALID_VALUE, "glVertexAttribPointer", "stride < 0");
8027 return error::kNoError;
8029 if (stride > 255) {
8030 LOCAL_SET_GL_ERROR(
8031 GL_INVALID_VALUE, "glVertexAttribPointer", "stride > 255");
8032 return error::kNoError;
8034 if (offset < 0) {
8035 LOCAL_SET_GL_ERROR(
8036 GL_INVALID_VALUE, "glVertexAttribPointer", "offset < 0");
8037 return error::kNoError;
8039 GLsizei component_size =
8040 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
8041 // component_size must be a power of two to use & as optimized modulo.
8042 DCHECK(GLES2Util::IsPOT(component_size));
8043 if (offset & (component_size - 1)) {
8044 LOCAL_SET_GL_ERROR(
8045 GL_INVALID_OPERATION,
8046 "glVertexAttribPointer", "offset not valid for type");
8047 return error::kNoError;
8049 if (stride & (component_size - 1)) {
8050 LOCAL_SET_GL_ERROR(
8051 GL_INVALID_OPERATION,
8052 "glVertexAttribPointer", "stride not valid for type");
8053 return error::kNoError;
8055 state_.vertex_attrib_manager
8056 ->SetAttribInfo(indx,
8057 state_.bound_array_buffer.get(),
8058 size,
8059 type,
8060 normalized,
8061 stride,
8062 stride != 0 ? stride : component_size * size,
8063 offset,
8064 GL_FALSE);
8065 // We support GL_FIXED natively on EGL/GLES2 implementations
8066 if (type != GL_FIXED || feature_info_->gl_version_info().is_es) {
8067 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
8069 return error::kNoError;
8072 void GLES2DecoderImpl::DoViewport(GLint x, GLint y, GLsizei width,
8073 GLsizei height) {
8074 state_.viewport_x = x;
8075 state_.viewport_y = y;
8076 state_.viewport_width = std::min(width, viewport_max_width_);
8077 state_.viewport_height = std::min(height, viewport_max_height_);
8078 glViewport(x, y, width, height);
8081 error::Error GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
8082 uint32 immediate_data_size,
8083 const void* cmd_data) {
8084 const gles2::cmds::VertexAttribDivisorANGLE& c =
8085 *static_cast<const gles2::cmds::VertexAttribDivisorANGLE*>(cmd_data);
8086 if (!features().angle_instanced_arrays) {
8087 LOCAL_SET_GL_ERROR(
8088 GL_INVALID_OPERATION,
8089 "glVertexAttribDivisorANGLE", "function not available");
8090 return error::kNoError;
8092 GLuint index = c.index;
8093 GLuint divisor = c.divisor;
8094 if (index >= group_->max_vertex_attribs()) {
8095 LOCAL_SET_GL_ERROR(
8096 GL_INVALID_VALUE,
8097 "glVertexAttribDivisorANGLE", "index out of range");
8098 return error::kNoError;
8101 state_.vertex_attrib_manager->SetDivisor(
8102 index,
8103 divisor);
8104 glVertexAttribDivisorANGLE(index, divisor);
8105 return error::kNoError;
8108 template <typename pixel_data_type>
8109 static void WriteAlphaData(
8110 void* pixels, uint32 row_count, uint32 channel_count,
8111 uint32 alpha_channel_index, uint32 unpadded_row_size,
8112 uint32 padded_row_size, pixel_data_type alpha_value) {
8113 DCHECK_GT(channel_count, 0U);
8114 DCHECK_EQ(unpadded_row_size % sizeof(pixel_data_type), 0U);
8115 uint32 unpadded_row_size_in_elements =
8116 unpadded_row_size / sizeof(pixel_data_type);
8117 DCHECK_EQ(padded_row_size % sizeof(pixel_data_type), 0U);
8118 uint32 padded_row_size_in_elements =
8119 padded_row_size / sizeof(pixel_data_type);
8120 pixel_data_type* dst =
8121 static_cast<pixel_data_type*>(pixels) + alpha_channel_index;
8122 for (uint32 yy = 0; yy < row_count; ++yy) {
8123 pixel_data_type* end = dst + unpadded_row_size_in_elements;
8124 for (pixel_data_type* d = dst; d < end; d += channel_count) {
8125 *d = alpha_value;
8127 dst += padded_row_size_in_elements;
8131 void GLES2DecoderImpl::FinishReadPixels(
8132 const cmds::ReadPixels& c,
8133 GLuint buffer) {
8134 TRACE_EVENT0("gpu", "GLES2DecoderImpl::FinishReadPixels");
8135 GLsizei width = c.width;
8136 GLsizei height = c.height;
8137 GLenum format = c.format;
8138 GLenum type = c.type;
8139 typedef cmds::ReadPixels::Result Result;
8140 uint32 pixels_size;
8141 Result* result = NULL;
8142 if (c.result_shm_id != 0) {
8143 result = GetSharedMemoryAs<Result*>(
8144 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8145 if (!result) {
8146 if (buffer != 0) {
8147 glDeleteBuffersARB(1, &buffer);
8149 return;
8152 GLES2Util::ComputeImageDataSizes(
8153 width, height, 1, format, type, state_.pack_alignment, &pixels_size,
8154 NULL, NULL);
8155 void* pixels = GetSharedMemoryAs<void*>(
8156 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
8157 if (!pixels) {
8158 if (buffer != 0) {
8159 glDeleteBuffersARB(1, &buffer);
8161 return;
8164 if (buffer != 0) {
8165 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
8166 void* data;
8167 if (features().map_buffer_range) {
8168 data = glMapBufferRange(
8169 GL_PIXEL_PACK_BUFFER_ARB, 0, pixels_size, GL_MAP_READ_BIT);
8170 } else {
8171 data = glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
8173 if (!data) {
8174 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glMapBuffer",
8175 "Unable to map memory for readback.");
8176 return;
8178 memcpy(pixels, data, pixels_size);
8179 // GL_PIXEL_PACK_BUFFER_ARB is currently unused, so we don't
8180 // have to restore the state.
8181 glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB);
8182 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
8183 glDeleteBuffersARB(1, &buffer);
8186 if (result != NULL) {
8187 *result = true;
8190 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
8191 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
8192 if ((channels_exist & 0x0008) == 0 &&
8193 workarounds().clear_alpha_in_readpixels) {
8194 // Set the alpha to 255 because some drivers are buggy in this regard.
8195 uint32 temp_size;
8197 uint32 unpadded_row_size;
8198 uint32 padded_row_size;
8199 if (!GLES2Util::ComputeImageDataSizes(
8200 width, 2, 1, format, type, state_.pack_alignment, &temp_size,
8201 &unpadded_row_size, &padded_row_size)) {
8202 return;
8205 uint32 channel_count = 0;
8206 uint32 alpha_channel = 0;
8207 switch (format) {
8208 case GL_RGBA:
8209 case GL_BGRA_EXT:
8210 channel_count = 4;
8211 alpha_channel = 3;
8212 break;
8213 case GL_ALPHA:
8214 channel_count = 1;
8215 alpha_channel = 0;
8216 break;
8219 if (channel_count > 0) {
8220 switch (type) {
8221 case GL_UNSIGNED_BYTE:
8222 WriteAlphaData<uint8>(
8223 pixels, height, channel_count, alpha_channel, unpadded_row_size,
8224 padded_row_size, 0xFF);
8225 break;
8226 case GL_FLOAT:
8227 WriteAlphaData<float>(
8228 pixels, height, channel_count, alpha_channel, unpadded_row_size,
8229 padded_row_size, 1.0f);
8230 break;
8231 case GL_HALF_FLOAT:
8232 WriteAlphaData<uint16>(
8233 pixels, height, channel_count, alpha_channel, unpadded_row_size,
8234 padded_row_size, 0x3C00);
8235 break;
8241 error::Error GLES2DecoderImpl::HandleReadPixels(uint32 immediate_data_size,
8242 const void* cmd_data) {
8243 const gles2::cmds::ReadPixels& c =
8244 *static_cast<const gles2::cmds::ReadPixels*>(cmd_data);
8245 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleReadPixels");
8246 error::Error fbo_error = WillAccessBoundFramebufferForRead();
8247 if (fbo_error != error::kNoError)
8248 return fbo_error;
8249 GLint x = c.x;
8250 GLint y = c.y;
8251 GLsizei width = c.width;
8252 GLsizei height = c.height;
8253 GLenum format = c.format;
8254 GLenum type = c.type;
8255 GLboolean async = static_cast<GLboolean>(c.async);
8256 if (width < 0 || height < 0) {
8257 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glReadPixels", "dimensions < 0");
8258 return error::kNoError;
8260 typedef cmds::ReadPixels::Result Result;
8261 uint32 pixels_size;
8262 if (!GLES2Util::ComputeImageDataSizes(
8263 width, height, 1, format, type, state_.pack_alignment, &pixels_size,
8264 NULL, NULL)) {
8265 return error::kOutOfBounds;
8267 void* pixels = GetSharedMemoryAs<void*>(
8268 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
8269 if (!pixels) {
8270 return error::kOutOfBounds;
8272 Result* result = NULL;
8273 if (c.result_shm_id != 0) {
8274 result = GetSharedMemoryAs<Result*>(
8275 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8276 if (!result) {
8277 return error::kOutOfBounds;
8281 if (!validators_->read_pixel_format.IsValid(format)) {
8282 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", format, "format");
8283 return error::kNoError;
8285 if (!validators_->read_pixel_type.IsValid(type)) {
8286 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", type, "type");
8287 return error::kNoError;
8289 if ((format != GL_RGBA && format != GL_BGRA_EXT && format != GL_RGB &&
8290 format != GL_ALPHA) || type != GL_UNSIGNED_BYTE) {
8291 // format and type are acceptable enums but not guaranteed to be supported
8292 // for this framebuffer. Have to ask gl if they are valid.
8293 GLint preferred_format = 0;
8294 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &preferred_format);
8295 GLint preferred_type = 0;
8296 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &preferred_type);
8297 if (format != static_cast<GLenum>(preferred_format) ||
8298 type != static_cast<GLenum>(preferred_type)) {
8299 LOCAL_SET_GL_ERROR(
8300 GL_INVALID_OPERATION, "glReadPixels", "format and type incompatible "
8301 "with the current read framebuffer");
8302 return error::kNoError;
8305 if (width == 0 || height == 0) {
8306 return error::kNoError;
8309 // Get the size of the current fbo or backbuffer.
8310 gfx::Size max_size = GetBoundReadFrameBufferSize();
8312 int32 max_x;
8313 int32 max_y;
8314 if (!SafeAddInt32(x, width, &max_x) || !SafeAddInt32(y, height, &max_y)) {
8315 LOCAL_SET_GL_ERROR(
8316 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
8317 return error::kNoError;
8320 if (!CheckBoundReadFramebufferColorAttachment("glReadPixels")) {
8321 return error::kNoError;
8324 if (!CheckBoundFramebuffersValid("glReadPixels")) {
8325 return error::kNoError;
8328 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixels");
8330 ScopedResolvedFrameBufferBinder binder(this, false, true);
8332 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
8333 // The user requested an out of range area. Get the results 1 line
8334 // at a time.
8335 uint32 temp_size;
8336 uint32 unpadded_row_size;
8337 uint32 padded_row_size;
8338 if (!GLES2Util::ComputeImageDataSizes(
8339 width, 2, 1, format, type, state_.pack_alignment, &temp_size,
8340 &unpadded_row_size, &padded_row_size)) {
8341 LOCAL_SET_GL_ERROR(
8342 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
8343 return error::kNoError;
8346 GLint dest_x_offset = std::max(-x, 0);
8347 uint32 dest_row_offset;
8348 if (!GLES2Util::ComputeImageDataSizes(
8349 dest_x_offset, 1, 1, format, type, state_.pack_alignment,
8350 &dest_row_offset, NULL, NULL)) {
8351 LOCAL_SET_GL_ERROR(
8352 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
8353 return error::kNoError;
8356 // Copy each row into the larger dest rect.
8357 int8* dst = static_cast<int8*>(pixels);
8358 GLint read_x = std::max(0, x);
8359 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
8360 GLint read_width = read_end_x - read_x;
8361 for (GLint yy = 0; yy < height; ++yy) {
8362 GLint ry = y + yy;
8364 // Clear the row.
8365 memset(dst, 0, unpadded_row_size);
8367 // If the row is in range, copy it.
8368 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
8369 glReadPixels(
8370 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
8372 dst += padded_row_size;
8374 } else {
8375 if (async && features().use_async_readpixels) {
8376 GLuint buffer = 0;
8377 glGenBuffersARB(1, &buffer);
8378 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
8379 // For ANGLE client version 2, GL_STREAM_READ is not available.
8380 const GLenum usage_hint = feature_info_->gl_version_info().is_angle ?
8381 GL_STATIC_DRAW : GL_STREAM_READ;
8382 glBufferData(GL_PIXEL_PACK_BUFFER_ARB, pixels_size, NULL, usage_hint);
8383 GLenum error = glGetError();
8384 if (error == GL_NO_ERROR) {
8385 glReadPixels(x, y, width, height, format, type, 0);
8386 pending_readpixel_fences_.push(linked_ptr<FenceCallback>(
8387 new FenceCallback()));
8388 WaitForReadPixels(base::Bind(
8389 &GLES2DecoderImpl::FinishReadPixels,
8390 base::internal::SupportsWeakPtrBase::StaticAsWeakPtr
8391 <GLES2DecoderImpl>(this),
8392 c, buffer));
8393 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
8394 return error::kNoError;
8395 } else {
8396 // On error, unbind pack buffer and fall through to sync readpixels
8397 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
8398 glDeleteBuffersARB(1, &buffer);
8401 glReadPixels(x, y, width, height, format, type, pixels);
8403 GLenum error = LOCAL_PEEK_GL_ERROR("glReadPixels");
8404 if (error == GL_NO_ERROR) {
8405 if (result != NULL) {
8406 *result = true;
8408 FinishReadPixels(c, 0);
8411 return error::kNoError;
8414 error::Error GLES2DecoderImpl::HandlePixelStorei(uint32 immediate_data_size,
8415 const void* cmd_data) {
8416 const gles2::cmds::PixelStorei& c =
8417 *static_cast<const gles2::cmds::PixelStorei*>(cmd_data);
8418 GLenum pname = c.pname;
8419 GLenum param = c.param;
8420 if (!validators_->pixel_store.IsValid(pname)) {
8421 LOCAL_SET_GL_ERROR_INVALID_ENUM("glPixelStorei", pname, "pname");
8422 return error::kNoError;
8424 switch (pname) {
8425 case GL_PACK_ALIGNMENT:
8426 case GL_UNPACK_ALIGNMENT:
8427 if (!validators_->pixel_store_alignment.IsValid(param)) {
8428 LOCAL_SET_GL_ERROR(
8429 GL_INVALID_VALUE, "glPixelStorei", "param GL_INVALID_VALUE");
8430 return error::kNoError;
8432 break;
8433 case GL_UNPACK_FLIP_Y_CHROMIUM:
8434 unpack_flip_y_ = (param != 0);
8435 return error::kNoError;
8436 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
8437 unpack_premultiply_alpha_ = (param != 0);
8438 return error::kNoError;
8439 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM:
8440 unpack_unpremultiply_alpha_ = (param != 0);
8441 return error::kNoError;
8442 default:
8443 break;
8445 glPixelStorei(pname, param);
8446 switch (pname) {
8447 case GL_PACK_ALIGNMENT:
8448 state_.pack_alignment = param;
8449 break;
8450 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
8451 state_.pack_reverse_row_order = (param != 0);
8452 break;
8453 case GL_UNPACK_ALIGNMENT:
8454 state_.unpack_alignment = param;
8455 break;
8456 default:
8457 // Validation should have prevented us from getting here.
8458 NOTREACHED();
8459 break;
8461 return error::kNoError;
8464 error::Error GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
8465 uint32 immediate_data_size,
8466 const void* cmd_data) {
8467 const gles2::cmds::PostSubBufferCHROMIUM& c =
8468 *static_cast<const gles2::cmds::PostSubBufferCHROMIUM*>(cmd_data);
8469 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
8471 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
8473 if (!supports_post_sub_buffer_) {
8474 LOCAL_SET_GL_ERROR(
8475 GL_INVALID_OPERATION,
8476 "glPostSubBufferCHROMIUM", "command not supported by surface");
8477 return error::kNoError;
8479 bool is_tracing;
8480 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
8481 &is_tracing);
8482 if (is_tracing) {
8483 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
8484 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
8485 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
8486 is_offscreen ? offscreen_size_ : surface_->GetSize());
8488 if (surface_->PostSubBuffer(c.x, c.y, c.width, c.height)) {
8489 return error::kNoError;
8490 } else {
8491 LOG(ERROR) << "Context lost because PostSubBuffer failed.";
8492 return error::kLostContext;
8496 error::Error GLES2DecoderImpl::HandleScheduleOverlayPlaneCHROMIUM(
8497 uint32 immediate_data_size,
8498 const void* cmd_data) {
8499 const gles2::cmds::ScheduleOverlayPlaneCHROMIUM& c =
8500 *static_cast<const gles2::cmds::ScheduleOverlayPlaneCHROMIUM*>(cmd_data);
8501 TextureRef* ref = texture_manager()->GetTexture(c.overlay_texture_id);
8502 if (!ref) {
8503 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
8504 "glScheduleOverlayPlaneCHROMIUM",
8505 "unknown texture");
8506 return error::kNoError;
8508 gfx::GLImage* image =
8509 ref->texture()->GetLevelImage(ref->texture()->target(), 0);
8510 if (!image) {
8511 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
8512 "glScheduleOverlayPlaneCHROMIUM",
8513 "unsupported texture format");
8514 return error::kNoError;
8516 gfx::OverlayTransform transform = GetGFXOverlayTransform(c.plane_transform);
8517 if (transform == gfx::OVERLAY_TRANSFORM_INVALID) {
8518 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM,
8519 "glScheduleOverlayPlaneCHROMIUM",
8520 "invalid transform enum");
8521 return error::kNoError;
8523 if (!surface_->ScheduleOverlayPlane(
8524 c.plane_z_order,
8525 transform,
8526 image,
8527 gfx::Rect(c.bounds_x, c.bounds_y, c.bounds_width, c.bounds_height),
8528 gfx::RectF(c.uv_x, c.uv_y, c.uv_width, c.uv_height))) {
8529 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
8530 "glScheduleOverlayPlaneCHROMIUM",
8531 "failed to schedule overlay");
8533 return error::kNoError;
8536 error::Error GLES2DecoderImpl::GetAttribLocationHelper(
8537 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
8538 const std::string& name_str) {
8539 if (!StringIsValidForGLES(name_str.c_str())) {
8540 LOCAL_SET_GL_ERROR(
8541 GL_INVALID_VALUE, "glGetAttribLocation", "Invalid character");
8542 return error::kNoError;
8544 Program* program = GetProgramInfoNotShader(
8545 client_id, "glGetAttribLocation");
8546 if (!program) {
8547 return error::kNoError;
8549 if (!program->IsValid()) {
8550 LOCAL_SET_GL_ERROR(
8551 GL_INVALID_OPERATION, "glGetAttribLocation", "program not linked");
8552 return error::kNoError;
8554 GLint* location = GetSharedMemoryAs<GLint*>(
8555 location_shm_id, location_shm_offset, sizeof(GLint));
8556 if (!location) {
8557 return error::kOutOfBounds;
8559 // Require the client to init this incase the context is lost and we are no
8560 // longer executing commands.
8561 if (*location != -1) {
8562 return error::kGenericError;
8564 *location = program->GetAttribLocation(name_str);
8565 return error::kNoError;
8568 error::Error GLES2DecoderImpl::HandleGetAttribLocation(
8569 uint32 immediate_data_size,
8570 const void* cmd_data) {
8571 const gles2::cmds::GetAttribLocation& c =
8572 *static_cast<const gles2::cmds::GetAttribLocation*>(cmd_data);
8573 Bucket* bucket = GetBucket(c.name_bucket_id);
8574 if (!bucket) {
8575 return error::kInvalidArguments;
8577 std::string name_str;
8578 if (!bucket->GetAsString(&name_str)) {
8579 return error::kInvalidArguments;
8581 return GetAttribLocationHelper(
8582 c.program, c.location_shm_id, c.location_shm_offset, name_str);
8585 error::Error GLES2DecoderImpl::GetUniformLocationHelper(
8586 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
8587 const std::string& name_str) {
8588 if (!StringIsValidForGLES(name_str.c_str())) {
8589 LOCAL_SET_GL_ERROR(
8590 GL_INVALID_VALUE, "glGetUniformLocation", "Invalid character");
8591 return error::kNoError;
8593 Program* program = GetProgramInfoNotShader(
8594 client_id, "glGetUniformLocation");
8595 if (!program) {
8596 return error::kNoError;
8598 if (!program->IsValid()) {
8599 LOCAL_SET_GL_ERROR(
8600 GL_INVALID_OPERATION, "glGetUniformLocation", "program not linked");
8601 return error::kNoError;
8603 GLint* location = GetSharedMemoryAs<GLint*>(
8604 location_shm_id, location_shm_offset, sizeof(GLint));
8605 if (!location) {
8606 return error::kOutOfBounds;
8608 // Require the client to init this incase the context is lost an we are no
8609 // longer executing commands.
8610 if (*location != -1) {
8611 return error::kGenericError;
8613 *location = program->GetUniformFakeLocation(name_str);
8614 return error::kNoError;
8617 error::Error GLES2DecoderImpl::HandleGetUniformLocation(
8618 uint32 immediate_data_size,
8619 const void* cmd_data) {
8620 const gles2::cmds::GetUniformLocation& c =
8621 *static_cast<const gles2::cmds::GetUniformLocation*>(cmd_data);
8622 Bucket* bucket = GetBucket(c.name_bucket_id);
8623 if (!bucket) {
8624 return error::kInvalidArguments;
8626 std::string name_str;
8627 if (!bucket->GetAsString(&name_str)) {
8628 return error::kInvalidArguments;
8630 return GetUniformLocationHelper(
8631 c.program, c.location_shm_id, c.location_shm_offset, name_str);
8634 error::Error GLES2DecoderImpl::HandleGetUniformIndices(
8635 uint32 immediate_data_size,
8636 const void* cmd_data) {
8637 if (!unsafe_es3_apis_enabled())
8638 return error::kUnknownCommand;
8639 const gles2::cmds::GetUniformIndices& c =
8640 *static_cast<const gles2::cmds::GetUniformIndices*>(cmd_data);
8641 Bucket* bucket = GetBucket(c.names_bucket_id);
8642 if (!bucket) {
8643 return error::kInvalidArguments;
8645 GLsizei count = 0;
8646 std::vector<char*> names;
8647 std::vector<GLint> len;
8648 if (!bucket->GetAsStrings(&count, &names, &len) || count <= 0) {
8649 return error::kInvalidArguments;
8651 typedef cmds::GetUniformIndices::Result Result;
8652 Result* result = GetSharedMemoryAs<Result*>(
8653 c.indices_shm_id, c.indices_shm_offset,
8654 Result::ComputeSize(static_cast<size_t>(count)));
8655 GLuint* indices = result ? result->GetData() : NULL;
8656 if (indices == NULL) {
8657 return error::kOutOfBounds;
8659 // Check that the client initialized the result.
8660 if (result->size != 0) {
8661 return error::kInvalidArguments;
8663 Program* program = GetProgramInfoNotShader(c.program, "glGetUniformIndices");
8664 if (!program) {
8665 return error::kNoError;
8667 GLuint service_id = program->service_id();
8668 GLint link_status = GL_FALSE;
8669 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
8670 if (link_status != GL_TRUE) {
8671 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
8672 "glGetUniformIndices", "program not linked");
8673 return error::kNoError;
8675 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetUniformIndices");
8676 glGetUniformIndices(service_id, count, &names[0], indices);
8677 GLenum error = glGetError();
8678 if (error == GL_NO_ERROR) {
8679 result->SetNumResults(count);
8680 } else {
8681 LOCAL_SET_GL_ERROR(error, "GetUniformIndices", "");
8683 return error::kNoError;
8686 error::Error GLES2DecoderImpl::GetFragDataLocationHelper(
8687 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
8688 const std::string& name_str) {
8689 GLint* location = GetSharedMemoryAs<GLint*>(
8690 location_shm_id, location_shm_offset, sizeof(GLint));
8691 if (!location) {
8692 return error::kOutOfBounds;
8694 // Require the client to init this incase the context is lost and we are no
8695 // longer executing commands.
8696 if (*location != -1) {
8697 return error::kGenericError;
8699 Program* program = GetProgramInfoNotShader(
8700 client_id, "glGetFragDataLocation");
8701 if (!program) {
8702 return error::kNoError;
8704 *location = glGetFragDataLocation(program->service_id(), name_str.c_str());
8705 return error::kNoError;
8708 error::Error GLES2DecoderImpl::HandleGetFragDataLocation(
8709 uint32 immediate_data_size,
8710 const void* cmd_data) {
8711 if (!unsafe_es3_apis_enabled())
8712 return error::kUnknownCommand;
8713 const gles2::cmds::GetFragDataLocation& c =
8714 *static_cast<const gles2::cmds::GetFragDataLocation*>(cmd_data);
8715 Bucket* bucket = GetBucket(c.name_bucket_id);
8716 if (!bucket) {
8717 return error::kInvalidArguments;
8719 std::string name_str;
8720 if (!bucket->GetAsString(&name_str)) {
8721 return error::kInvalidArguments;
8723 return GetFragDataLocationHelper(
8724 c.program, c.location_shm_id, c.location_shm_offset, name_str);
8727 error::Error GLES2DecoderImpl::HandleGetUniformBlockIndex(
8728 uint32 immediate_data_size, const void* cmd_data) {
8729 if (!unsafe_es3_apis_enabled())
8730 return error::kUnknownCommand;
8731 const gles2::cmds::GetUniformBlockIndex& c =
8732 *static_cast<const gles2::cmds::GetUniformBlockIndex*>(cmd_data);
8733 Bucket* bucket = GetBucket(c.name_bucket_id);
8734 if (!bucket) {
8735 return error::kInvalidArguments;
8737 std::string name_str;
8738 if (!bucket->GetAsString(&name_str)) {
8739 return error::kInvalidArguments;
8741 GLuint* index = GetSharedMemoryAs<GLuint*>(
8742 c.index_shm_id, c.index_shm_offset, sizeof(GLuint));
8743 if (!index) {
8744 return error::kOutOfBounds;
8746 // Require the client to init this in case the context is lost and we are no
8747 // longer executing commands.
8748 if (*index != GL_INVALID_INDEX) {
8749 return error::kGenericError;
8751 Program* program = GetProgramInfoNotShader(
8752 c.program, "glGetUniformBlockIndex");
8753 if (!program) {
8754 return error::kNoError;
8756 *index = glGetUniformBlockIndex(program->service_id(), name_str.c_str());
8757 return error::kNoError;
8760 error::Error GLES2DecoderImpl::HandleGetString(uint32 immediate_data_size,
8761 const void* cmd_data) {
8762 const gles2::cmds::GetString& c =
8763 *static_cast<const gles2::cmds::GetString*>(cmd_data);
8764 GLenum name = static_cast<GLenum>(c.name);
8765 if (!validators_->string_type.IsValid(name)) {
8766 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetString", name, "name");
8767 return error::kNoError;
8770 const char* str = nullptr;
8771 std::string extensions;
8772 switch (name) {
8773 case GL_VERSION:
8774 str = "OpenGL ES 2.0 Chromium";
8775 break;
8776 case GL_SHADING_LANGUAGE_VERSION:
8777 str = "OpenGL ES GLSL ES 1.0 Chromium";
8778 break;
8779 case GL_RENDERER:
8780 case GL_VENDOR:
8781 // Return the unmasked VENDOR/RENDERER string for WebGL contexts.
8782 // They are used by WEBGL_debug_renderer_info.
8783 if (!force_webgl_glsl_validation_)
8784 str = "Chromium";
8785 else
8786 str = reinterpret_cast<const char*>(glGetString(name));
8787 break;
8788 case GL_EXTENSIONS:
8790 // For WebGL contexts, strip out the OES derivatives and
8791 // EXT frag depth extensions if they have not been enabled.
8792 if (force_webgl_glsl_validation_) {
8793 extensions = feature_info_->extensions();
8794 if (!derivatives_explicitly_enabled_) {
8795 size_t offset = extensions.find(kOESDerivativeExtension);
8796 if (std::string::npos != offset) {
8797 extensions.replace(offset, arraysize(kOESDerivativeExtension),
8798 std::string());
8801 if (!frag_depth_explicitly_enabled_) {
8802 size_t offset = extensions.find(kEXTFragDepthExtension);
8803 if (std::string::npos != offset) {
8804 extensions.replace(offset, arraysize(kEXTFragDepthExtension),
8805 std::string());
8808 if (!draw_buffers_explicitly_enabled_) {
8809 size_t offset = extensions.find(kEXTDrawBuffersExtension);
8810 if (std::string::npos != offset) {
8811 extensions.replace(offset, arraysize(kEXTDrawBuffersExtension),
8812 std::string());
8815 if (!shader_texture_lod_explicitly_enabled_) {
8816 size_t offset = extensions.find(kEXTShaderTextureLodExtension);
8817 if (std::string::npos != offset) {
8818 extensions.replace(offset,
8819 arraysize(kEXTShaderTextureLodExtension),
8820 std::string());
8823 } else {
8824 extensions = feature_info_->extensions().c_str();
8826 if (supports_post_sub_buffer_)
8827 extensions += " GL_CHROMIUM_post_sub_buffer";
8828 str = extensions.c_str();
8830 break;
8831 default:
8832 str = reinterpret_cast<const char*>(glGetString(name));
8833 break;
8835 Bucket* bucket = CreateBucket(c.bucket_id);
8836 bucket->SetFromString(str);
8837 return error::kNoError;
8840 error::Error GLES2DecoderImpl::HandleBufferData(uint32 immediate_data_size,
8841 const void* cmd_data) {
8842 const gles2::cmds::BufferData& c =
8843 *static_cast<const gles2::cmds::BufferData*>(cmd_data);
8844 GLenum target = static_cast<GLenum>(c.target);
8845 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
8846 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
8847 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
8848 GLenum usage = static_cast<GLenum>(c.usage);
8849 const void* data = NULL;
8850 if (data_shm_id != 0 || data_shm_offset != 0) {
8851 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
8852 if (!data) {
8853 return error::kOutOfBounds;
8856 buffer_manager()->ValidateAndDoBufferData(&state_, target, size, data, usage);
8857 return error::kNoError;
8860 void GLES2DecoderImpl::DoBufferSubData(
8861 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
8862 // Just delegate it. Some validation is actually done before this.
8863 buffer_manager()->ValidateAndDoBufferSubData(
8864 &state_, target, offset, size, data);
8867 bool GLES2DecoderImpl::ClearLevel(
8868 Texture* texture,
8869 unsigned target,
8870 int level,
8871 unsigned internal_format,
8872 unsigned format,
8873 unsigned type,
8874 int width,
8875 int height,
8876 bool is_texture_immutable) {
8877 uint32 channels = GLES2Util::GetChannelsForFormat(format);
8878 if (feature_info_->feature_flags().angle_depth_texture &&
8879 (channels & GLES2Util::kDepth) != 0) {
8880 // It's a depth format and ANGLE doesn't allow texImage2D or texSubImage2D
8881 // on depth formats.
8882 GLuint fb = 0;
8883 glGenFramebuffersEXT(1, &fb);
8884 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb);
8886 bool have_stencil = (channels & GLES2Util::kStencil) != 0;
8887 GLenum attachment = have_stencil ? GL_DEPTH_STENCIL_ATTACHMENT :
8888 GL_DEPTH_ATTACHMENT;
8890 glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, attachment, target,
8891 texture->service_id(), level);
8892 // ANGLE promises a depth only attachment ok.
8893 if (glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT) !=
8894 GL_FRAMEBUFFER_COMPLETE) {
8895 return false;
8897 glClearStencil(0);
8898 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
8899 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
8900 glClearDepth(1.0f);
8901 state_.SetDeviceDepthMask(GL_TRUE);
8902 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
8903 glClear(GL_DEPTH_BUFFER_BIT | (have_stencil ? GL_STENCIL_BUFFER_BIT : 0));
8905 RestoreClearState();
8907 glDeleteFramebuffersEXT(1, &fb);
8908 Framebuffer* framebuffer =
8909 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
8910 GLuint fb_service_id =
8911 framebuffer ? framebuffer->service_id() : GetBackbufferServiceId();
8912 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb_service_id);
8913 return true;
8916 static const uint32 kMaxZeroSize = 1024 * 1024 * 4;
8918 uint32 size;
8919 uint32 padded_row_size;
8920 if (!GLES2Util::ComputeImageDataSizes(
8921 width, height, 1, format, type, state_.unpack_alignment, &size,
8922 NULL, &padded_row_size)) {
8923 return false;
8926 TRACE_EVENT1("gpu", "GLES2DecoderImpl::ClearLevel", "size", size);
8928 int tile_height;
8930 if (size > kMaxZeroSize) {
8931 if (kMaxZeroSize < padded_row_size) {
8932 // That'd be an awfully large texture.
8933 return false;
8935 // We should never have a large total size with a zero row size.
8936 DCHECK_GT(padded_row_size, 0U);
8937 tile_height = kMaxZeroSize / padded_row_size;
8938 if (!GLES2Util::ComputeImageDataSizes(
8939 width, tile_height, 1, format, type, state_.unpack_alignment, &size,
8940 NULL, NULL)) {
8941 return false;
8943 } else {
8944 tile_height = height;
8947 // Assumes the size has already been checked.
8948 scoped_ptr<char[]> zero(new char[size]);
8949 memset(zero.get(), 0, size);
8950 glBindTexture(texture->target(), texture->service_id());
8952 bool has_images = texture->HasImages();
8953 GLint y = 0;
8954 while (y < height) {
8955 GLint h = y + tile_height > height ? height - y : tile_height;
8956 if (is_texture_immutable || h != height || has_images) {
8957 glTexSubImage2D(target, level, 0, y, width, h, format, type, zero.get());
8958 } else {
8959 glTexImage2D(
8960 target, level, internal_format, width, h, 0, format, type,
8961 zero.get());
8963 y += tile_height;
8965 TextureRef* bound_texture =
8966 texture_manager()->GetTextureInfoForTarget(&state_, texture->target());
8967 glBindTexture(texture->target(),
8968 bound_texture ? bound_texture->service_id() : 0);
8969 return true;
8972 namespace {
8974 const int kS3TCBlockWidth = 4;
8975 const int kS3TCBlockHeight = 4;
8976 const int kS3TCDXT1BlockSize = 8;
8977 const int kS3TCDXT3AndDXT5BlockSize = 16;
8978 const int kEACAndETC2BlockSize = 4;
8980 bool IsValidDXTSize(GLint level, GLsizei size) {
8981 return (size == 1) ||
8982 (size == 2) || !(size % kS3TCBlockWidth);
8985 bool IsValidPVRTCSize(GLint level, GLsizei size) {
8986 return GLES2Util::IsPOT(size);
8989 } // anonymous namespace.
8991 bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
8992 const char* function_name, GLsizei width, GLsizei height, GLsizei depth,
8993 GLenum format, GLsizei size) {
8994 base::CheckedNumeric<GLsizei> bytes_required(0);
8996 switch (format) {
8997 case GL_ATC_RGB_AMD:
8998 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
8999 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
9000 case GL_ETC1_RGB8_OES:
9001 bytes_required =
9002 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
9003 bytes_required *=
9004 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
9005 bytes_required *= kS3TCDXT1BlockSize;
9006 break;
9007 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
9008 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
9009 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
9010 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
9011 bytes_required =
9012 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
9013 bytes_required *=
9014 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
9015 bytes_required *= kS3TCDXT3AndDXT5BlockSize;
9016 break;
9017 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
9018 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
9019 bytes_required = std::max(width, 8);
9020 bytes_required *= std::max(height, 8);
9021 bytes_required *= 4;
9022 bytes_required += 7;
9023 bytes_required /= 8;
9024 break;
9025 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
9026 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
9027 bytes_required = std::max(width, 16);
9028 bytes_required *= std::max(height, 8);
9029 bytes_required *= 2;
9030 bytes_required += 7;
9031 bytes_required /= 8;
9032 break;
9034 // ES3 formats.
9035 case GL_COMPRESSED_R11_EAC:
9036 case GL_COMPRESSED_SIGNED_R11_EAC:
9037 case GL_COMPRESSED_RGB8_ETC2:
9038 case GL_COMPRESSED_SRGB8_ETC2:
9039 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9040 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9041 bytes_required =
9042 (width + kEACAndETC2BlockSize - 1) / kEACAndETC2BlockSize;
9043 bytes_required *=
9044 (height + kEACAndETC2BlockSize - 1) / kEACAndETC2BlockSize;
9045 bytes_required *= 8;
9046 bytes_required *= depth;
9047 break;
9048 case GL_COMPRESSED_RG11_EAC:
9049 case GL_COMPRESSED_SIGNED_RG11_EAC:
9050 case GL_COMPRESSED_RGBA8_ETC2_EAC:
9051 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
9052 bytes_required =
9053 (width + kEACAndETC2BlockSize - 1) / kEACAndETC2BlockSize;
9054 bytes_required *=
9055 (height + kEACAndETC2BlockSize - 1) / kEACAndETC2BlockSize;
9056 bytes_required *= 16;
9057 bytes_required *= depth;
9058 break;
9059 default:
9060 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, format, "format");
9061 return false;
9064 if (!bytes_required.IsValid() || size != bytes_required.ValueOrDefault(0)) {
9065 LOCAL_SET_GL_ERROR(
9066 GL_INVALID_VALUE, function_name, "size is not correct for dimensions");
9067 return false;
9070 return true;
9073 bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
9074 const char* function_name, GLenum target, GLint level,
9075 GLsizei width, GLsizei height, GLsizei depth, GLenum format) {
9076 switch (format) {
9077 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
9078 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
9079 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
9080 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
9081 DCHECK_EQ(1, depth); // 2D formats.
9082 if (!IsValidDXTSize(level, width) || !IsValidDXTSize(level, height)) {
9083 LOCAL_SET_GL_ERROR(
9084 GL_INVALID_OPERATION, function_name,
9085 "width or height invalid for level");
9086 return false;
9088 return true;
9089 case GL_ATC_RGB_AMD:
9090 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
9091 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
9092 case GL_ETC1_RGB8_OES:
9093 DCHECK_EQ(1, depth); // 2D formats.
9094 if (width <= 0 || height <= 0) {
9095 LOCAL_SET_GL_ERROR(
9096 GL_INVALID_OPERATION, function_name,
9097 "width or height invalid for level");
9098 return false;
9100 return true;
9101 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
9102 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
9103 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
9104 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
9105 DCHECK_EQ(1, depth); // 2D formats.
9106 if (!IsValidPVRTCSize(level, width) ||
9107 !IsValidPVRTCSize(level, height)) {
9108 LOCAL_SET_GL_ERROR(
9109 GL_INVALID_OPERATION, function_name,
9110 "width or height invalid for level");
9111 return false;
9113 return true;
9115 // ES3 formats.
9116 case GL_COMPRESSED_R11_EAC:
9117 case GL_COMPRESSED_SIGNED_R11_EAC:
9118 case GL_COMPRESSED_RG11_EAC:
9119 case GL_COMPRESSED_SIGNED_RG11_EAC:
9120 case GL_COMPRESSED_RGB8_ETC2:
9121 case GL_COMPRESSED_SRGB8_ETC2:
9122 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9123 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9124 case GL_COMPRESSED_RGBA8_ETC2_EAC:
9125 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
9126 if (width <= 0 || height <= 0 || depth <= 0) {
9127 LOCAL_SET_GL_ERROR(
9128 GL_INVALID_OPERATION, function_name,
9129 "width, height, or depth invalid");
9130 return false;
9132 if (target == GL_TEXTURE_3D) {
9133 LOCAL_SET_GL_ERROR(
9134 GL_INVALID_OPERATION, function_name,
9135 "target invalid for format");
9136 return false;
9138 return true;
9139 default:
9140 return false;
9144 bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
9145 const char* function_name,
9146 GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
9147 GLsizei width, GLsizei height, GLsizei depth, GLenum format,
9148 Texture* texture) {
9149 if (xoffset < 0 || yoffset < 0 || zoffset < 0) {
9150 LOCAL_SET_GL_ERROR(
9151 GL_INVALID_VALUE, function_name, "x/y/z offset < 0");
9152 return false;
9155 switch (format) {
9156 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
9157 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
9158 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
9159 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
9160 const int kBlockWidth = 4;
9161 const int kBlockHeight = 4;
9162 if ((xoffset % kBlockWidth) || (yoffset % kBlockHeight)) {
9163 LOCAL_SET_GL_ERROR(
9164 GL_INVALID_OPERATION, function_name,
9165 "xoffset or yoffset not multiple of 4");
9166 return false;
9168 GLsizei tex_width = 0;
9169 GLsizei tex_height = 0;
9170 if (!texture->GetLevelSize(target, level,
9171 &tex_width, &tex_height, nullptr) ||
9172 width - xoffset > tex_width ||
9173 height - yoffset > tex_height) {
9174 LOCAL_SET_GL_ERROR(
9175 GL_INVALID_OPERATION, function_name, "dimensions out of range");
9176 return false;
9178 return ValidateCompressedTexDimensions(
9179 function_name, target, level, width, height, 1, format);
9181 case GL_ATC_RGB_AMD:
9182 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
9183 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD: {
9184 LOCAL_SET_GL_ERROR(
9185 GL_INVALID_OPERATION, function_name,
9186 "not supported for ATC textures");
9187 return false;
9189 case GL_ETC1_RGB8_OES: {
9190 LOCAL_SET_GL_ERROR(
9191 GL_INVALID_OPERATION, function_name,
9192 "not supported for ECT1_RGB8_OES textures");
9193 return false;
9195 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
9196 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
9197 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
9198 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
9199 if ((xoffset != 0) || (yoffset != 0)) {
9200 LOCAL_SET_GL_ERROR(
9201 GL_INVALID_OPERATION, function_name,
9202 "xoffset and yoffset must be zero");
9203 return false;
9205 GLsizei tex_width = 0;
9206 GLsizei tex_height = 0;
9207 if (!texture->GetLevelSize(target, level,
9208 &tex_width, &tex_height, nullptr) ||
9209 width != tex_width ||
9210 height != tex_height) {
9211 LOCAL_SET_GL_ERROR(
9212 GL_INVALID_OPERATION, function_name,
9213 "dimensions must match existing texture level dimensions");
9214 return false;
9216 return ValidateCompressedTexDimensions(
9217 function_name, target, level, width, height, 1, format);
9220 // ES3 formats
9221 case GL_COMPRESSED_R11_EAC:
9222 case GL_COMPRESSED_SIGNED_R11_EAC:
9223 case GL_COMPRESSED_RG11_EAC:
9224 case GL_COMPRESSED_SIGNED_RG11_EAC:
9225 case GL_COMPRESSED_RGB8_ETC2:
9226 case GL_COMPRESSED_SRGB8_ETC2:
9227 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9228 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9229 case GL_COMPRESSED_RGBA8_ETC2_EAC:
9230 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
9232 const int kBlockSize = 4;
9233 GLsizei tex_width, tex_height;
9234 if (target == GL_TEXTURE_3D ||
9235 !texture->GetLevelSize(target, level,
9236 &tex_width, &tex_height, nullptr) ||
9237 (xoffset % kBlockSize) || (yoffset % kBlockSize) ||
9238 ((width % kBlockSize) && xoffset + width != tex_width) ||
9239 ((height % kBlockSize) && yoffset + height != tex_height)) {
9240 LOCAL_SET_GL_ERROR(
9241 GL_INVALID_OPERATION, function_name,
9242 "dimensions must match existing texture level dimensions");
9243 return false;
9245 return true;
9247 default:
9248 return false;
9252 error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
9253 GLenum target,
9254 GLint level,
9255 GLenum internal_format,
9256 GLsizei width,
9257 GLsizei height,
9258 GLint border,
9259 GLsizei image_size,
9260 const void* data) {
9261 if (!validators_->texture_target.IsValid(target)) {
9262 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9263 "glCompressedTexImage2D", target, "target");
9264 return error::kNoError;
9266 if (!validators_->compressed_texture_format.IsValid(
9267 internal_format)) {
9268 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9269 "glCompressedTexImage2D", internal_format, "internal_format");
9270 return error::kNoError;
9272 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
9273 border != 0) {
9274 LOCAL_SET_GL_ERROR(
9275 GL_INVALID_VALUE,
9276 "glCompressedTexImage2D", "dimensions out of range");
9277 return error::kNoError;
9279 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9280 &state_, target);
9281 if (!texture_ref) {
9282 LOCAL_SET_GL_ERROR(
9283 GL_INVALID_VALUE,
9284 "glCompressedTexImage2D", "unknown texture target");
9285 return error::kNoError;
9287 Texture* texture = texture_ref->texture();
9288 if (texture->IsImmutable()) {
9289 LOCAL_SET_GL_ERROR(
9290 GL_INVALID_OPERATION,
9291 "glCompressedTexImage2D", "texture is immutable");
9292 return error::kNoError;
9295 if (!ValidateCompressedTexDimensions("glCompressedTexImage2D", target, level,
9296 width, height, 1, internal_format) ||
9297 !ValidateCompressedTexFuncData("glCompressedTexImage2D", width, height,
9298 1, internal_format, image_size)) {
9299 return error::kNoError;
9302 if (!EnsureGPUMemoryAvailable(image_size)) {
9303 LOCAL_SET_GL_ERROR(
9304 GL_OUT_OF_MEMORY, "glCompressedTexImage2D", "out of memory");
9305 return error::kNoError;
9308 if (texture->IsAttachedToFramebuffer()) {
9309 framebuffer_state_.clear_state_dirty = true;
9312 scoped_ptr<int8[]> zero;
9313 if (!data) {
9314 zero.reset(new int8[image_size]);
9315 memset(zero.get(), 0, image_size);
9316 data = zero.get();
9318 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage2D");
9319 glCompressedTexImage2D(
9320 target, level, internal_format, width, height, border, image_size, data);
9321 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedTexImage2D");
9322 if (error == GL_NO_ERROR) {
9323 texture_manager()->SetLevelInfo(
9324 texture_ref, target, level, internal_format,
9325 width, height, 1, border, 0, 0, true);
9328 // This may be a slow command. Exit command processing to allow for
9329 // context preemption and GPU watchdog checks.
9330 ExitCommandProcessingEarly();
9331 return error::kNoError;
9334 error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
9335 uint32 immediate_data_size,
9336 const void* cmd_data) {
9337 const gles2::cmds::CompressedTexImage2D& c =
9338 *static_cast<const gles2::cmds::CompressedTexImage2D*>(cmd_data);
9339 GLenum target = static_cast<GLenum>(c.target);
9340 GLint level = static_cast<GLint>(c.level);
9341 GLenum internal_format = static_cast<GLenum>(c.internalformat);
9342 GLsizei width = static_cast<GLsizei>(c.width);
9343 GLsizei height = static_cast<GLsizei>(c.height);
9344 GLint border = static_cast<GLint>(c.border);
9345 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
9346 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
9347 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
9348 const void* data = NULL;
9349 if (data_shm_id != 0 || data_shm_offset != 0) {
9350 data = GetSharedMemoryAs<const void*>(
9351 data_shm_id, data_shm_offset, image_size);
9352 if (!data) {
9353 return error::kOutOfBounds;
9356 return DoCompressedTexImage2D(
9357 target, level, internal_format, width, height, border, image_size, data);
9360 error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
9361 uint32 immediate_data_size,
9362 const void* cmd_data) {
9363 const gles2::cmds::CompressedTexImage2DBucket& c =
9364 *static_cast<const gles2::cmds::CompressedTexImage2DBucket*>(cmd_data);
9365 GLenum target = static_cast<GLenum>(c.target);
9366 GLint level = static_cast<GLint>(c.level);
9367 GLenum internal_format = static_cast<GLenum>(c.internalformat);
9368 GLsizei width = static_cast<GLsizei>(c.width);
9369 GLsizei height = static_cast<GLsizei>(c.height);
9370 GLint border = static_cast<GLint>(c.border);
9371 Bucket* bucket = GetBucket(c.bucket_id);
9372 if (!bucket) {
9373 return error::kInvalidArguments;
9375 uint32 data_size = bucket->size();
9376 GLsizei imageSize = data_size;
9377 const void* data = bucket->GetData(0, data_size);
9378 if (!data) {
9379 return error::kInvalidArguments;
9381 return DoCompressedTexImage2D(
9382 target, level, internal_format, width, height, border,
9383 imageSize, data);
9386 error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
9387 uint32 immediate_data_size,
9388 const void* cmd_data) {
9389 const gles2::cmds::CompressedTexSubImage2DBucket& c =
9390 *static_cast<const gles2::cmds::CompressedTexSubImage2DBucket*>(cmd_data);
9391 GLenum target = static_cast<GLenum>(c.target);
9392 GLint level = static_cast<GLint>(c.level);
9393 GLint xoffset = static_cast<GLint>(c.xoffset);
9394 GLint yoffset = static_cast<GLint>(c.yoffset);
9395 GLsizei width = static_cast<GLsizei>(c.width);
9396 GLsizei height = static_cast<GLsizei>(c.height);
9397 GLenum format = static_cast<GLenum>(c.format);
9398 Bucket* bucket = GetBucket(c.bucket_id);
9399 if (!bucket) {
9400 return error::kInvalidArguments;
9402 uint32 data_size = bucket->size();
9403 GLsizei imageSize = data_size;
9404 const void* data = bucket->GetData(0, data_size);
9405 if (!data) {
9406 return error::kInvalidArguments;
9408 if (!validators_->texture_target.IsValid(target)) {
9409 LOCAL_SET_GL_ERROR(
9410 GL_INVALID_ENUM, "glCompressedTexSubImage2D", "target");
9411 return error::kNoError;
9413 if (!validators_->compressed_texture_format.IsValid(format)) {
9414 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9415 "glCompressedTexSubImage2D", format, "format");
9416 return error::kNoError;
9418 if (width < 0) {
9419 LOCAL_SET_GL_ERROR(
9420 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "width < 0");
9421 return error::kNoError;
9423 if (height < 0) {
9424 LOCAL_SET_GL_ERROR(
9425 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "height < 0");
9426 return error::kNoError;
9428 if (imageSize < 0) {
9429 LOCAL_SET_GL_ERROR(
9430 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "imageSize < 0");
9431 return error::kNoError;
9433 DoCompressedTexSubImage2D(
9434 target, level, xoffset, yoffset, width, height, format, imageSize, data);
9435 return error::kNoError;
9438 error::Error GLES2DecoderImpl::DoCompressedTexImage3D(
9439 GLenum target,
9440 GLint level,
9441 GLenum internal_format,
9442 GLsizei width,
9443 GLsizei height,
9444 GLsizei depth,
9445 GLint border,
9446 GLsizei image_size,
9447 const void* data) {
9448 if (!validators_->texture_3_d_target.IsValid(target)) {
9449 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9450 "glCompressedTexImage3D", target, "target");
9451 return error::kNoError;
9453 if (!validators_->compressed_texture_format.IsValid(
9454 internal_format)) {
9455 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9456 "glCompressedTexImage3D", internal_format, "internal_format");
9457 return error::kNoError;
9459 if (!texture_manager()->ValidForTarget(target, level, width, height, depth) ||
9460 border != 0) {
9461 LOCAL_SET_GL_ERROR(
9462 GL_INVALID_VALUE,
9463 "glCompressedTexImage3D", "dimensions out of range");
9464 return error::kNoError;
9466 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9467 &state_, target);
9468 if (!texture_ref) {
9469 LOCAL_SET_GL_ERROR(
9470 GL_INVALID_VALUE,
9471 "glCompressedTexImage3D", "unknown texture target");
9472 return error::kNoError;
9474 Texture* texture = texture_ref->texture();
9475 if (texture->IsImmutable()) {
9476 LOCAL_SET_GL_ERROR(
9477 GL_INVALID_OPERATION,
9478 "glCompressedTexImage3D", "texture is immutable");
9479 return error::kNoError;
9482 if (!ValidateCompressedTexDimensions("glCompressedTexImage3D", target, level,
9483 width, height, depth, internal_format) ||
9484 !ValidateCompressedTexFuncData("glCompressedTexImage3D", width, height,
9485 depth, internal_format, image_size)) {
9486 return error::kNoError;
9489 if (!EnsureGPUMemoryAvailable(image_size)) {
9490 LOCAL_SET_GL_ERROR(
9491 GL_OUT_OF_MEMORY, "glCompressedTexImage3D", "out of memory");
9492 return error::kNoError;
9495 if (texture->IsAttachedToFramebuffer()) {
9496 framebuffer_state_.clear_state_dirty = true;
9499 scoped_ptr<int8[]> zero;
9500 if (!data) {
9501 zero.reset(new int8[image_size]);
9502 memset(zero.get(), 0, image_size);
9503 data = zero.get();
9505 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage3D");
9506 glCompressedTexImage3D(target, level, internal_format, width, height, depth,
9507 border, image_size, data);
9508 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedTexImage3D");
9509 if (error == GL_NO_ERROR) {
9510 texture_manager()->SetLevelInfo(
9511 texture_ref, target, level, internal_format,
9512 width, height, depth, border, 0, 0, true);
9515 // This may be a slow command. Exit command processing to allow for
9516 // context preemption and GPU watchdog checks.
9517 ExitCommandProcessingEarly();
9518 return error::kNoError;
9521 error::Error GLES2DecoderImpl::HandleCompressedTexImage3D(
9522 uint32 immediate_data_size, const void* cmd_data) {
9523 if (!unsafe_es3_apis_enabled())
9524 return error::kUnknownCommand;
9526 const gles2::cmds::CompressedTexImage3D& c =
9527 *static_cast<const gles2::cmds::CompressedTexImage3D*>(cmd_data);
9528 GLenum target = static_cast<GLenum>(c.target);
9529 GLint level = static_cast<GLint>(c.level);
9530 GLenum internal_format = static_cast<GLenum>(c.internalformat);
9531 GLsizei width = static_cast<GLsizei>(c.width);
9532 GLsizei height = static_cast<GLsizei>(c.height);
9533 GLsizei depth = static_cast<GLsizei>(c.depth);
9534 GLint border = static_cast<GLint>(c.border);
9535 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
9536 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
9537 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
9538 const void* data = NULL;
9539 if (data_shm_id != 0 || data_shm_offset != 0) {
9540 data = GetSharedMemoryAs<const void*>(
9541 data_shm_id, data_shm_offset, image_size);
9542 if (!data) {
9543 return error::kOutOfBounds;
9546 return DoCompressedTexImage3D(target, level, internal_format, width, height,
9547 depth, border, image_size, data);
9550 error::Error GLES2DecoderImpl::HandleCompressedTexImage3DBucket(
9551 uint32 immediate_data_size, const void* cmd_data) {
9552 if (!unsafe_es3_apis_enabled())
9553 return error::kUnknownCommand;
9555 const gles2::cmds::CompressedTexImage3DBucket& c =
9556 *static_cast<const gles2::cmds::CompressedTexImage3DBucket*>(cmd_data);
9557 GLenum target = static_cast<GLenum>(c.target);
9558 GLint level = static_cast<GLint>(c.level);
9559 GLenum internal_format = static_cast<GLenum>(c.internalformat);
9560 GLsizei width = static_cast<GLsizei>(c.width);
9561 GLsizei height = static_cast<GLsizei>(c.height);
9562 GLsizei depth = static_cast<GLsizei>(c.depth);
9563 GLint border = static_cast<GLint>(c.border);
9564 Bucket* bucket = GetBucket(c.bucket_id);
9565 if (!bucket) {
9566 return error::kInvalidArguments;
9568 uint32 data_size = bucket->size();
9569 GLsizei imageSize = data_size;
9570 const void* data = bucket->GetData(0, data_size);
9571 if (!data) {
9572 return error::kInvalidArguments;
9574 return DoCompressedTexImage3D(target, level, internal_format, width, height,
9575 depth, border, imageSize, data);
9578 void GLES2DecoderImpl::DoCompressedTexSubImage3D(
9579 GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
9580 GLsizei width, GLsizei height, GLsizei depth, GLenum format,
9581 GLsizei image_size, const void* data) {
9582 if (!validators_->texture_3_d_target.IsValid(target)) {
9583 LOCAL_SET_GL_ERROR(
9584 GL_INVALID_ENUM, "glCompressedTexSubImage3D", "target");
9585 return;
9587 if (!validators_->compressed_texture_format.IsValid(format)) {
9588 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9589 "glCompressedTexSubImage3D", format, "format");
9590 return;
9592 if (width < 0 || height < 0 || depth < 0) {
9593 LOCAL_SET_GL_ERROR(
9594 GL_INVALID_VALUE, "glCompressedTexSubImage3D", "size < 0");
9595 return;
9597 if (image_size < 0) {
9598 LOCAL_SET_GL_ERROR(
9599 GL_INVALID_VALUE, "glCompressedTexSubImage3D", "imageSize < 0");
9600 return;
9602 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9603 &state_, target);
9604 if (!texture_ref) {
9605 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCompressedTexSubImage3D",
9606 "unknown texture for target");
9607 return;
9609 Texture* texture = texture_ref->texture();
9610 GLenum type = 0, internal_format = 0;
9611 if (!texture->GetLevelType(target, level, &type, &internal_format)) {
9612 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCompressedTexSubImage3D",
9613 "level does not exist");
9614 return;
9616 if (internal_format != format) {
9617 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCompressedTexSubImage3D",
9618 "format does not match internal format");
9619 return;
9621 if (!texture->ValidForTexture(target, level, xoffset, yoffset, zoffset,
9622 width, height, depth, type)) {
9623 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCompressedTexSubImage3D",
9624 "bad dimensions");
9625 return;
9627 if (!ValidateCompressedTexFuncData("glCompressedTexSubImage3D",
9628 width, height, depth, format,
9629 image_size) ||
9630 !ValidateCompressedTexSubDimensions("glCompressedTexSubImage3D",
9631 target, level, xoffset, yoffset,
9632 zoffset, width, height, depth,
9633 format, texture)) {
9634 return;
9637 // Note: There is no need to deal with texture cleared tracking here
9638 // because the validation above means you can only get here if the level
9639 // is already a matching compressed format and in that case
9640 // CompressedTexImage3D already cleared the texture.
9641 glCompressedTexSubImage3D(
9642 target, level, xoffset, yoffset, zoffset, width, height, depth, format,
9643 image_size, data);
9645 // This may be a slow command. Exit command processing to allow for
9646 // context preemption and GPU watchdog checks.
9647 ExitCommandProcessingEarly();
9650 error::Error GLES2DecoderImpl::HandleCompressedTexSubImage3DBucket(
9651 uint32 immediate_data_size, const void* cmd_data) {
9652 if (!unsafe_es3_apis_enabled())
9653 return error::kUnknownCommand;
9654 const gles2::cmds::CompressedTexSubImage3DBucket& c =
9655 *static_cast<const gles2::cmds::CompressedTexSubImage3DBucket*>(cmd_data);
9656 GLenum target = static_cast<GLenum>(c.target);
9657 GLint level = static_cast<GLint>(c.level);
9658 GLint xoffset = static_cast<GLint>(c.xoffset);
9659 GLint yoffset = static_cast<GLint>(c.yoffset);
9660 GLint zoffset = static_cast<GLint>(c.zoffset);
9661 GLsizei width = static_cast<GLsizei>(c.width);
9662 GLsizei height = static_cast<GLsizei>(c.height);
9663 GLsizei depth = static_cast<GLsizei>(c.depth);
9664 GLenum format = static_cast<GLenum>(c.format);
9665 Bucket* bucket = GetBucket(c.bucket_id);
9666 if (!bucket) {
9667 return error::kInvalidArguments;
9669 uint32 data_size = bucket->size();
9670 GLsizei image_size = data_size;
9671 const void* data = bucket->GetData(0, data_size);
9672 if (!data) {
9673 return error::kInvalidArguments;
9675 DoCompressedTexSubImage3D(
9676 target, level, xoffset, yoffset, zoffset, width, height, depth, format,
9677 image_size, data);
9678 return error::kNoError;
9681 error::Error GLES2DecoderImpl::HandleTexImage2D(uint32 immediate_data_size,
9682 const void* cmd_data) {
9683 const gles2::cmds::TexImage2D& c =
9684 *static_cast<const gles2::cmds::TexImage2D*>(cmd_data);
9685 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage2D",
9686 "width", c.width, "height", c.height);
9687 // Set as failed for now, but if it successed, this will be set to not failed.
9688 texture_state_.tex_image_failed = true;
9689 GLenum target = static_cast<GLenum>(c.target);
9690 GLint level = static_cast<GLint>(c.level);
9691 // TODO(kloveless): Change TexImage2D command to use unsigned integer
9692 // for internalformat.
9693 GLenum internal_format = static_cast<GLenum>(c.internalformat);
9694 GLsizei width = static_cast<GLsizei>(c.width);
9695 GLsizei height = static_cast<GLsizei>(c.height);
9696 GLint border = static_cast<GLint>(c.border);
9697 GLenum format = static_cast<GLenum>(c.format);
9698 GLenum type = static_cast<GLenum>(c.type);
9699 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
9700 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
9701 uint32 pixels_size;
9702 if (!GLES2Util::ComputeImageDataSizes(
9703 width, height, 1, format, type, state_.unpack_alignment, &pixels_size,
9704 NULL, NULL)) {
9705 return error::kOutOfBounds;
9707 const void* pixels = NULL;
9708 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
9709 pixels = GetSharedMemoryAs<const void*>(
9710 pixels_shm_id, pixels_shm_offset, pixels_size);
9711 if (!pixels) {
9712 return error::kOutOfBounds;
9716 // For testing only. Allows us to stress the ability to respond to OOM errors.
9717 if (workarounds().simulate_out_of_memory_on_large_textures &&
9718 (width * height >= 4096 * 4096)) {
9719 LOCAL_SET_GL_ERROR(
9720 GL_OUT_OF_MEMORY,
9721 "glTexImage2D", "synthetic out of memory");
9722 return error::kNoError;
9725 TextureManager::DoTexImageArguments args = {
9726 target, level, internal_format, width, height, 1, border, format, type,
9727 pixels, pixels_size, TextureManager::DoTexImageArguments::kTexImage2D };
9728 texture_manager()->ValidateAndDoTexImage(
9729 &texture_state_, &state_, &framebuffer_state_, "glTexImage2D", args);
9731 // This may be a slow command. Exit command processing to allow for
9732 // context preemption and GPU watchdog checks.
9733 ExitCommandProcessingEarly();
9734 return error::kNoError;
9737 error::Error GLES2DecoderImpl::HandleTexImage3D(uint32 immediate_data_size,
9738 const void* cmd_data) {
9739 if (!unsafe_es3_apis_enabled())
9740 return error::kUnknownCommand;
9742 const gles2::cmds::TexImage3D& c =
9743 *static_cast<const gles2::cmds::TexImage3D*>(cmd_data);
9744 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage3D",
9745 "widthXheight", c.width * c.height, "depth", c.depth);
9746 // Set as failed for now, but if it successed, this will be set to not failed.
9747 texture_state_.tex_image_failed = true;
9748 GLenum target = static_cast<GLenum>(c.target);
9749 GLint level = static_cast<GLint>(c.level);
9750 GLenum internal_format = static_cast<GLenum>(c.internalformat);
9751 GLsizei width = static_cast<GLsizei>(c.width);
9752 GLsizei height = static_cast<GLsizei>(c.height);
9753 GLsizei depth = static_cast<GLsizei>(c.depth);
9754 GLint border = static_cast<GLint>(c.border);
9755 GLenum format = static_cast<GLenum>(c.format);
9756 GLenum type = static_cast<GLenum>(c.type);
9757 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
9758 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
9759 uint32 pixels_size;
9760 if (!GLES2Util::ComputeImageDataSizes(
9761 width, height, depth, format, type, state_.unpack_alignment, &pixels_size,
9762 NULL, NULL)) {
9763 return error::kOutOfBounds;
9765 const void* pixels = NULL;
9766 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
9767 pixels = GetSharedMemoryAs<const void*>(
9768 pixels_shm_id, pixels_shm_offset, pixels_size);
9769 if (!pixels) {
9770 return error::kOutOfBounds;
9774 // For testing only. Allows us to stress the ability to respond to OOM errors.
9775 if (workarounds().simulate_out_of_memory_on_large_textures &&
9776 (width * height * depth >= 4096 * 4096)) {
9777 LOCAL_SET_GL_ERROR(
9778 GL_OUT_OF_MEMORY,
9779 "glTexImage3D", "synthetic out of memory");
9780 return error::kNoError;
9783 TextureManager::DoTexImageArguments args = {
9784 target, level, internal_format, width, height, depth, border, format, type,
9785 pixels, pixels_size, TextureManager::DoTexImageArguments::kTexImage3D };
9786 texture_manager()->ValidateAndDoTexImage(
9787 &texture_state_, &state_, &framebuffer_state_, "glTexImage3D", args);
9789 // This may be a slow command. Exit command processing to allow for
9790 // context preemption and GPU watchdog checks.
9791 ExitCommandProcessingEarly();
9792 return error::kNoError;
9795 void GLES2DecoderImpl::DoCompressedTexSubImage2D(
9796 GLenum target,
9797 GLint level,
9798 GLint xoffset,
9799 GLint yoffset,
9800 GLsizei width,
9801 GLsizei height,
9802 GLenum format,
9803 GLsizei image_size,
9804 const void * data) {
9805 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9806 &state_, target);
9807 if (!texture_ref) {
9808 LOCAL_SET_GL_ERROR(
9809 GL_INVALID_OPERATION,
9810 "glCompressedTexSubImage2D", "unknown texture for target");
9811 return;
9813 Texture* texture = texture_ref->texture();
9814 GLenum type = 0;
9815 GLenum internal_format = 0;
9816 if (!texture->GetLevelType(target, level, &type, &internal_format)) {
9817 LOCAL_SET_GL_ERROR(
9818 GL_INVALID_OPERATION,
9819 "glCompressedTexSubImage2D", "level does not exist.");
9820 return;
9822 if (internal_format != format) {
9823 LOCAL_SET_GL_ERROR(
9824 GL_INVALID_OPERATION,
9825 "glCompressedTexSubImage2D", "format does not match internal format.");
9826 return;
9828 if (!texture->ValidForTexture(target, level, xoffset, yoffset, 0, width,
9829 height, 1, type)) {
9830 LOCAL_SET_GL_ERROR(
9831 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "bad dimensions.");
9832 return;
9835 if (!ValidateCompressedTexFuncData("glCompressedTexSubImage2D",
9836 width, height, 1, format, image_size) ||
9837 !ValidateCompressedTexSubDimensions("glCompressedTexSubImage2D",
9838 target, level, xoffset, yoffset, 0,
9839 width, height, 1, format, texture)) {
9840 return;
9844 // Note: There is no need to deal with texture cleared tracking here
9845 // because the validation above means you can only get here if the level
9846 // is already a matching compressed format and in that case
9847 // CompressedTexImage2D already cleared the texture.
9848 glCompressedTexSubImage2D(
9849 target, level, xoffset, yoffset, width, height, format, image_size, data);
9851 // This may be a slow command. Exit command processing to allow for
9852 // context preemption and GPU watchdog checks.
9853 ExitCommandProcessingEarly();
9856 static void Clip(
9857 GLint start, GLint range, GLint sourceRange,
9858 GLint* out_start, GLint* out_range) {
9859 DCHECK(out_start);
9860 DCHECK(out_range);
9861 if (start < 0) {
9862 range += start;
9863 start = 0;
9865 GLint end = start + range;
9866 if (end > sourceRange) {
9867 range -= end - sourceRange;
9869 *out_start = start;
9870 *out_range = range;
9873 void GLES2DecoderImpl::DoCopyTexImage2D(
9874 GLenum target,
9875 GLint level,
9876 GLenum internal_format,
9877 GLint x,
9878 GLint y,
9879 GLsizei width,
9880 GLsizei height,
9881 GLint border) {
9882 DCHECK(!ShouldDeferReads());
9883 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9884 &state_, target);
9885 if (!texture_ref) {
9886 LOCAL_SET_GL_ERROR(
9887 GL_INVALID_OPERATION,
9888 "glCopyTexImage2D", "unknown texture for target");
9889 return;
9891 Texture* texture = texture_ref->texture();
9892 if (texture->IsImmutable()) {
9893 LOCAL_SET_GL_ERROR(
9894 GL_INVALID_OPERATION, "glCopyTexImage2D", "texture is immutable");
9895 return;
9897 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
9898 border != 0) {
9899 LOCAL_SET_GL_ERROR(
9900 GL_INVALID_VALUE, "glCopyTexImage2D", "dimensions out of range");
9901 return;
9903 if (!texture_manager()->ValidateFormatAndTypeCombination(
9904 state_.GetErrorState(), "glCopyTexImage2D", internal_format,
9905 GL_UNSIGNED_BYTE)) {
9906 return;
9909 // Check we have compatible formats.
9910 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
9911 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
9912 uint32 channels_needed = GLES2Util::GetChannelsForFormat(internal_format);
9914 if ((channels_needed & channels_exist) != channels_needed) {
9915 LOCAL_SET_GL_ERROR(
9916 GL_INVALID_OPERATION, "glCopyTexImage2D", "incompatible format");
9917 return;
9920 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
9921 LOCAL_SET_GL_ERROR(
9922 GL_INVALID_OPERATION,
9923 "glCopyTexImage2D", "can not be used with depth or stencil textures");
9924 return;
9927 uint32 estimated_size = 0;
9928 if (!GLES2Util::ComputeImageDataSizes(
9929 width, height, 1, internal_format, GL_UNSIGNED_BYTE,
9930 state_.unpack_alignment, &estimated_size, NULL, NULL)) {
9931 LOCAL_SET_GL_ERROR(
9932 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too large");
9933 return;
9936 if (!EnsureGPUMemoryAvailable(estimated_size)) {
9937 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexImage2D", "out of memory");
9938 return;
9941 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexImage2D")) {
9942 return;
9945 if (FormsTextureCopyingFeedbackLoop(texture_ref, level)) {
9946 LOCAL_SET_GL_ERROR(
9947 GL_INVALID_OPERATION,
9948 "glCopyTexImage2D", "source and destination textures are the same");
9949 return;
9952 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
9953 return;
9956 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTexImage2D");
9957 ScopedResolvedFrameBufferBinder binder(this, false, true);
9958 gfx::Size size = GetBoundReadFrameBufferSize();
9960 if (texture->IsAttachedToFramebuffer()) {
9961 framebuffer_state_.clear_state_dirty = true;
9964 // Clip to size to source dimensions
9965 GLint copyX = 0;
9966 GLint copyY = 0;
9967 GLint copyWidth = 0;
9968 GLint copyHeight = 0;
9969 Clip(x, width, size.width(), &copyX, &copyWidth);
9970 Clip(y, height, size.height(), &copyY, &copyHeight);
9972 if (copyX != x ||
9973 copyY != y ||
9974 copyWidth != width ||
9975 copyHeight != height) {
9976 // some part was clipped so clear the texture.
9977 if (!ClearLevel(texture, target, level, internal_format, internal_format,
9978 GL_UNSIGNED_BYTE, width, height, texture->IsImmutable())) {
9979 LOCAL_SET_GL_ERROR(
9980 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too big");
9981 return;
9983 if (copyHeight > 0 && copyWidth > 0) {
9984 GLint dx = copyX - x;
9985 GLint dy = copyY - y;
9986 GLint destX = dx;
9987 GLint destY = dy;
9988 ScopedModifyPixels modify(texture_ref);
9989 glCopyTexSubImage2D(target, level,
9990 destX, destY, copyX, copyY,
9991 copyWidth, copyHeight);
9993 } else {
9994 ScopedModifyPixels modify(texture_ref);
9995 glCopyTexImage2D(target, level, internal_format,
9996 copyX, copyY, copyWidth, copyHeight, border);
9998 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTexImage2D");
9999 if (error == GL_NO_ERROR) {
10000 texture_manager()->SetLevelInfo(
10001 texture_ref, target, level, internal_format, width, height, 1,
10002 border, internal_format, GL_UNSIGNED_BYTE, true);
10005 // This may be a slow command. Exit command processing to allow for
10006 // context preemption and GPU watchdog checks.
10007 ExitCommandProcessingEarly();
10010 void GLES2DecoderImpl::DoCopyTexSubImage2D(
10011 GLenum target,
10012 GLint level,
10013 GLint xoffset,
10014 GLint yoffset,
10015 GLint x,
10016 GLint y,
10017 GLsizei width,
10018 GLsizei height) {
10019 DCHECK(!ShouldDeferReads());
10020 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10021 &state_, target);
10022 if (!texture_ref) {
10023 LOCAL_SET_GL_ERROR(
10024 GL_INVALID_OPERATION,
10025 "glCopyTexSubImage2D", "unknown texture for target");
10026 return;
10028 Texture* texture = texture_ref->texture();
10029 GLenum type = 0;
10030 GLenum format = 0;
10031 if (!texture->GetLevelType(target, level, &type, &format) ||
10032 !texture->ValidForTexture(
10033 target, level, xoffset, yoffset, 0, width, height, 1, type)) {
10034 LOCAL_SET_GL_ERROR(
10035 GL_INVALID_VALUE, "glCopyTexSubImage2D", "bad dimensions.");
10036 return;
10038 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
10039 LOCAL_SET_GL_ERROR(
10040 GL_INVALID_OPERATION,
10041 "glCopyTexSubImage2D", "async upload pending for texture");
10042 return;
10045 // Check we have compatible formats.
10046 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
10047 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
10048 uint32 channels_needed = GLES2Util::GetChannelsForFormat(format);
10050 if (!channels_needed ||
10051 (channels_needed & channels_exist) != channels_needed) {
10052 LOCAL_SET_GL_ERROR(
10053 GL_INVALID_OPERATION, "glCopyTexSubImage2D", "incompatible format");
10054 return;
10057 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
10058 LOCAL_SET_GL_ERROR(
10059 GL_INVALID_OPERATION,
10060 "glCopySubImage2D", "can not be used with depth or stencil textures");
10061 return;
10064 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexSubImage2D")) {
10065 return;
10068 if (FormsTextureCopyingFeedbackLoop(texture_ref, level)) {
10069 LOCAL_SET_GL_ERROR(
10070 GL_INVALID_OPERATION,
10071 "glCopyTexSubImage2D", "source and destination textures are the same");
10072 return;
10075 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
10076 return;
10079 ScopedResolvedFrameBufferBinder binder(this, false, true);
10080 gfx::Size size = GetBoundReadFrameBufferSize();
10081 GLint copyX = 0;
10082 GLint copyY = 0;
10083 GLint copyWidth = 0;
10084 GLint copyHeight = 0;
10085 Clip(x, width, size.width(), &copyX, &copyWidth);
10086 Clip(y, height, size.height(), &copyY, &copyHeight);
10088 if (xoffset != 0 || yoffset != 0 || width != size.width() ||
10089 height != size.height()) {
10090 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target,
10091 level)) {
10092 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexSubImage2D",
10093 "dimensions too big");
10094 return;
10096 } else {
10097 // Write all pixels in below.
10098 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
10101 if (copyX != x ||
10102 copyY != y ||
10103 copyWidth != width ||
10104 copyHeight != height) {
10105 // some part was clipped so clear the sub rect.
10106 uint32 pixels_size = 0;
10107 if (!GLES2Util::ComputeImageDataSizes(
10108 width, height, 1, format, type, state_.unpack_alignment, &pixels_size,
10109 NULL, NULL)) {
10110 LOCAL_SET_GL_ERROR(
10111 GL_INVALID_VALUE, "glCopyTexSubImage2D", "dimensions too large");
10112 return;
10114 scoped_ptr<char[]> zero(new char[pixels_size]);
10115 memset(zero.get(), 0, pixels_size);
10116 ScopedModifyPixels modify(texture_ref);
10117 glTexSubImage2D(
10118 target, level, xoffset, yoffset, width, height,
10119 format, type, zero.get());
10122 if (copyHeight > 0 && copyWidth > 0) {
10123 GLint dx = copyX - x;
10124 GLint dy = copyY - y;
10125 GLint destX = xoffset + dx;
10126 GLint destY = yoffset + dy;
10127 ScopedModifyPixels modify(texture_ref);
10128 glCopyTexSubImage2D(target, level,
10129 destX, destY, copyX, copyY,
10130 copyWidth, copyHeight);
10133 // This may be a slow command. Exit command processing to allow for
10134 // context preemption and GPU watchdog checks.
10135 ExitCommandProcessingEarly();
10138 bool GLES2DecoderImpl::ValidateTexSubImage2D(
10139 error::Error* error,
10140 const char* function_name,
10141 GLenum target,
10142 GLint level,
10143 GLint xoffset,
10144 GLint yoffset,
10145 GLsizei width,
10146 GLsizei height,
10147 GLenum format,
10148 GLenum type,
10149 const void * data) {
10150 (*error) = error::kNoError;
10151 if (!validators_->texture_target.IsValid(target)) {
10152 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
10153 return false;
10155 if (width < 0) {
10156 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "width < 0");
10157 return false;
10159 if (height < 0) {
10160 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "height < 0");
10161 return false;
10163 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10164 &state_, target);
10165 if (!texture_ref) {
10166 LOCAL_SET_GL_ERROR(
10167 GL_INVALID_OPERATION,
10168 function_name, "unknown texture for target");
10169 return false;
10171 Texture* texture = texture_ref->texture();
10172 GLenum current_type = 0;
10173 GLenum internal_format = 0;
10174 if (!texture->GetLevelType(target, level, &current_type, &internal_format)) {
10175 LOCAL_SET_GL_ERROR(
10176 GL_INVALID_OPERATION, function_name, "level does not exist.");
10177 return false;
10179 if (!texture_manager()->ValidateTextureParameters(state_.GetErrorState(),
10180 function_name, format, type, internal_format, level)) {
10181 return false;
10183 if (type != current_type) {
10184 LOCAL_SET_GL_ERROR(
10185 GL_INVALID_OPERATION,
10186 function_name, "type does not match type of texture.");
10187 return false;
10189 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
10190 LOCAL_SET_GL_ERROR(
10191 GL_INVALID_OPERATION,
10192 function_name, "async upload pending for texture");
10193 return false;
10195 if (!texture->ValidForTexture(
10196 target, level, xoffset, yoffset, 0, width, height, 1, type)) {
10197 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "bad dimensions.");
10198 return false;
10200 if ((GLES2Util::GetChannelsForFormat(format) &
10201 (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
10202 LOCAL_SET_GL_ERROR(
10203 GL_INVALID_OPERATION,
10204 function_name, "can not supply data for depth or stencil textures");
10205 return false;
10207 if (data == NULL) {
10208 (*error) = error::kOutOfBounds;
10209 return false;
10211 return true;
10214 error::Error GLES2DecoderImpl::DoTexSubImage2D(
10215 GLenum target,
10216 GLint level,
10217 GLint xoffset,
10218 GLint yoffset,
10219 GLsizei width,
10220 GLsizei height,
10221 GLenum format,
10222 GLenum type,
10223 const void * data) {
10224 error::Error error = error::kNoError;
10225 if (!ValidateTexSubImage2D(&error, "glTexSubImage2D", target, level,
10226 xoffset, yoffset, width, height, format, type, data)) {
10227 return error;
10229 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10230 &state_, target);
10231 Texture* texture = texture_ref->texture();
10232 GLsizei tex_width = 0;
10233 GLsizei tex_height = 0;
10234 bool ok = texture->GetLevelSize(
10235 target, level, &tex_width, &tex_height, nullptr);
10236 DCHECK(ok);
10237 if (xoffset != 0 || yoffset != 0 ||
10238 width != tex_width || height != tex_height) {
10239 if (!texture_manager()->ClearTextureLevel(this, texture_ref,
10240 target, level)) {
10241 LOCAL_SET_GL_ERROR(
10242 GL_OUT_OF_MEMORY, "glTexSubImage2D", "dimensions too big");
10243 return error::kNoError;
10245 ScopedTextureUploadTimer timer(&texture_state_);
10246 glTexSubImage2D(
10247 target, level, xoffset, yoffset, width, height, format, type, data);
10248 return error::kNoError;
10251 if (!texture_state_.texsubimage_faster_than_teximage &&
10252 !texture->IsImmutable() &&
10253 !texture->HasImages()) {
10254 ScopedTextureUploadTimer timer(&texture_state_);
10255 GLenum internal_format;
10256 GLenum tex_type;
10257 texture->GetLevelType(target, level, &tex_type, &internal_format);
10258 // NOTE: In OpenGL ES 2.0 border is always zero. If that changes we'll need
10259 // to look it up.
10260 glTexImage2D(
10261 target, level, internal_format, width, height, 0, format, type, data);
10262 } else {
10263 ScopedTextureUploadTimer timer(&texture_state_);
10264 glTexSubImage2D(
10265 target, level, xoffset, yoffset, width, height, format, type, data);
10267 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
10269 // This may be a slow command. Exit command processing to allow for
10270 // context preemption and GPU watchdog checks.
10271 ExitCommandProcessingEarly();
10272 return error::kNoError;
10275 error::Error GLES2DecoderImpl::HandleTexSubImage2D(uint32 immediate_data_size,
10276 const void* cmd_data) {
10277 const gles2::cmds::TexSubImage2D& c =
10278 *static_cast<const gles2::cmds::TexSubImage2D*>(cmd_data);
10279 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage2D",
10280 "width", c.width, "height", c.height);
10281 GLboolean internal = static_cast<GLboolean>(c.internal);
10282 if (internal == GL_TRUE && texture_state_.tex_image_failed)
10283 return error::kNoError;
10285 GLenum target = static_cast<GLenum>(c.target);
10286 GLint level = static_cast<GLint>(c.level);
10287 GLint xoffset = static_cast<GLint>(c.xoffset);
10288 GLint yoffset = static_cast<GLint>(c.yoffset);
10289 GLsizei width = static_cast<GLsizei>(c.width);
10290 GLsizei height = static_cast<GLsizei>(c.height);
10291 GLenum format = static_cast<GLenum>(c.format);
10292 GLenum type = static_cast<GLenum>(c.type);
10293 uint32 data_size;
10294 if (!GLES2Util::ComputeImageDataSizes(
10295 width, height, 1, format, type, state_.unpack_alignment, &data_size,
10296 NULL, NULL)) {
10297 return error::kOutOfBounds;
10299 const void* pixels = GetSharedMemoryAs<const void*>(
10300 c.pixels_shm_id, c.pixels_shm_offset, data_size);
10301 return DoTexSubImage2D(
10302 target, level, xoffset, yoffset, width, height, format, type, pixels);
10305 error::Error GLES2DecoderImpl::DoTexSubImage3D(
10306 GLenum target,
10307 GLint level,
10308 GLint xoffset,
10309 GLint yoffset,
10310 GLint zoffset,
10311 GLsizei width,
10312 GLsizei height,
10313 GLsizei depth,
10314 GLenum format,
10315 GLenum type,
10316 const void * data) {
10317 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10318 &state_, target);
10319 if (!texture_ref) {
10320 LOCAL_SET_GL_ERROR(
10321 GL_INVALID_ENUM, "glTexSubImage3D", "invalid target");
10324 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexSubImage3D");
10325 ScopedTextureUploadTimer timer(&texture_state_);
10326 glTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height,
10327 depth, format, type, data);
10328 GLenum error = LOCAL_PEEK_GL_ERROR("glTexSubImage3D");
10329 if (error == GL_NO_ERROR) {
10330 // TODO(zmo): This is not 100% correct because only part of the level
10331 // image is cleared.
10332 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
10335 // This may be a slow command. Exit command processing to allow for
10336 // context preemption and GPU watchdog checks.
10337 ExitCommandProcessingEarly();
10338 return error::kNoError;
10341 error::Error GLES2DecoderImpl::HandleTexSubImage3D(uint32 immediate_data_size,
10342 const void* cmd_data) {
10343 if (!unsafe_es3_apis_enabled())
10344 return error::kUnknownCommand;
10346 const gles2::cmds::TexSubImage3D& c =
10347 *static_cast<const gles2::cmds::TexSubImage3D*>(cmd_data);
10348 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage3D",
10349 "widthXheight", c.width * c.height, "depth", c.depth);
10350 GLboolean internal = static_cast<GLboolean>(c.internal);
10351 if (internal == GL_TRUE && texture_state_.tex_image_failed)
10352 return error::kNoError;
10354 GLenum target = static_cast<GLenum>(c.target);
10355 GLint level = static_cast<GLint>(c.level);
10356 GLint xoffset = static_cast<GLint>(c.xoffset);
10357 GLint yoffset = static_cast<GLint>(c.yoffset);
10358 GLint zoffset = static_cast<GLint>(c.zoffset);
10359 GLsizei width = static_cast<GLsizei>(c.width);
10360 GLsizei height = static_cast<GLsizei>(c.height);
10361 GLsizei depth = static_cast<GLsizei>(c.depth);
10362 GLenum format = static_cast<GLenum>(c.format);
10363 GLenum type = static_cast<GLenum>(c.type);
10364 uint32 data_size;
10365 if (!GLES2Util::ComputeImageDataSizes(
10366 width, height, depth, format, type, state_.unpack_alignment, &data_size,
10367 NULL, NULL)) {
10368 return error::kOutOfBounds;
10370 const void* pixels = GetSharedMemoryAs<const void*>(
10371 c.pixels_shm_id, c.pixels_shm_offset, data_size);
10372 return DoTexSubImage3D(target, level, xoffset, yoffset, zoffset, width,
10373 height, depth, format, type, pixels);
10376 error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
10377 uint32 immediate_data_size,
10378 const void* cmd_data) {
10379 const gles2::cmds::GetVertexAttribPointerv& c =
10380 *static_cast<const gles2::cmds::GetVertexAttribPointerv*>(cmd_data);
10381 GLuint index = static_cast<GLuint>(c.index);
10382 GLenum pname = static_cast<GLenum>(c.pname);
10383 typedef cmds::GetVertexAttribPointerv::Result Result;
10384 Result* result = GetSharedMemoryAs<Result*>(
10385 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
10386 if (!result) {
10387 return error::kOutOfBounds;
10389 // Check that the client initialized the result.
10390 if (result->size != 0) {
10391 return error::kInvalidArguments;
10393 if (!validators_->vertex_pointer.IsValid(pname)) {
10394 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10395 "glGetVertexAttribPointerv", pname, "pname");
10396 return error::kNoError;
10398 if (index >= group_->max_vertex_attribs()) {
10399 LOCAL_SET_GL_ERROR(
10400 GL_INVALID_VALUE, "glGetVertexAttribPointerv", "index out of range.");
10401 return error::kNoError;
10403 result->SetNumResults(1);
10404 *result->GetData() =
10405 state_.vertex_attrib_manager->GetVertexAttrib(index)->offset();
10406 return error::kNoError;
10409 template <class T>
10410 bool GLES2DecoderImpl::GetUniformSetup(GLuint program_id,
10411 GLint fake_location,
10412 uint32 shm_id,
10413 uint32 shm_offset,
10414 error::Error* error,
10415 GLint* real_location,
10416 GLuint* service_id,
10417 SizedResult<T>** result_pointer,
10418 GLenum* result_type,
10419 GLsizei* result_size) {
10420 DCHECK(error);
10421 DCHECK(service_id);
10422 DCHECK(result_pointer);
10423 DCHECK(result_type);
10424 DCHECK(result_size);
10425 DCHECK(real_location);
10426 *error = error::kNoError;
10427 // Make sure we have enough room for the result on failure.
10428 SizedResult<T>* result;
10429 result = GetSharedMemoryAs<SizedResult<T>*>(
10430 shm_id, shm_offset, SizedResult<T>::ComputeSize(0));
10431 if (!result) {
10432 *error = error::kOutOfBounds;
10433 return false;
10435 *result_pointer = result;
10436 // Set the result size to 0 so the client does not have to check for success.
10437 result->SetNumResults(0);
10438 Program* program = GetProgramInfoNotShader(program_id, "glGetUniform");
10439 if (!program) {
10440 return false;
10442 if (!program->IsValid()) {
10443 // Program was not linked successfully. (ie, glLinkProgram)
10444 LOCAL_SET_GL_ERROR(
10445 GL_INVALID_OPERATION, "glGetUniform", "program not linked");
10446 return false;
10448 *service_id = program->service_id();
10449 GLint array_index = -1;
10450 const Program::UniformInfo* uniform_info =
10451 program->GetUniformInfoByFakeLocation(
10452 fake_location, real_location, &array_index);
10453 if (!uniform_info) {
10454 // No such location.
10455 LOCAL_SET_GL_ERROR(
10456 GL_INVALID_OPERATION, "glGetUniform", "unknown location");
10457 return false;
10459 GLenum type = uniform_info->type;
10460 uint32 num_elements = GLES2Util::GetElementCountForUniformType(type);
10461 if (num_elements == 0) {
10462 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glGetUniform", "unknown type");
10463 return false;
10465 result = GetSharedMemoryAs<SizedResult<T>*>(
10466 shm_id, shm_offset, SizedResult<T>::ComputeSize(num_elements));
10467 if (!result) {
10468 *error = error::kOutOfBounds;
10469 return false;
10471 result->SetNumResults(num_elements);
10472 *result_size = num_elements * sizeof(T);
10473 *result_type = type;
10474 return true;
10477 error::Error GLES2DecoderImpl::HandleGetUniformiv(uint32 immediate_data_size,
10478 const void* cmd_data) {
10479 const gles2::cmds::GetUniformiv& c =
10480 *static_cast<const gles2::cmds::GetUniformiv*>(cmd_data);
10481 GLuint program = c.program;
10482 GLint fake_location = c.location;
10483 GLuint service_id;
10484 GLenum result_type;
10485 GLsizei result_size;
10486 GLint real_location = -1;
10487 Error error;
10488 cmds::GetUniformiv::Result* result;
10489 if (GetUniformSetup<GLint>(program, fake_location, c.params_shm_id,
10490 c.params_shm_offset, &error, &real_location,
10491 &service_id, &result, &result_type,
10492 &result_size)) {
10493 glGetUniformiv(
10494 service_id, real_location, result->GetData());
10496 return error;
10499 error::Error GLES2DecoderImpl::HandleGetUniformuiv(uint32 immediate_data_size,
10500 const void* cmd_data) {
10501 if (!unsafe_es3_apis_enabled())
10502 return error::kUnknownCommand;
10504 const gles2::cmds::GetUniformuiv& c =
10505 *static_cast<const gles2::cmds::GetUniformuiv*>(cmd_data);
10506 GLuint program = c.program;
10507 GLint fake_location = c.location;
10508 GLuint service_id;
10509 GLenum result_type;
10510 GLsizei result_size;
10511 GLint real_location = -1;
10512 Error error;
10513 cmds::GetUniformuiv::Result* result;
10514 if (GetUniformSetup<GLuint>(program, fake_location, c.params_shm_id,
10515 c.params_shm_offset, &error, &real_location,
10516 &service_id, &result, &result_type,
10517 &result_size)) {
10518 glGetUniformuiv(
10519 service_id, real_location, result->GetData());
10521 return error;
10524 error::Error GLES2DecoderImpl::HandleGetUniformfv(uint32 immediate_data_size,
10525 const void* cmd_data) {
10526 const gles2::cmds::GetUniformfv& c =
10527 *static_cast<const gles2::cmds::GetUniformfv*>(cmd_data);
10528 GLuint program = c.program;
10529 GLint fake_location = c.location;
10530 GLuint service_id;
10531 GLint real_location = -1;
10532 Error error;
10533 cmds::GetUniformfv::Result* result;
10534 GLenum result_type;
10535 GLsizei result_size;
10536 if (GetUniformSetup<GLfloat>(program, fake_location, c.params_shm_id,
10537 c.params_shm_offset, &error, &real_location,
10538 &service_id, &result, &result_type,
10539 &result_size)) {
10540 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
10541 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
10542 GLsizei num_values = result_size / sizeof(GLfloat);
10543 scoped_ptr<GLint[]> temp(new GLint[num_values]);
10544 glGetUniformiv(service_id, real_location, temp.get());
10545 GLfloat* dst = result->GetData();
10546 for (GLsizei ii = 0; ii < num_values; ++ii) {
10547 dst[ii] = (temp[ii] != 0);
10549 } else {
10550 glGetUniformfv(service_id, real_location, result->GetData());
10553 return error;
10556 error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
10557 uint32 immediate_data_size,
10558 const void* cmd_data) {
10559 const gles2::cmds::GetShaderPrecisionFormat& c =
10560 *static_cast<const gles2::cmds::GetShaderPrecisionFormat*>(cmd_data);
10561 GLenum shader_type = static_cast<GLenum>(c.shadertype);
10562 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
10563 typedef cmds::GetShaderPrecisionFormat::Result Result;
10564 Result* result = GetSharedMemoryAs<Result*>(
10565 c.result_shm_id, c.result_shm_offset, sizeof(*result));
10566 if (!result) {
10567 return error::kOutOfBounds;
10569 // Check that the client initialized the result.
10570 if (result->success != 0) {
10571 return error::kInvalidArguments;
10573 if (!validators_->shader_type.IsValid(shader_type)) {
10574 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10575 "glGetShaderPrecisionFormat", shader_type, "shader_type");
10576 return error::kNoError;
10578 if (!validators_->shader_precision.IsValid(precision_type)) {
10579 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10580 "glGetShaderPrecisionFormat", precision_type, "precision_type");
10581 return error::kNoError;
10584 result->success = 1; // true
10586 GLint range[2] = { 0, 0 };
10587 GLint precision = 0;
10588 GetShaderPrecisionFormatImpl(shader_type, precision_type, range, &precision);
10590 result->min_range = range[0];
10591 result->max_range = range[1];
10592 result->precision = precision;
10594 return error::kNoError;
10597 error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
10598 uint32 immediate_data_size,
10599 const void* cmd_data) {
10600 const gles2::cmds::GetAttachedShaders& c =
10601 *static_cast<const gles2::cmds::GetAttachedShaders*>(cmd_data);
10602 uint32 result_size = c.result_size;
10603 GLuint program_id = static_cast<GLuint>(c.program);
10604 Program* program = GetProgramInfoNotShader(
10605 program_id, "glGetAttachedShaders");
10606 if (!program) {
10607 return error::kNoError;
10609 typedef cmds::GetAttachedShaders::Result Result;
10610 uint32 max_count = Result::ComputeMaxResults(result_size);
10611 Result* result = GetSharedMemoryAs<Result*>(
10612 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
10613 if (!result) {
10614 return error::kOutOfBounds;
10616 // Check that the client initialized the result.
10617 if (result->size != 0) {
10618 return error::kInvalidArguments;
10620 GLsizei count = 0;
10621 glGetAttachedShaders(
10622 program->service_id(), max_count, &count, result->GetData());
10623 for (GLsizei ii = 0; ii < count; ++ii) {
10624 if (!shader_manager()->GetClientId(result->GetData()[ii],
10625 &result->GetData()[ii])) {
10626 NOTREACHED();
10627 return error::kGenericError;
10630 result->SetNumResults(count);
10631 return error::kNoError;
10634 error::Error GLES2DecoderImpl::HandleGetActiveUniform(
10635 uint32 immediate_data_size,
10636 const void* cmd_data) {
10637 const gles2::cmds::GetActiveUniform& c =
10638 *static_cast<const gles2::cmds::GetActiveUniform*>(cmd_data);
10639 GLuint program_id = c.program;
10640 GLuint index = c.index;
10641 uint32 name_bucket_id = c.name_bucket_id;
10642 typedef cmds::GetActiveUniform::Result Result;
10643 Result* result = GetSharedMemoryAs<Result*>(
10644 c.result_shm_id, c.result_shm_offset, sizeof(*result));
10645 if (!result) {
10646 return error::kOutOfBounds;
10648 // Check that the client initialized the result.
10649 if (result->success != 0) {
10650 return error::kInvalidArguments;
10652 Program* program = GetProgramInfoNotShader(
10653 program_id, "glGetActiveUniform");
10654 if (!program) {
10655 return error::kNoError;
10657 const Program::UniformInfo* uniform_info =
10658 program->GetUniformInfo(index);
10659 if (!uniform_info) {
10660 LOCAL_SET_GL_ERROR(
10661 GL_INVALID_VALUE, "glGetActiveUniform", "index out of range");
10662 return error::kNoError;
10664 result->success = 1; // true.
10665 result->size = uniform_info->size;
10666 result->type = uniform_info->type;
10667 Bucket* bucket = CreateBucket(name_bucket_id);
10668 bucket->SetFromString(uniform_info->name.c_str());
10669 return error::kNoError;
10672 error::Error GLES2DecoderImpl::HandleGetActiveUniformBlockiv(
10673 uint32 immediate_data_size, const void* cmd_data) {
10674 if (!unsafe_es3_apis_enabled())
10675 return error::kUnknownCommand;
10676 const gles2::cmds::GetActiveUniformBlockiv& c =
10677 *static_cast<const gles2::cmds::GetActiveUniformBlockiv*>(cmd_data);
10678 GLuint program_id = c.program;
10679 GLuint index = static_cast<GLuint>(c.index);
10680 GLenum pname = static_cast<GLenum>(c.pname);
10681 Program* program = GetProgramInfoNotShader(
10682 program_id, "glGetActiveUniformBlockiv");
10683 if (!program) {
10684 return error::kNoError;
10686 GLuint service_id = program->service_id();
10687 GLint link_status = GL_FALSE;
10688 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
10689 if (link_status != GL_TRUE) {
10690 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10691 "glGetActiveActiveUniformBlockiv", "program not linked");
10692 return error::kNoError;
10694 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetActiveUniformBlockiv");
10695 GLsizei num_values = 1;
10696 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES) {
10697 GLint num = 0;
10698 glGetActiveUniformBlockiv(
10699 service_id, index, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &num);
10700 GLenum error = glGetError();
10701 if (error != GL_NO_ERROR) {
10702 // Assume this will the same error if calling with pname.
10703 LOCAL_SET_GL_ERROR(error, "GetActiveUniformBlockiv", "");
10704 return error::kNoError;
10706 num_values = static_cast<GLsizei>(num);
10708 typedef cmds::GetActiveUniformBlockiv::Result Result;
10709 Result* result = GetSharedMemoryAs<Result*>(
10710 c.params_shm_id, c.params_shm_offset, Result::ComputeSize(num_values));
10711 GLint* params = result ? result->GetData() : NULL;
10712 if (params == NULL) {
10713 return error::kOutOfBounds;
10715 // Check that the client initialized the result.
10716 if (result->size != 0) {
10717 return error::kInvalidArguments;
10719 glGetActiveUniformBlockiv(service_id, index, pname, params);
10720 GLenum error = glGetError();
10721 if (error == GL_NO_ERROR) {
10722 result->SetNumResults(num_values);
10723 } else {
10724 LOCAL_SET_GL_ERROR(error, "GetActiveUniformBlockiv", "");
10726 return error::kNoError;
10729 error::Error GLES2DecoderImpl::HandleGetActiveUniformBlockName(
10730 uint32 immediate_data_size, const void* cmd_data) {
10731 if (!unsafe_es3_apis_enabled())
10732 return error::kUnknownCommand;
10733 const gles2::cmds::GetActiveUniformBlockName& c =
10734 *static_cast<const gles2::cmds::GetActiveUniformBlockName*>(cmd_data);
10735 GLuint program_id = c.program;
10736 GLuint index = c.index;
10737 uint32 name_bucket_id = c.name_bucket_id;
10738 typedef cmds::GetActiveUniformBlockName::Result Result;
10739 Result* result = GetSharedMemoryAs<Result*>(
10740 c.result_shm_id, c.result_shm_offset, sizeof(*result));
10741 if (!result) {
10742 return error::kOutOfBounds;
10744 // Check that the client initialized the result.
10745 if (*result != 0) {
10746 return error::kInvalidArguments;
10748 Program* program = GetProgramInfoNotShader(
10749 program_id, "glGetActiveUniformBlockName");
10750 if (!program) {
10751 return error::kNoError;
10753 GLuint service_id = program->service_id();
10754 GLint link_status = GL_FALSE;
10755 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
10756 if (link_status != GL_TRUE) {
10757 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10758 "glGetActiveActiveUniformBlockName", "program not linked");
10759 return error::kNoError;
10761 GLint max_length = 0;
10762 glGetProgramiv(
10763 service_id, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &max_length);
10764 // Increase one so &buffer[0] is always valid.
10765 GLsizei buf_size = static_cast<GLsizei>(max_length) + 1;
10766 std::vector<char> buffer(buf_size);
10767 GLsizei length = 0;
10768 glGetActiveUniformBlockName(
10769 service_id, index, buf_size, &length, &buffer[0]);
10770 if (length == 0) {
10771 *result = 0;
10772 return error::kNoError;
10774 *result = 1;
10775 Bucket* bucket = CreateBucket(name_bucket_id);
10776 DCHECK_GT(buf_size, length);
10777 DCHECK_EQ(0, buffer[length]);
10778 bucket->SetFromString(&buffer[0]);
10779 return error::kNoError;
10782 error::Error GLES2DecoderImpl::HandleGetActiveUniformsiv(
10783 uint32 immediate_data_size, const void* cmd_data) {
10784 if (!unsafe_es3_apis_enabled())
10785 return error::kUnknownCommand;
10786 const gles2::cmds::GetActiveUniformsiv& c =
10787 *static_cast<const gles2::cmds::GetActiveUniformsiv*>(cmd_data);
10788 GLuint program_id = c.program;
10789 GLenum pname = static_cast<GLenum>(c.pname);
10790 Bucket* bucket = GetBucket(c.indices_bucket_id);
10791 if (!bucket) {
10792 return error::kInvalidArguments;
10794 GLsizei count = static_cast<GLsizei>(bucket->size() / sizeof(GLuint));
10795 const GLuint* indices = bucket->GetDataAs<const GLuint*>(0, bucket->size());
10796 typedef cmds::GetActiveUniformsiv::Result Result;
10797 Result* result = GetSharedMemoryAs<Result*>(
10798 c.params_shm_id, c.params_shm_offset, Result::ComputeSize(count));
10799 GLint* params = result ? result->GetData() : NULL;
10800 if (params == NULL) {
10801 return error::kOutOfBounds;
10803 // Check that the client initialized the result.
10804 if (result->size != 0) {
10805 return error::kInvalidArguments;
10807 Program* program = GetProgramInfoNotShader(
10808 program_id, "glGetActiveUniformsiv");
10809 if (!program) {
10810 return error::kNoError;
10812 GLuint service_id = program->service_id();
10813 GLint link_status = GL_FALSE;
10814 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
10815 if (link_status != GL_TRUE) {
10816 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10817 "glGetActiveUniformsiv", "program not linked");
10818 return error::kNoError;
10820 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetActiveUniformsiv");
10821 glGetActiveUniformsiv(service_id, count, indices, pname, params);
10822 GLenum error = glGetError();
10823 if (error == GL_NO_ERROR) {
10824 result->SetNumResults(count);
10825 } else {
10826 LOCAL_SET_GL_ERROR(error, "GetActiveUniformsiv", "");
10828 return error::kNoError;
10831 error::Error GLES2DecoderImpl::HandleGetActiveAttrib(uint32 immediate_data_size,
10832 const void* cmd_data) {
10833 const gles2::cmds::GetActiveAttrib& c =
10834 *static_cast<const gles2::cmds::GetActiveAttrib*>(cmd_data);
10835 GLuint program_id = c.program;
10836 GLuint index = c.index;
10837 uint32 name_bucket_id = c.name_bucket_id;
10838 typedef cmds::GetActiveAttrib::Result Result;
10839 Result* result = GetSharedMemoryAs<Result*>(
10840 c.result_shm_id, c.result_shm_offset, sizeof(*result));
10841 if (!result) {
10842 return error::kOutOfBounds;
10844 // Check that the client initialized the result.
10845 if (result->success != 0) {
10846 return error::kInvalidArguments;
10848 Program* program = GetProgramInfoNotShader(
10849 program_id, "glGetActiveAttrib");
10850 if (!program) {
10851 return error::kNoError;
10853 const Program::VertexAttrib* attrib_info =
10854 program->GetAttribInfo(index);
10855 if (!attrib_info) {
10856 LOCAL_SET_GL_ERROR(
10857 GL_INVALID_VALUE, "glGetActiveAttrib", "index out of range");
10858 return error::kNoError;
10860 result->success = 1; // true.
10861 result->size = attrib_info->size;
10862 result->type = attrib_info->type;
10863 Bucket* bucket = CreateBucket(name_bucket_id);
10864 bucket->SetFromString(attrib_info->name.c_str());
10865 return error::kNoError;
10868 error::Error GLES2DecoderImpl::HandleShaderBinary(uint32 immediate_data_size,
10869 const void* cmd_data) {
10870 #if 1 // No binary shader support.
10871 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glShaderBinary", "not supported");
10872 return error::kNoError;
10873 #else
10874 GLsizei n = static_cast<GLsizei>(c.n);
10875 if (n < 0) {
10876 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "n < 0");
10877 return error::kNoError;
10879 GLsizei length = static_cast<GLsizei>(c.length);
10880 if (length < 0) {
10881 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "length < 0");
10882 return error::kNoError;
10884 uint32 data_size;
10885 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
10886 return error::kOutOfBounds;
10888 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
10889 c.shaders_shm_id, c.shaders_shm_offset, data_size);
10890 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
10891 const void* binary = GetSharedMemoryAs<const void*>(
10892 c.binary_shm_id, c.binary_shm_offset, length);
10893 if (shaders == NULL || binary == NULL) {
10894 return error::kOutOfBounds;
10896 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
10897 for (GLsizei ii = 0; ii < n; ++ii) {
10898 Shader* shader = GetShader(shaders[ii]);
10899 if (!shader) {
10900 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "unknown shader");
10901 return error::kNoError;
10903 service_ids[ii] = shader->service_id();
10905 // TODO(gman): call glShaderBinary
10906 return error::kNoError;
10907 #endif
10910 void GLES2DecoderImpl::DoSwapBuffers() {
10911 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
10913 int this_frame_number = frame_number_++;
10914 // TRACE_EVENT for gpu tests:
10915 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffersLatency",
10916 TRACE_EVENT_SCOPE_THREAD,
10917 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
10918 "width", (is_offscreen ? offscreen_size_.width() :
10919 surface_->GetSize().width()));
10920 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoSwapBuffers",
10921 "offscreen", is_offscreen,
10922 "frame", this_frame_number);
10924 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
10927 ScopedGPUTrace scoped_gpu_trace(gpu_tracer_.get(), kTraceDecoder,
10928 "gpu_toplevel", "SwapBuffer");
10930 bool is_tracing;
10931 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
10932 &is_tracing);
10933 if (is_tracing) {
10934 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
10935 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
10936 is_offscreen ? offscreen_size_ : surface_->GetSize());
10939 // If offscreen then don't actually SwapBuffers to the display. Just copy
10940 // the rendered frame to another frame buffer.
10941 if (is_offscreen) {
10942 TRACE_EVENT2("gpu", "Offscreen",
10943 "width", offscreen_size_.width(), "height", offscreen_size_.height());
10944 if (offscreen_size_ != offscreen_saved_color_texture_->size()) {
10945 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
10946 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
10947 // fix this.
10948 if (workarounds().needs_offscreen_buffer_workaround) {
10949 offscreen_saved_frame_buffer_->Create();
10950 glFinish();
10953 // Allocate the offscreen saved color texture.
10954 DCHECK(offscreen_saved_color_format_);
10955 offscreen_saved_color_texture_->AllocateStorage(
10956 offscreen_size_, offscreen_saved_color_format_, false);
10958 offscreen_saved_frame_buffer_->AttachRenderTexture(
10959 offscreen_saved_color_texture_.get());
10960 if (offscreen_size_.width() != 0 && offscreen_size_.height() != 0) {
10961 if (offscreen_saved_frame_buffer_->CheckStatus() !=
10962 GL_FRAMEBUFFER_COMPLETE) {
10963 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
10964 << "because offscreen saved FBO was incomplete.";
10965 MarkContextLost(error::kUnknown);
10966 group_->LoseContexts(error::kUnknown);
10967 return;
10970 // Clear the offscreen color texture.
10971 // TODO(piman): Is this still necessary?
10973 ScopedFrameBufferBinder binder(this,
10974 offscreen_saved_frame_buffer_->id());
10975 glClearColor(0, 0, 0, 0);
10976 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
10977 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
10978 glClear(GL_COLOR_BUFFER_BIT);
10979 RestoreClearState();
10983 UpdateParentTextureInfo();
10986 if (offscreen_size_.width() == 0 || offscreen_size_.height() == 0)
10987 return;
10988 ScopedGLErrorSuppressor suppressor(
10989 "GLES2DecoderImpl::DoSwapBuffers", GetErrorState());
10991 if (IsOffscreenBufferMultisampled()) {
10992 // For multisampled buffers, resolve the frame buffer.
10993 ScopedResolvedFrameBufferBinder binder(this, true, false);
10994 } else {
10995 ScopedFrameBufferBinder binder(this,
10996 offscreen_target_frame_buffer_->id());
10998 if (offscreen_target_buffer_preserved_) {
10999 // Copy the target frame buffer to the saved offscreen texture.
11000 offscreen_saved_color_texture_->Copy(
11001 offscreen_saved_color_texture_->size(),
11002 offscreen_saved_color_format_);
11003 } else {
11004 // Flip the textures in the parent context via the texture manager.
11005 if (!!offscreen_saved_color_texture_info_.get())
11006 offscreen_saved_color_texture_info_->texture()->
11007 SetServiceId(offscreen_target_color_texture_->id());
11009 offscreen_saved_color_texture_.swap(offscreen_target_color_texture_);
11010 offscreen_target_frame_buffer_->AttachRenderTexture(
11011 offscreen_target_color_texture_.get());
11014 // Ensure the side effects of the copy are visible to the parent
11015 // context. There is no need to do this for ANGLE because it uses a
11016 // single D3D device for all contexts.
11017 if (!feature_info_->gl_version_info().is_angle)
11018 glFlush();
11020 } else {
11021 if (!surface_->SwapBuffers()) {
11022 LOG(ERROR) << "Context lost because SwapBuffers failed.";
11023 if (!CheckResetStatus()) {
11024 MarkContextLost(error::kUnknown);
11025 group_->LoseContexts(error::kUnknown);
11030 // This may be a slow command. Exit command processing to allow for
11031 // context preemption and GPU watchdog checks.
11032 ExitCommandProcessingEarly();
11035 void GLES2DecoderImpl::DoSwapInterval(int interval) {
11036 context_->SetSwapInterval(interval);
11039 error::Error GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
11040 uint32 immediate_data_size,
11041 const void* cmd_data) {
11042 const gles2::cmds::EnableFeatureCHROMIUM& c =
11043 *static_cast<const gles2::cmds::EnableFeatureCHROMIUM*>(cmd_data);
11044 Bucket* bucket = GetBucket(c.bucket_id);
11045 if (!bucket || bucket->size() == 0) {
11046 return error::kInvalidArguments;
11048 typedef cmds::EnableFeatureCHROMIUM::Result Result;
11049 Result* result = GetSharedMemoryAs<Result*>(
11050 c.result_shm_id, c.result_shm_offset, sizeof(*result));
11051 if (!result) {
11052 return error::kOutOfBounds;
11054 // Check that the client initialized the result.
11055 if (*result != 0) {
11056 return error::kInvalidArguments;
11058 std::string feature_str;
11059 if (!bucket->GetAsString(&feature_str)) {
11060 return error::kInvalidArguments;
11063 // TODO(gman): make this some kind of table to function pointer thingy.
11064 if (feature_str.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
11065 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
11066 } else if (feature_str.compare("pepper3d_support_fixed_attribs") == 0) {
11067 buffer_manager()->set_allow_fixed_attribs(true);
11068 // TODO(gman): decide how to remove the need for this const_cast.
11069 // I could make validators_ non const but that seems bad as this is the only
11070 // place it is needed. I could make some special friend class of validators
11071 // just to allow this to set them. That seems silly. I could refactor this
11072 // code to use the extension mechanism or the initialization attributes to
11073 // turn this feature on. Given that the only real point of this is to make
11074 // the conformance tests pass and given that there is lots of real work that
11075 // needs to be done it seems like refactoring for one to one of those
11076 // methods is a very low priority.
11077 const_cast<Validators*>(validators_)->vertex_attrib_type.AddValue(GL_FIXED);
11078 } else if (feature_str.compare("webgl_enable_glsl_webgl_validation") == 0) {
11079 force_webgl_glsl_validation_ = true;
11080 InitializeShaderTranslator();
11081 } else {
11082 return error::kNoError;
11085 *result = 1; // true.
11086 return error::kNoError;
11089 error::Error GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
11090 uint32 immediate_data_size,
11091 const void* cmd_data) {
11092 const gles2::cmds::GetRequestableExtensionsCHROMIUM& c =
11093 *static_cast<const gles2::cmds::GetRequestableExtensionsCHROMIUM*>(
11094 cmd_data);
11095 Bucket* bucket = CreateBucket(c.bucket_id);
11096 scoped_refptr<FeatureInfo> info(new FeatureInfo());
11097 info->Initialize(disallowed_features_);
11098 bucket->SetFromString(info->extensions().c_str());
11099 return error::kNoError;
11102 error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
11103 uint32 immediate_data_size,
11104 const void* cmd_data) {
11105 const gles2::cmds::RequestExtensionCHROMIUM& c =
11106 *static_cast<const gles2::cmds::RequestExtensionCHROMIUM*>(cmd_data);
11107 Bucket* bucket = GetBucket(c.bucket_id);
11108 if (!bucket || bucket->size() == 0) {
11109 return error::kInvalidArguments;
11111 std::string feature_str;
11112 if (!bucket->GetAsString(&feature_str)) {
11113 return error::kInvalidArguments;
11116 bool desire_webgl_glsl_validation =
11117 feature_str.find("GL_CHROMIUM_webglsl") != std::string::npos;
11118 bool desire_standard_derivatives = false;
11119 bool desire_frag_depth = false;
11120 bool desire_draw_buffers = false;
11121 bool desire_shader_texture_lod = false;
11122 if (force_webgl_glsl_validation_) {
11123 desire_standard_derivatives =
11124 feature_str.find("GL_OES_standard_derivatives") != std::string::npos;
11125 desire_frag_depth =
11126 feature_str.find("GL_EXT_frag_depth") != std::string::npos;
11127 desire_draw_buffers =
11128 feature_str.find("GL_EXT_draw_buffers") != std::string::npos;
11129 desire_shader_texture_lod =
11130 feature_str.find("GL_EXT_shader_texture_lod") != std::string::npos;
11133 if (desire_webgl_glsl_validation != force_webgl_glsl_validation_ ||
11134 desire_standard_derivatives != derivatives_explicitly_enabled_ ||
11135 desire_frag_depth != frag_depth_explicitly_enabled_ ||
11136 desire_draw_buffers != draw_buffers_explicitly_enabled_) {
11137 force_webgl_glsl_validation_ |= desire_webgl_glsl_validation;
11138 derivatives_explicitly_enabled_ |= desire_standard_derivatives;
11139 frag_depth_explicitly_enabled_ |= desire_frag_depth;
11140 draw_buffers_explicitly_enabled_ |= desire_draw_buffers;
11141 shader_texture_lod_explicitly_enabled_ |= desire_shader_texture_lod;
11142 InitializeShaderTranslator();
11145 UpdateCapabilities();
11147 return error::kNoError;
11150 error::Error GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
11151 uint32 immediate_data_size,
11152 const void* cmd_data) {
11153 const gles2::cmds::GetProgramInfoCHROMIUM& c =
11154 *static_cast<const gles2::cmds::GetProgramInfoCHROMIUM*>(cmd_data);
11155 GLuint program_id = static_cast<GLuint>(c.program);
11156 uint32 bucket_id = c.bucket_id;
11157 Bucket* bucket = CreateBucket(bucket_id);
11158 bucket->SetSize(sizeof(ProgramInfoHeader)); // in case we fail.
11159 Program* program = NULL;
11160 program = GetProgram(program_id);
11161 if (!program || !program->IsValid()) {
11162 return error::kNoError;
11164 program->GetProgramInfo(program_manager(), bucket);
11165 return error::kNoError;
11168 error::Error GLES2DecoderImpl::HandleGetUniformBlocksCHROMIUM(
11169 uint32 immediate_data_size, const void* cmd_data) {
11170 if (!unsafe_es3_apis_enabled())
11171 return error::kUnknownCommand;
11172 const gles2::cmds::GetUniformBlocksCHROMIUM& c =
11173 *static_cast<const gles2::cmds::GetUniformBlocksCHROMIUM*>(cmd_data);
11174 GLuint program_id = static_cast<GLuint>(c.program);
11175 uint32 bucket_id = c.bucket_id;
11176 Bucket* bucket = CreateBucket(bucket_id);
11177 bucket->SetSize(sizeof(UniformBlocksHeader)); // in case we fail.
11178 Program* program = NULL;
11179 program = GetProgram(program_id);
11180 if (!program || !program->IsValid()) {
11181 return error::kNoError;
11183 program->GetUniformBlocks(bucket);
11184 return error::kNoError;
11187 error::Error GLES2DecoderImpl::HandleGetUniformsES3CHROMIUM(
11188 uint32 immediate_data_size, const void* cmd_data) {
11189 if (!unsafe_es3_apis_enabled())
11190 return error::kUnknownCommand;
11191 const gles2::cmds::GetUniformsES3CHROMIUM& c =
11192 *static_cast<const gles2::cmds::GetUniformsES3CHROMIUM*>(cmd_data);
11193 GLuint program_id = static_cast<GLuint>(c.program);
11194 uint32 bucket_id = c.bucket_id;
11195 Bucket* bucket = CreateBucket(bucket_id);
11196 bucket->SetSize(sizeof(UniformsES3Header)); // in case we fail.
11197 Program* program = NULL;
11198 program = GetProgram(program_id);
11199 if (!program || !program->IsValid()) {
11200 return error::kNoError;
11202 program->GetUniformsES3(bucket);
11203 return error::kNoError;
11206 error::Error GLES2DecoderImpl::HandleGetTransformFeedbackVarying(
11207 uint32 immediate_data_size,
11208 const void* cmd_data) {
11209 if (!unsafe_es3_apis_enabled())
11210 return error::kUnknownCommand;
11211 const gles2::cmds::GetTransformFeedbackVarying& c =
11212 *static_cast<const gles2::cmds::GetTransformFeedbackVarying*>(cmd_data);
11213 GLuint program_id = c.program;
11214 GLuint index = c.index;
11215 uint32 name_bucket_id = c.name_bucket_id;
11216 typedef cmds::GetTransformFeedbackVarying::Result Result;
11217 Result* result = GetSharedMemoryAs<Result*>(
11218 c.result_shm_id, c.result_shm_offset, sizeof(*result));
11219 if (!result) {
11220 return error::kOutOfBounds;
11222 // Check that the client initialized the result.
11223 if (result->success != 0) {
11224 return error::kInvalidArguments;
11226 Program* program = GetProgramInfoNotShader(
11227 program_id, "glGetTransformFeedbackVarying");
11228 if (!program) {
11229 return error::kNoError;
11231 GLuint service_id = program->service_id();
11232 GLint link_status = GL_FALSE;
11233 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
11234 if (link_status != GL_TRUE) {
11235 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
11236 "glGetTransformFeedbackVarying", "program not linked");
11237 return error::kNoError;
11239 GLint max_length = 0;
11240 glGetProgramiv(
11241 service_id, GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH, &max_length);
11242 max_length = std::max(1, max_length);
11243 std::vector<char> buffer(max_length);
11244 GLsizei length = 0;
11245 GLsizei size = 0;
11246 GLenum type = 0;
11247 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetTransformFeedbackVarying");
11248 glGetTransformFeedbackVarying(
11249 service_id, index, max_length, &length, &size, &type, &buffer[0]);
11250 GLenum error = glGetError();
11251 if (error != GL_NO_ERROR) {
11252 LOCAL_SET_GL_ERROR(error, "glGetTransformFeedbackVarying", "");
11253 return error::kNoError;
11255 result->success = 1; // true.
11256 result->size = static_cast<int32_t>(size);
11257 result->type = static_cast<uint32_t>(type);
11258 Bucket* bucket = CreateBucket(name_bucket_id);
11259 DCHECK(length >= 0 && length < max_length);
11260 buffer[length] = '\0'; // Just to be safe.
11261 bucket->SetFromString(&buffer[0]);
11262 return error::kNoError;
11265 error::Error GLES2DecoderImpl::HandleGetTransformFeedbackVaryingsCHROMIUM(
11266 uint32 immediate_data_size, const void* cmd_data) {
11267 if (!unsafe_es3_apis_enabled())
11268 return error::kUnknownCommand;
11269 const gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM& c =
11270 *static_cast<const gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM*>(
11271 cmd_data);
11272 GLuint program_id = static_cast<GLuint>(c.program);
11273 uint32 bucket_id = c.bucket_id;
11274 Bucket* bucket = CreateBucket(bucket_id);
11275 bucket->SetSize(sizeof(TransformFeedbackVaryingsHeader)); // in case we fail.
11276 Program* program = NULL;
11277 program = GetProgram(program_id);
11278 if (!program || !program->IsValid()) {
11279 return error::kNoError;
11281 program->GetTransformFeedbackVaryings(bucket);
11282 return error::kNoError;
11285 error::ContextLostReason GLES2DecoderImpl::GetContextLostReason() {
11286 return context_lost_reason_;
11289 error::ContextLostReason GLES2DecoderImpl::GetContextLostReasonFromResetStatus(
11290 GLenum reset_status) const {
11291 switch (reset_status) {
11292 case GL_NO_ERROR:
11293 // TODO(kbr): improve the precision of the error code in this case.
11294 // Consider delegating to context for error code if MakeCurrent fails.
11295 return error::kUnknown;
11296 case GL_GUILTY_CONTEXT_RESET_ARB:
11297 return error::kGuilty;
11298 case GL_INNOCENT_CONTEXT_RESET_ARB:
11299 return error::kInnocent;
11300 case GL_UNKNOWN_CONTEXT_RESET_ARB:
11301 return error::kUnknown;
11304 NOTREACHED();
11305 return error::kUnknown;
11308 bool GLES2DecoderImpl::WasContextLost() const {
11309 return context_was_lost_;
11312 bool GLES2DecoderImpl::WasContextLostByRobustnessExtension() const {
11313 return WasContextLost() && reset_by_robustness_extension_;
11316 void GLES2DecoderImpl::MarkContextLost(error::ContextLostReason reason) {
11317 // Only lose the context once.
11318 if (WasContextLost())
11319 return;
11321 // Don't make GL calls in here, the context might not be current.
11322 context_lost_reason_ = reason;
11323 current_decoder_error_ = error::kLostContext;
11324 context_was_lost_ = true;
11326 // Some D3D drivers cannot recover from device lost in the GPU process
11327 // sandbox. Allow a new GPU process to launch.
11328 if (workarounds().exit_on_context_lost) {
11329 LOG(ERROR) << "Exiting GPU process because some drivers cannot reset"
11330 << " a D3D device in the Chrome GPU process sandbox.";
11331 #if defined(OS_WIN)
11332 base::win::SetShouldCrashOnProcessDetach(false);
11333 #endif
11334 exit(0);
11338 bool GLES2DecoderImpl::CheckResetStatus() {
11339 DCHECK(!WasContextLost());
11340 DCHECK(context_->IsCurrent(NULL));
11342 if (IsRobustnessSupported()) {
11343 // If the reason for the call was a GL error, we can try to determine the
11344 // reset status more accurately.
11345 GLenum driver_status = glGetGraphicsResetStatusARB();
11346 if (driver_status == GL_NO_ERROR)
11347 return false;
11349 LOG(ERROR) << (surface_->IsOffscreen() ? "Offscreen" : "Onscreen")
11350 << " context lost via ARB/EXT_robustness. Reset status = "
11351 << GLES2Util::GetStringEnum(driver_status);
11353 // Don't pretend we know which client was responsible.
11354 if (workarounds().use_virtualized_gl_contexts)
11355 driver_status = GL_UNKNOWN_CONTEXT_RESET_ARB;
11357 switch (driver_status) {
11358 case GL_GUILTY_CONTEXT_RESET_ARB:
11359 MarkContextLost(error::kGuilty);
11360 break;
11361 case GL_INNOCENT_CONTEXT_RESET_ARB:
11362 MarkContextLost(error::kInnocent);
11363 break;
11364 case GL_UNKNOWN_CONTEXT_RESET_ARB:
11365 MarkContextLost(error::kUnknown);
11366 break;
11367 default:
11368 NOTREACHED();
11369 return false;
11371 reset_by_robustness_extension_ = true;
11372 return true;
11374 return false;
11377 error::Error GLES2DecoderImpl::HandleInsertSyncPointCHROMIUM(
11378 uint32 immediate_data_size,
11379 const void* cmd_data) {
11380 return error::kUnknownCommand;
11383 error::Error GLES2DecoderImpl::HandleWaitSyncPointCHROMIUM(
11384 uint32 immediate_data_size,
11385 const void* cmd_data) {
11386 const gles2::cmds::WaitSyncPointCHROMIUM& c =
11387 *static_cast<const gles2::cmds::WaitSyncPointCHROMIUM*>(cmd_data);
11388 uint32 sync_point = c.sync_point;
11389 if (wait_sync_point_callback_.is_null())
11390 return error::kNoError;
11392 return wait_sync_point_callback_.Run(sync_point) ?
11393 error::kNoError : error::kDeferCommandUntilLater;
11396 error::Error GLES2DecoderImpl::HandleDiscardBackbufferCHROMIUM(
11397 uint32 immediate_data_size,
11398 const void* cmd_data) {
11399 if (surface_->DeferDraws())
11400 return error::kDeferCommandUntilLater;
11401 if (!surface_->SetBackbufferAllocation(false))
11402 return error::kLostContext;
11403 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
11404 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
11405 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
11406 return error::kNoError;
11409 bool GLES2DecoderImpl::GenQueriesEXTHelper(
11410 GLsizei n, const GLuint* client_ids) {
11411 for (GLsizei ii = 0; ii < n; ++ii) {
11412 if (query_manager_->GetQuery(client_ids[ii])) {
11413 return false;
11416 query_manager_->GenQueries(n, client_ids);
11417 return true;
11420 void GLES2DecoderImpl::DeleteQueriesEXTHelper(
11421 GLsizei n, const GLuint* client_ids) {
11422 for (GLsizei ii = 0; ii < n; ++ii) {
11423 QueryManager::Query* query = query_manager_->GetQuery(client_ids[ii]);
11424 if (query && !query->IsDeleted()) {
11425 ContextState::QueryMap::iterator it =
11426 state_.current_queries.find(query->target());
11427 if (it != state_.current_queries.end())
11428 state_.current_queries.erase(it);
11430 query->Destroy(true);
11432 query_manager_->RemoveQuery(client_ids[ii]);
11436 bool GLES2DecoderImpl::ProcessPendingQueries(bool did_finish) {
11437 if (query_manager_.get() == NULL) {
11438 return false;
11440 if (!query_manager_->ProcessPendingQueries(did_finish)) {
11441 current_decoder_error_ = error::kOutOfBounds;
11443 return query_manager_->HavePendingQueries();
11446 // Note that if there are no pending readpixels right now,
11447 // this function will call the callback immediately.
11448 void GLES2DecoderImpl::WaitForReadPixels(base::Closure callback) {
11449 if (features().use_async_readpixels && !pending_readpixel_fences_.empty()) {
11450 pending_readpixel_fences_.back()->callbacks.push_back(callback);
11451 } else {
11452 callback.Run();
11456 void GLES2DecoderImpl::ProcessPendingReadPixels() {
11457 while (!pending_readpixel_fences_.empty() &&
11458 pending_readpixel_fences_.front()->fence->HasCompleted()) {
11459 std::vector<base::Closure> callbacks =
11460 pending_readpixel_fences_.front()->callbacks;
11461 pending_readpixel_fences_.pop();
11462 for (size_t i = 0; i < callbacks.size(); i++) {
11463 callbacks[i].Run();
11468 bool GLES2DecoderImpl::HasMoreIdleWork() {
11469 return !pending_readpixel_fences_.empty() ||
11470 async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers();
11473 void GLES2DecoderImpl::PerformIdleWork() {
11474 ProcessPendingReadPixels();
11475 if (!async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers())
11476 return;
11477 async_pixel_transfer_manager_->ProcessMorePendingTransfers();
11478 ProcessFinishedAsyncTransfers();
11481 error::Error GLES2DecoderImpl::HandleBeginQueryEXT(uint32 immediate_data_size,
11482 const void* cmd_data) {
11483 const gles2::cmds::BeginQueryEXT& c =
11484 *static_cast<const gles2::cmds::BeginQueryEXT*>(cmd_data);
11485 GLenum target = static_cast<GLenum>(c.target);
11486 GLuint client_id = static_cast<GLuint>(c.id);
11487 int32 sync_shm_id = static_cast<int32>(c.sync_data_shm_id);
11488 uint32 sync_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
11490 switch (target) {
11491 case GL_COMMANDS_ISSUED_CHROMIUM:
11492 case GL_LATENCY_QUERY_CHROMIUM:
11493 case GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM:
11494 case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM:
11495 case GL_GET_ERROR_QUERY_CHROMIUM:
11496 break;
11497 case GL_COMMANDS_COMPLETED_CHROMIUM:
11498 if (!features().chromium_sync_query) {
11499 LOCAL_SET_GL_ERROR(
11500 GL_INVALID_OPERATION, "glBeginQueryEXT",
11501 "not enabled for commands completed queries");
11502 return error::kNoError;
11504 break;
11505 default:
11506 if (!features().occlusion_query_boolean) {
11507 LOCAL_SET_GL_ERROR(
11508 GL_INVALID_OPERATION, "glBeginQueryEXT",
11509 "not enabled for occlusion queries");
11510 return error::kNoError;
11512 break;
11515 if (state_.current_queries.find(target) != state_.current_queries.end()) {
11516 LOCAL_SET_GL_ERROR(
11517 GL_INVALID_OPERATION, "glBeginQueryEXT", "query already in progress");
11518 return error::kNoError;
11521 if (client_id == 0) {
11522 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glBeginQueryEXT", "id is 0");
11523 return error::kNoError;
11526 QueryManager::Query* query = query_manager_->GetQuery(client_id);
11527 if (!query) {
11528 if (!query_manager_->IsValidQuery(client_id)) {
11529 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
11530 "glBeginQueryEXT",
11531 "id not made by glGenQueriesEXT");
11532 return error::kNoError;
11534 query = query_manager_->CreateQuery(
11535 target, client_id, sync_shm_id, sync_shm_offset);
11538 if (query->target() != target) {
11539 LOCAL_SET_GL_ERROR(
11540 GL_INVALID_OPERATION, "glBeginQueryEXT", "target does not match");
11541 return error::kNoError;
11542 } else if (query->shm_id() != sync_shm_id ||
11543 query->shm_offset() != sync_shm_offset) {
11544 DLOG(ERROR) << "Shared memory used by query not the same as before";
11545 return error::kInvalidArguments;
11548 if (!query_manager_->BeginQuery(query)) {
11549 return error::kOutOfBounds;
11552 state_.current_queries[target] = query;
11553 return error::kNoError;
11556 error::Error GLES2DecoderImpl::HandleEndQueryEXT(uint32 immediate_data_size,
11557 const void* cmd_data) {
11558 const gles2::cmds::EndQueryEXT& c =
11559 *static_cast<const gles2::cmds::EndQueryEXT*>(cmd_data);
11560 GLenum target = static_cast<GLenum>(c.target);
11561 uint32 submit_count = static_cast<GLuint>(c.submit_count);
11562 ContextState::QueryMap::iterator it = state_.current_queries.find(target);
11564 if (it == state_.current_queries.end()) {
11565 LOCAL_SET_GL_ERROR(
11566 GL_INVALID_OPERATION, "glEndQueryEXT", "No active query");
11567 return error::kNoError;
11570 QueryManager::Query* query = it->second.get();
11571 if (!query_manager_->EndQuery(query, submit_count)) {
11572 return error::kOutOfBounds;
11575 query_manager_->ProcessPendingTransferQueries();
11577 state_.current_queries.erase(it);
11578 return error::kNoError;
11581 bool GLES2DecoderImpl::GenVertexArraysOESHelper(
11582 GLsizei n, const GLuint* client_ids) {
11583 for (GLsizei ii = 0; ii < n; ++ii) {
11584 if (GetVertexAttribManager(client_ids[ii])) {
11585 return false;
11589 if (!features().native_vertex_array_object) {
11590 // Emulated VAO
11591 for (GLsizei ii = 0; ii < n; ++ii) {
11592 CreateVertexAttribManager(client_ids[ii], 0, true);
11594 } else {
11595 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
11597 glGenVertexArraysOES(n, service_ids.get());
11598 for (GLsizei ii = 0; ii < n; ++ii) {
11599 CreateVertexAttribManager(client_ids[ii], service_ids[ii], true);
11603 return true;
11606 void GLES2DecoderImpl::DeleteVertexArraysOESHelper(
11607 GLsizei n, const GLuint* client_ids) {
11608 for (GLsizei ii = 0; ii < n; ++ii) {
11609 VertexAttribManager* vao =
11610 GetVertexAttribManager(client_ids[ii]);
11611 if (vao && !vao->IsDeleted()) {
11612 if (state_.vertex_attrib_manager.get() == vao) {
11613 DoBindVertexArrayOES(0);
11615 RemoveVertexAttribManager(client_ids[ii]);
11620 void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id) {
11621 VertexAttribManager* vao = NULL;
11622 if (client_id != 0) {
11623 vao = GetVertexAttribManager(client_id);
11624 if (!vao) {
11625 // Unlike most Bind* methods, the spec explicitly states that VertexArray
11626 // only allows names that have been previously generated. As such, we do
11627 // not generate new names here.
11628 LOCAL_SET_GL_ERROR(
11629 GL_INVALID_OPERATION,
11630 "glBindVertexArrayOES", "bad vertex array id.");
11631 current_decoder_error_ = error::kNoError;
11632 return;
11634 } else {
11635 vao = state_.default_vertex_attrib_manager.get();
11638 // Only set the VAO state if it's changed
11639 if (state_.vertex_attrib_manager.get() != vao) {
11640 state_.vertex_attrib_manager = vao;
11641 if (!features().native_vertex_array_object) {
11642 EmulateVertexArrayState();
11643 } else {
11644 GLuint service_id = vao->service_id();
11645 glBindVertexArrayOES(service_id);
11650 // Used when OES_vertex_array_object isn't natively supported
11651 void GLES2DecoderImpl::EmulateVertexArrayState() {
11652 // Setup the Vertex attribute state
11653 for (uint32 vv = 0; vv < group_->max_vertex_attribs(); ++vv) {
11654 RestoreStateForAttrib(vv, true);
11657 // Setup the element buffer
11658 Buffer* element_array_buffer =
11659 state_.vertex_attrib_manager->element_array_buffer();
11660 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
11661 element_array_buffer ? element_array_buffer->service_id() : 0);
11664 bool GLES2DecoderImpl::DoIsVertexArrayOES(GLuint client_id) {
11665 const VertexAttribManager* vao =
11666 GetVertexAttribManager(client_id);
11667 return vao && vao->IsValid() && !vao->IsDeleted();
11670 #if defined(OS_MACOSX)
11671 void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id) {
11672 TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.find(
11673 texture_id);
11674 if (it != texture_to_io_surface_map_.end()) {
11675 // Found a previous IOSurface bound to this texture; release it.
11676 IOSurfaceRef surface = it->second;
11677 CFRelease(surface);
11678 texture_to_io_surface_map_.erase(it);
11681 #endif
11683 void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
11684 GLenum target, GLsizei width, GLsizei height,
11685 GLuint io_surface_id, GLuint plane) {
11686 #if defined(OS_MACOSX)
11687 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) {
11688 LOCAL_SET_GL_ERROR(
11689 GL_INVALID_OPERATION,
11690 "glTexImageIOSurface2DCHROMIUM", "only supported on desktop GL.");
11691 return;
11694 if (target != GL_TEXTURE_RECTANGLE_ARB) {
11695 // This might be supported in the future, and if we could require
11696 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
11697 // could delete a lot of code. For now, perform strict validation so we
11698 // know what's going on.
11699 LOCAL_SET_GL_ERROR(
11700 GL_INVALID_OPERATION,
11701 "glTexImageIOSurface2DCHROMIUM",
11702 "requires TEXTURE_RECTANGLE_ARB target");
11703 return;
11706 // Default target might be conceptually valid, but disallow it to avoid
11707 // accidents.
11708 TextureRef* texture_ref =
11709 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
11710 if (!texture_ref) {
11711 LOCAL_SET_GL_ERROR(
11712 GL_INVALID_OPERATION,
11713 "glTexImageIOSurface2DCHROMIUM", "no rectangle texture bound");
11714 return;
11717 // Look up the new IOSurface. Note that because of asynchrony
11718 // between processes this might fail; during live resizing the
11719 // plugin process might allocate and release an IOSurface before
11720 // this process gets a chance to look it up. Hold on to any old
11721 // IOSurface in this case.
11722 IOSurfaceRef surface = IOSurfaceLookup(io_surface_id);
11723 if (!surface) {
11724 LOCAL_SET_GL_ERROR(
11725 GL_INVALID_OPERATION,
11726 "glTexImageIOSurface2DCHROMIUM", "no IOSurface with the given ID");
11727 return;
11730 // Release any IOSurface previously bound to this texture.
11731 ReleaseIOSurfaceForTexture(texture_ref->service_id());
11733 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
11734 texture_to_io_surface_map_.insert(
11735 std::make_pair(texture_ref->service_id(), surface));
11737 CGLContextObj context =
11738 static_cast<CGLContextObj>(context_->GetHandle());
11740 CGLError err = CGLTexImageIOSurface2D(
11741 context,
11742 target,
11743 GL_RGBA,
11744 width,
11745 height,
11746 GL_BGRA,
11747 GL_UNSIGNED_INT_8_8_8_8_REV,
11748 surface,
11749 plane);
11751 if (err != kCGLNoError) {
11752 LOCAL_SET_GL_ERROR(
11753 GL_INVALID_OPERATION,
11754 "glTexImageIOSurface2DCHROMIUM", "error in CGLTexImageIOSurface2D");
11755 return;
11758 texture_manager()->SetLevelInfo(
11759 texture_ref, target, 0, GL_RGBA, width, height, 1, 0,
11760 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, true);
11762 #else
11763 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
11764 "glTexImageIOSurface2DCHROMIUM", "not supported.");
11765 #endif
11768 static GLenum ExtractFormatFromStorageFormat(GLenum internalformat) {
11769 switch (internalformat) {
11770 case GL_RGB565:
11771 return GL_RGB;
11772 case GL_RGBA4:
11773 return GL_RGBA;
11774 case GL_RGB5_A1:
11775 return GL_RGBA;
11776 case GL_RGB8_OES:
11777 return GL_RGB;
11778 case GL_RGBA8_OES:
11779 return GL_RGBA;
11780 case GL_LUMINANCE8_ALPHA8_EXT:
11781 return GL_LUMINANCE_ALPHA;
11782 case GL_LUMINANCE8_EXT:
11783 return GL_LUMINANCE;
11784 case GL_ALPHA8_EXT:
11785 return GL_ALPHA;
11786 case GL_RGBA32F_EXT:
11787 return GL_RGBA;
11788 case GL_RGB32F_EXT:
11789 return GL_RGB;
11790 case GL_ALPHA32F_EXT:
11791 return GL_ALPHA;
11792 case GL_LUMINANCE32F_EXT:
11793 return GL_LUMINANCE;
11794 case GL_LUMINANCE_ALPHA32F_EXT:
11795 return GL_LUMINANCE_ALPHA;
11796 case GL_RGBA16F_EXT:
11797 return GL_RGBA;
11798 case GL_RGB16F_EXT:
11799 return GL_RGB;
11800 case GL_ALPHA16F_EXT:
11801 return GL_ALPHA;
11802 case GL_LUMINANCE16F_EXT:
11803 return GL_LUMINANCE;
11804 case GL_LUMINANCE_ALPHA16F_EXT:
11805 return GL_LUMINANCE_ALPHA;
11806 case GL_BGRA8_EXT:
11807 return GL_BGRA_EXT;
11808 case GL_SRGB8_ALPHA8_EXT:
11809 return GL_SRGB_ALPHA_EXT;
11810 default:
11811 return GL_NONE;
11815 bool GLES2DecoderImpl::ValidateCopyTextureCHROMIUM(
11816 const char* function_name,
11817 GLenum target,
11818 TextureRef* source_texture_ref,
11819 TextureRef* dest_texture_ref,
11820 GLenum dest_internal_format) {
11821 if (!source_texture_ref || !dest_texture_ref) {
11822 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "unknown texture id");
11823 return false;
11826 if (GL_TEXTURE_2D != target) {
11827 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name,
11828 "invalid texture target");
11829 return false;
11832 Texture* source_texture = source_texture_ref->texture();
11833 Texture* dest_texture = dest_texture_ref->texture();
11834 if (source_texture == dest_texture) {
11835 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
11836 "source and destination textures are the same");
11837 return false;
11840 if (dest_texture->target() != GL_TEXTURE_2D ||
11841 (source_texture->target() != GL_TEXTURE_2D &&
11842 source_texture->target() != GL_TEXTURE_RECTANGLE_ARB &&
11843 source_texture->target() != GL_TEXTURE_EXTERNAL_OES)) {
11844 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name,
11845 "invalid texture target binding");
11846 return false;
11849 GLenum source_type = 0;
11850 GLenum source_internal_format = 0;
11851 source_texture->GetLevelType(source_texture->target(), 0, &source_type,
11852 &source_internal_format);
11854 // The destination format should be GL_RGB, or GL_RGBA. GL_ALPHA,
11855 // GL_LUMINANCE, and GL_LUMINANCE_ALPHA are not supported because they are not
11856 // renderable on some platforms.
11857 bool valid_dest_format = dest_internal_format == GL_RGB ||
11858 dest_internal_format == GL_RGBA ||
11859 dest_internal_format == GL_BGRA_EXT;
11860 bool valid_source_format = source_internal_format == GL_ALPHA ||
11861 source_internal_format == GL_RGB ||
11862 source_internal_format == GL_RGBA ||
11863 source_internal_format == GL_LUMINANCE ||
11864 source_internal_format == GL_LUMINANCE_ALPHA ||
11865 source_internal_format == GL_BGRA_EXT;
11866 if (!valid_source_format || !valid_dest_format) {
11867 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
11868 "invalid internal format");
11869 return false;
11871 return true;
11874 void GLES2DecoderImpl::DoCopyTextureCHROMIUM(GLenum target,
11875 GLuint source_id,
11876 GLuint dest_id,
11877 GLenum internal_format,
11878 GLenum dest_type) {
11879 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopyTextureCHROMIUM");
11881 TextureRef* source_texture_ref = GetTexture(source_id);
11882 TextureRef* dest_texture_ref = GetTexture(dest_id);
11883 Texture* source_texture = source_texture_ref->texture();
11884 Texture* dest_texture = dest_texture_ref->texture();
11885 int source_width = 0;
11886 int source_height = 0;
11887 gfx::GLImage* image =
11888 source_texture->GetLevelImage(source_texture->target(), 0);
11889 if (image) {
11890 gfx::Size size = image->GetSize();
11891 source_width = size.width();
11892 source_height = size.height();
11893 if (source_width <= 0 || source_height <= 0) {
11894 LOCAL_SET_GL_ERROR(
11895 GL_INVALID_VALUE,
11896 "glCopyTextureChromium", "invalid image size");
11897 return;
11899 } else {
11900 if (!source_texture->GetLevelSize(source_texture->target(), 0,
11901 &source_width, &source_height, nullptr)) {
11902 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
11903 "glCopyTextureChromium",
11904 "source texture has no level 0");
11905 return;
11908 // Check that this type of texture is allowed.
11909 if (!texture_manager()->ValidForTarget(source_texture->target(), 0,
11910 source_width, source_height, 1)) {
11911 LOCAL_SET_GL_ERROR(
11912 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "Bad dimensions");
11913 return;
11917 GLenum source_type = 0;
11918 GLenum source_internal_format = 0;
11919 source_texture->GetLevelType(
11920 source_texture->target(), 0, &source_type, &source_internal_format);
11922 if (dest_texture->IsImmutable()) {
11923 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCopyTextureCHROMIUM",
11924 "texture is immutable");
11925 return;
11928 if (!ValidateCopyTextureCHROMIUM("glCopyTextureCHROMIUM", target,
11929 source_texture_ref, dest_texture_ref,
11930 internal_format)) {
11931 return;
11934 // Clear the source texture if necessary.
11935 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref,
11936 source_texture->target(), 0)) {
11937 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTextureCHROMIUM",
11938 "dimensions too big");
11939 return;
11942 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
11943 // needed because it takes 10s of milliseconds to initialize.
11944 if (!copy_texture_CHROMIUM_.get()) {
11945 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
11946 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
11947 copy_texture_CHROMIUM_->Initialize(this);
11948 RestoreCurrentFramebufferBindings();
11949 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR)
11950 return;
11953 GLenum dest_type_previous = dest_type;
11954 GLenum dest_internal_format = internal_format;
11955 int dest_width = 0;
11956 int dest_height = 0;
11957 bool dest_level_defined = dest_texture->GetLevelSize(
11958 GL_TEXTURE_2D, 0, &dest_width, &dest_height, nullptr);
11960 if (dest_level_defined) {
11961 dest_texture->GetLevelType(GL_TEXTURE_2D, 0, &dest_type_previous,
11962 &dest_internal_format);
11965 // Resize the destination texture to the dimensions of the source texture.
11966 if (!dest_level_defined || dest_width != source_width ||
11967 dest_height != source_height ||
11968 dest_internal_format != internal_format ||
11969 dest_type_previous != dest_type) {
11970 // Ensure that the glTexImage2D succeeds.
11971 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
11972 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
11973 glTexImage2D(GL_TEXTURE_2D, 0, internal_format, source_width, source_height,
11974 0, internal_format, dest_type, NULL);
11975 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM");
11976 if (error != GL_NO_ERROR) {
11977 RestoreCurrentTextureBindings(&state_, GL_TEXTURE_2D);
11978 return;
11981 texture_manager()->SetLevelInfo(
11982 dest_texture_ref, GL_TEXTURE_2D, 0, internal_format, source_width,
11983 source_height, 1, 0, internal_format, dest_type, true);
11984 } else {
11985 texture_manager()->SetLevelCleared(dest_texture_ref, GL_TEXTURE_2D, 0,
11986 true);
11989 ScopedModifyPixels modify(dest_texture_ref);
11991 // Try using GLImage::CopyTexSubImage when possible.
11992 bool unpack_premultiply_alpha_change =
11993 unpack_premultiply_alpha_ ^ unpack_unpremultiply_alpha_;
11994 if (image && !unpack_flip_y_ && !unpack_premultiply_alpha_change) {
11995 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
11996 if (image->CopyTexSubImage(GL_TEXTURE_2D, gfx::Point(0, 0),
11997 gfx::Rect(0, 0, source_width, source_height))) {
11998 return;
12002 DoWillUseTexImageIfNeeded(source_texture, source_texture->target());
12004 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
12005 // before presenting.
12006 if (source_texture->target() == GL_TEXTURE_EXTERNAL_OES) {
12007 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
12008 // instead of using kIdentityMatrix crbug.com/226218.
12009 copy_texture_CHROMIUM_->DoCopyTextureWithTransform(
12010 this, source_texture->target(), source_texture->service_id(),
12011 dest_texture->service_id(), source_width, source_height, unpack_flip_y_,
12012 unpack_premultiply_alpha_, unpack_unpremultiply_alpha_,
12013 kIdentityMatrix);
12014 } else {
12015 copy_texture_CHROMIUM_->DoCopyTexture(
12016 this, source_texture->target(), source_texture->service_id(),
12017 source_internal_format, dest_texture->service_id(), internal_format,
12018 source_width, source_height, unpack_flip_y_, unpack_premultiply_alpha_,
12019 unpack_unpremultiply_alpha_);
12022 DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
12025 void GLES2DecoderImpl::DoCopySubTextureCHROMIUM(GLenum target,
12026 GLuint source_id,
12027 GLuint dest_id,
12028 GLint xoffset,
12029 GLint yoffset,
12030 GLint x,
12031 GLint y,
12032 GLsizei width,
12033 GLsizei height) {
12034 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopySubTextureCHROMIUM");
12036 TextureRef* source_texture_ref = GetTexture(source_id);
12037 TextureRef* dest_texture_ref = GetTexture(dest_id);
12038 Texture* source_texture = source_texture_ref->texture();
12039 Texture* dest_texture = dest_texture_ref->texture();
12040 int source_width = 0;
12041 int source_height = 0;
12042 gfx::GLImage* image =
12043 source_texture->GetLevelImage(source_texture->target(), 0);
12044 if (image) {
12045 gfx::Size size = image->GetSize();
12046 source_width = size.width();
12047 source_height = size.height();
12048 if (source_width <= 0 || source_height <= 0) {
12049 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
12050 "invalid image size");
12051 return;
12053 } else {
12054 if (!source_texture->GetLevelSize(source_texture->target(), 0,
12055 &source_width, &source_height, nullptr)) {
12056 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
12057 "source texture has no level 0");
12058 return;
12061 // Check that this type of texture is allowed.
12062 if (!texture_manager()->ValidForTarget(source_texture->target(), 0,
12063 source_width, source_height, 1)) {
12064 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
12065 "source texture bad dimensions");
12066 return;
12070 GLenum source_type = 0;
12071 GLenum source_internal_format = 0;
12072 source_texture->GetLevelType(source_texture->target(), 0, &source_type,
12073 &source_internal_format);
12074 if (!source_texture->ValidForTexture(source_texture->target(), 0, x, y, 0,
12075 width, height, 1, source_type)) {
12076 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
12077 "source texture bad dimensions.");
12078 return;
12081 GLenum dest_type = 0;
12082 GLenum dest_internal_format = 0;
12083 bool dest_level_defined = dest_texture->GetLevelType(
12084 dest_texture->target(), 0, &dest_type, &dest_internal_format);
12085 if (!dest_level_defined) {
12086 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCopySubTextureCHROMIUM",
12087 "destination texture is not defined");
12088 return;
12090 if (!dest_texture->ValidForTexture(dest_texture->target(), 0, xoffset,
12091 yoffset, 0, width, height, 1, dest_type)) {
12092 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
12093 "destination texture bad dimensions.");
12094 return;
12097 if (!ValidateCopyTextureCHROMIUM("glCopySubTextureCHROMIUM", target,
12098 source_texture_ref, dest_texture_ref,
12099 dest_internal_format)) {
12100 return;
12103 // Clear the source texture if necessary.
12104 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref,
12105 source_texture->target(), 0)) {
12106 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopySubTextureCHROMIUM",
12107 "source texture dimensions too big");
12108 return;
12111 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
12112 // needed because it takes 10s of milliseconds to initialize.
12113 if (!copy_texture_CHROMIUM_.get()) {
12114 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopySubTextureCHROMIUM");
12115 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
12116 copy_texture_CHROMIUM_->Initialize(this);
12117 RestoreCurrentFramebufferBindings();
12118 if (LOCAL_PEEK_GL_ERROR("glCopySubTextureCHROMIUM") != GL_NO_ERROR)
12119 return;
12122 int dest_width = 0;
12123 int dest_height = 0;
12124 bool ok = dest_texture->GetLevelSize(
12125 GL_TEXTURE_2D, 0, &dest_width, &dest_height, nullptr);
12126 DCHECK(ok);
12127 if (xoffset != 0 || yoffset != 0 || width != dest_width ||
12128 height != dest_height) {
12129 if (!texture_manager()->ClearTextureLevel(this, dest_texture_ref, target,
12130 0)) {
12131 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopySubTextureCHROMIUM",
12132 "destination texture dimensions too big");
12133 return;
12135 } else {
12136 texture_manager()->SetLevelCleared(dest_texture_ref, GL_TEXTURE_2D, 0,
12137 true);
12140 ScopedModifyPixels modify(dest_texture_ref);
12142 // Try using GLImage::CopyTexSubImage when possible.
12143 bool unpack_premultiply_alpha_change =
12144 unpack_premultiply_alpha_ ^ unpack_unpremultiply_alpha_;
12145 if (image && !unpack_flip_y_ && !unpack_premultiply_alpha_change) {
12146 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
12147 if (image->CopyTexSubImage(GL_TEXTURE_2D, gfx::Point(xoffset, yoffset),
12148 gfx::Rect(x, y, width, height))) {
12149 return;
12153 DoWillUseTexImageIfNeeded(source_texture, source_texture->target());
12155 // TODO(hkuang): get the StreamTexture transform matrix in GPU process.
12156 // crbug.com/226218.
12157 copy_texture_CHROMIUM_->DoCopySubTexture(
12158 this, source_texture->target(), source_texture->service_id(),
12159 source_internal_format, dest_texture->service_id(), dest_internal_format,
12160 xoffset, yoffset, x, y, width, height, dest_width, dest_height,
12161 source_width, source_height, unpack_flip_y_, unpack_premultiply_alpha_,
12162 unpack_unpremultiply_alpha_);
12164 DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
12167 static GLenum ExtractTypeFromStorageFormat(GLenum internalformat) {
12168 switch (internalformat) {
12169 case GL_RGB565:
12170 return GL_UNSIGNED_SHORT_5_6_5;
12171 case GL_RGBA4:
12172 return GL_UNSIGNED_SHORT_4_4_4_4;
12173 case GL_RGB5_A1:
12174 return GL_UNSIGNED_SHORT_5_5_5_1;
12175 case GL_RGB8_OES:
12176 return GL_UNSIGNED_BYTE;
12177 case GL_RGBA8_OES:
12178 return GL_UNSIGNED_BYTE;
12179 case GL_LUMINANCE8_ALPHA8_EXT:
12180 return GL_UNSIGNED_BYTE;
12181 case GL_LUMINANCE8_EXT:
12182 return GL_UNSIGNED_BYTE;
12183 case GL_ALPHA8_EXT:
12184 return GL_UNSIGNED_BYTE;
12185 case GL_RGBA32F_EXT:
12186 return GL_FLOAT;
12187 case GL_RGB32F_EXT:
12188 return GL_FLOAT;
12189 case GL_ALPHA32F_EXT:
12190 return GL_FLOAT;
12191 case GL_LUMINANCE32F_EXT:
12192 return GL_FLOAT;
12193 case GL_LUMINANCE_ALPHA32F_EXT:
12194 return GL_FLOAT;
12195 case GL_RGBA16F_EXT:
12196 return GL_HALF_FLOAT_OES;
12197 case GL_RGB16F_EXT:
12198 return GL_HALF_FLOAT_OES;
12199 case GL_ALPHA16F_EXT:
12200 return GL_HALF_FLOAT_OES;
12201 case GL_LUMINANCE16F_EXT:
12202 return GL_HALF_FLOAT_OES;
12203 case GL_LUMINANCE_ALPHA16F_EXT:
12204 return GL_HALF_FLOAT_OES;
12205 case GL_BGRA8_EXT:
12206 return GL_UNSIGNED_BYTE;
12207 default:
12208 return GL_NONE;
12212 void GLES2DecoderImpl::DoTexStorage2DEXT(
12213 GLenum target,
12214 GLint levels,
12215 GLenum internal_format,
12216 GLsizei width,
12217 GLsizei height) {
12218 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT",
12219 "width", width, "height", height);
12220 if (!texture_manager()->ValidForTarget(target, 0, width, height, 1) ||
12221 TextureManager::ComputeMipMapCount(target, width, height, 1) < levels) {
12222 LOCAL_SET_GL_ERROR(
12223 GL_INVALID_VALUE, "glTexStorage2DEXT", "dimensions out of range");
12224 return;
12226 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
12227 &state_, target);
12228 if (!texture_ref) {
12229 LOCAL_SET_GL_ERROR(
12230 GL_INVALID_OPERATION,
12231 "glTexStorage2DEXT", "unknown texture for target");
12232 return;
12234 Texture* texture = texture_ref->texture();
12235 if (texture->IsAttachedToFramebuffer()) {
12236 framebuffer_state_.clear_state_dirty = true;
12238 if (texture->IsImmutable()) {
12239 LOCAL_SET_GL_ERROR(
12240 GL_INVALID_OPERATION,
12241 "glTexStorage2DEXT", "texture is immutable");
12242 return;
12245 GLenum format = ExtractFormatFromStorageFormat(internal_format);
12246 GLenum type = ExtractTypeFromStorageFormat(internal_format);
12249 GLsizei level_width = width;
12250 GLsizei level_height = height;
12251 uint32 estimated_size = 0;
12252 for (int ii = 0; ii < levels; ++ii) {
12253 uint32 level_size = 0;
12254 if (!GLES2Util::ComputeImageDataSizes(
12255 level_width, level_height, 1, format, type, state_.unpack_alignment,
12256 &estimated_size, NULL, NULL) ||
12257 !SafeAddUint32(estimated_size, level_size, &estimated_size)) {
12258 LOCAL_SET_GL_ERROR(
12259 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "dimensions too large");
12260 return;
12262 level_width = std::max(1, level_width >> 1);
12263 level_height = std::max(1, level_height >> 1);
12265 if (!EnsureGPUMemoryAvailable(estimated_size)) {
12266 LOCAL_SET_GL_ERROR(
12267 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "out of memory");
12268 return;
12272 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexStorage2DEXT");
12273 glTexStorage2DEXT(target, levels, internal_format, width, height);
12274 GLenum error = LOCAL_PEEK_GL_ERROR("glTexStorage2DEXT");
12275 if (error == GL_NO_ERROR) {
12276 GLsizei level_width = width;
12277 GLsizei level_height = height;
12278 for (int ii = 0; ii < levels; ++ii) {
12279 texture_manager()->SetLevelInfo(
12280 texture_ref, target, ii, format,
12281 level_width, level_height, 1, 0, format, type, false);
12282 level_width = std::max(1, level_width >> 1);
12283 level_height = std::max(1, level_height >> 1);
12285 texture->SetImmutable(true);
12289 error::Error GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
12290 uint32 immediate_data_size,
12291 const void* cmd_data) {
12292 return error::kUnknownCommand;
12295 void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target,
12296 const GLbyte* data) {
12297 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureCHROMIUM",
12298 "context", logger_.GetLogPrefix(),
12299 "mailbox[0]", static_cast<unsigned char>(data[0]));
12301 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
12302 &state_, target);
12303 ProduceTextureRef("glProduceTextureCHROMIUM", texture_ref, target, data);
12306 void GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM(GLuint client_id,
12307 GLenum target, const GLbyte* data) {
12308 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM",
12309 "context", logger_.GetLogPrefix(),
12310 "mailbox[0]", static_cast<unsigned char>(data[0]));
12312 ProduceTextureRef("glProduceTextureDirectCHROMIUM", GetTexture(client_id),
12313 target, data);
12316 void GLES2DecoderImpl::ProduceTextureRef(std::string func_name,
12317 TextureRef* texture_ref, GLenum target, const GLbyte* data) {
12318 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
12319 DLOG_IF(ERROR, !mailbox.Verify()) << func_name << " was passed a "
12320 "mailbox that was not generated by "
12321 "GenMailboxCHROMIUM.";
12323 if (!texture_ref) {
12324 LOCAL_SET_GL_ERROR(
12325 GL_INVALID_OPERATION, func_name.c_str(), "unknown texture for target");
12326 return;
12329 Texture* produced = texture_manager()->Produce(texture_ref);
12330 if (!produced) {
12331 LOCAL_SET_GL_ERROR(
12332 GL_INVALID_OPERATION, func_name.c_str(), "invalid texture");
12333 return;
12336 if (produced->target() != target) {
12337 LOCAL_SET_GL_ERROR(
12338 GL_INVALID_OPERATION, func_name.c_str(), "invalid target");
12339 return;
12342 group_->mailbox_manager()->ProduceTexture(mailbox, produced);
12345 void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target,
12346 const GLbyte* data) {
12347 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoConsumeTextureCHROMIUM",
12348 "context", logger_.GetLogPrefix(),
12349 "mailbox[0]", static_cast<unsigned char>(data[0]));
12350 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
12351 DLOG_IF(ERROR, !mailbox.Verify()) << "ConsumeTextureCHROMIUM was passed a "
12352 "mailbox that was not generated by "
12353 "GenMailboxCHROMIUM.";
12355 scoped_refptr<TextureRef> texture_ref =
12356 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
12357 if (!texture_ref.get()) {
12358 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
12359 "glConsumeTextureCHROMIUM",
12360 "unknown texture for target");
12361 return;
12363 GLuint client_id = texture_ref->client_id();
12364 if (!client_id) {
12365 LOCAL_SET_GL_ERROR(
12366 GL_INVALID_OPERATION,
12367 "glConsumeTextureCHROMIUM", "unknown texture for target");
12368 return;
12370 Texture* texture = group_->mailbox_manager()->ConsumeTexture(mailbox);
12371 if (!texture) {
12372 LOCAL_SET_GL_ERROR(
12373 GL_INVALID_OPERATION,
12374 "glConsumeTextureCHROMIUM", "invalid mailbox name");
12375 return;
12377 if (texture->target() != target) {
12378 LOCAL_SET_GL_ERROR(
12379 GL_INVALID_OPERATION,
12380 "glConsumeTextureCHROMIUM", "invalid target");
12381 return;
12384 DeleteTexturesHelper(1, &client_id);
12385 texture_ref = texture_manager()->Consume(client_id, texture);
12386 glBindTexture(target, texture_ref->service_id());
12388 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
12389 unit.bind_target = target;
12390 switch (target) {
12391 case GL_TEXTURE_2D:
12392 unit.bound_texture_2d = texture_ref;
12393 break;
12394 case GL_TEXTURE_CUBE_MAP:
12395 unit.bound_texture_cube_map = texture_ref;
12396 break;
12397 case GL_TEXTURE_EXTERNAL_OES:
12398 unit.bound_texture_external_oes = texture_ref;
12399 break;
12400 case GL_TEXTURE_RECTANGLE_ARB:
12401 unit.bound_texture_rectangle_arb = texture_ref;
12402 break;
12403 default:
12404 NOTREACHED(); // Validation should prevent us getting here.
12405 break;
12409 void GLES2DecoderImpl::EnsureTextureForClientId(
12410 GLenum target,
12411 GLuint client_id) {
12412 TextureRef* texture_ref = GetTexture(client_id);
12413 if (!texture_ref) {
12414 GLuint service_id;
12415 glGenTextures(1, &service_id);
12416 DCHECK_NE(0u, service_id);
12417 texture_ref = CreateTexture(client_id, service_id);
12418 texture_manager()->SetTarget(texture_ref, target);
12419 glBindTexture(target, service_id);
12420 RestoreCurrentTextureBindings(&state_, target);
12424 // If CreateAndConsumeTexture fails we still need to ensure that the client_id
12425 // provided is associated with a service_id/TextureRef for consistency, even if
12426 // the resulting texture is incomplete.
12427 error::Error GLES2DecoderImpl::HandleCreateAndConsumeTextureCHROMIUMImmediate(
12428 uint32_t immediate_data_size,
12429 const void* cmd_data) {
12430 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate& c =
12431 *static_cast<
12432 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate*>(
12433 cmd_data);
12434 GLenum target = static_cast<GLenum>(c.target);
12435 uint32_t data_size;
12436 if (!ComputeDataSize(1, sizeof(GLbyte), 64, &data_size)) {
12437 return error::kOutOfBounds;
12439 if (data_size > immediate_data_size) {
12440 return error::kOutOfBounds;
12442 const GLbyte* mailbox =
12443 GetImmediateDataAs<const GLbyte*>(c, data_size, immediate_data_size);
12444 if (!validators_->texture_bind_target.IsValid(target)) {
12445 LOCAL_SET_GL_ERROR_INVALID_ENUM(
12446 "glCreateAndConsumeTextureCHROMIUM", target, "target");
12447 return error::kNoError;
12449 if (mailbox == NULL) {
12450 return error::kOutOfBounds;
12452 uint32_t client_id = c.client_id;
12453 DoCreateAndConsumeTextureCHROMIUM(target, mailbox, client_id);
12454 return error::kNoError;
12457 void GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM(GLenum target,
12458 const GLbyte* data, GLuint client_id) {
12459 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM",
12460 "context", logger_.GetLogPrefix(),
12461 "mailbox[0]", static_cast<unsigned char>(data[0]));
12462 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
12463 DLOG_IF(ERROR, !mailbox.Verify()) << "CreateAndConsumeTextureCHROMIUM was "
12464 "passed a mailbox that was not "
12465 "generated by GenMailboxCHROMIUM.";
12467 TextureRef* texture_ref = GetTexture(client_id);
12468 if (texture_ref) {
12469 // No need to call EnsureTextureForClientId here, the client_id already has
12470 // an associated texture.
12471 LOCAL_SET_GL_ERROR(
12472 GL_INVALID_OPERATION,
12473 "glCreateAndConsumeTextureCHROMIUM", "client id already in use");
12474 return;
12476 Texture* texture = group_->mailbox_manager()->ConsumeTexture(mailbox);
12477 if (!texture) {
12478 EnsureTextureForClientId(target, client_id);
12479 LOCAL_SET_GL_ERROR(
12480 GL_INVALID_OPERATION,
12481 "glCreateAndConsumeTextureCHROMIUM", "invalid mailbox name");
12482 return;
12485 if (texture->target() != target) {
12486 EnsureTextureForClientId(target, client_id);
12487 LOCAL_SET_GL_ERROR(
12488 GL_INVALID_OPERATION,
12489 "glCreateAndConsumeTextureCHROMIUM", "invalid target");
12490 return;
12493 texture_ref = texture_manager()->Consume(client_id, texture);
12496 bool GLES2DecoderImpl::DoIsValuebufferCHROMIUM(GLuint client_id) {
12497 const Valuebuffer* valuebuffer = GetValuebuffer(client_id);
12498 return valuebuffer && valuebuffer->IsValid();
12501 void GLES2DecoderImpl::DoBindValueBufferCHROMIUM(GLenum target,
12502 GLuint client_id) {
12503 Valuebuffer* valuebuffer = NULL;
12504 if (client_id != 0) {
12505 valuebuffer = GetValuebuffer(client_id);
12506 if (!valuebuffer) {
12507 if (!group_->bind_generates_resource()) {
12508 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glBindValuebufferCHROMIUM",
12509 "id not generated by glBindValuebufferCHROMIUM");
12510 return;
12513 // It's a new id so make a valuebuffer for it.
12514 CreateValuebuffer(client_id);
12515 valuebuffer = GetValuebuffer(client_id);
12517 valuebuffer->MarkAsValid();
12519 state_.bound_valuebuffer = valuebuffer;
12522 void GLES2DecoderImpl::DoSubscribeValueCHROMIUM(GLenum target,
12523 GLenum subscription) {
12524 if (!CheckCurrentValuebuffer("glSubscribeValueCHROMIUM")) {
12525 return;
12527 state_.bound_valuebuffer.get()->AddSubscription(subscription);
12530 void GLES2DecoderImpl::DoPopulateSubscribedValuesCHROMIUM(GLenum target) {
12531 if (!CheckCurrentValuebuffer("glPopulateSubscribedValuesCHROMIUM")) {
12532 return;
12534 valuebuffer_manager()->UpdateValuebufferState(state_.bound_valuebuffer.get());
12537 void GLES2DecoderImpl::DoUniformValueBufferCHROMIUM(GLint location,
12538 GLenum target,
12539 GLenum subscription) {
12540 if (!CheckCurrentValuebufferForSubscription(
12541 subscription, "glPopulateSubscribedValuesCHROMIUM")) {
12542 return;
12544 if (!CheckSubscriptionTarget(location, subscription,
12545 "glPopulateSubscribedValuesCHROMIUM")) {
12546 return;
12548 const ValueState* state =
12549 state_.bound_valuebuffer.get()->GetState(subscription);
12550 if (state) {
12551 switch (subscription) {
12552 case GL_MOUSE_POSITION_CHROMIUM:
12553 DoUniform2iv(location, 1, state->int_value);
12554 break;
12555 default:
12556 NOTREACHED() << "Unhandled uniform subscription target "
12557 << subscription;
12558 break;
12563 void GLES2DecoderImpl::DoInsertEventMarkerEXT(
12564 GLsizei length, const GLchar* marker) {
12565 if (!marker) {
12566 marker = "";
12568 debug_marker_manager_.SetMarker(
12569 length ? std::string(marker, length) : std::string(marker));
12572 void GLES2DecoderImpl::DoPushGroupMarkerEXT(
12573 GLsizei length, const GLchar* marker) {
12574 if (!marker) {
12575 marker = "";
12577 std::string name = length ? std::string(marker, length) : std::string(marker);
12578 debug_marker_manager_.PushGroup(name);
12579 gpu_tracer_->Begin(TRACE_DISABLED_BY_DEFAULT("gpu_group_marker"), name,
12580 kTraceGroupMarker);
12583 void GLES2DecoderImpl::DoPopGroupMarkerEXT(void) {
12584 debug_marker_manager_.PopGroup();
12585 gpu_tracer_->End(kTraceGroupMarker);
12588 void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(
12589 GLenum target, GLint image_id) {
12590 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM");
12592 if (target == GL_TEXTURE_CUBE_MAP) {
12593 LOCAL_SET_GL_ERROR(
12594 GL_INVALID_ENUM,
12595 "glBindTexImage2DCHROMIUM", "invalid target");
12596 return;
12599 // Default target might be conceptually valid, but disallow it to avoid
12600 // accidents.
12601 TextureRef* texture_ref =
12602 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
12603 if (!texture_ref) {
12604 LOCAL_SET_GL_ERROR(
12605 GL_INVALID_OPERATION,
12606 "glBindTexImage2DCHROMIUM", "no texture bound");
12607 return;
12610 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
12611 if (!gl_image) {
12612 LOCAL_SET_GL_ERROR(
12613 GL_INVALID_OPERATION,
12614 "glBindTexImage2DCHROMIUM", "no image found with the given ID");
12615 return;
12619 ScopedGLErrorSuppressor suppressor(
12620 "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", GetErrorState());
12621 if (!gl_image->BindTexImage(target)) {
12622 LOCAL_SET_GL_ERROR(
12623 GL_INVALID_OPERATION,
12624 "glBindTexImage2DCHROMIUM", "fail to bind image with the given ID");
12625 return;
12629 gfx::Size size = gl_image->GetSize();
12630 texture_manager()->SetLevelInfo(
12631 texture_ref, target, 0, gl_image->GetInternalFormat(),
12632 size.width(), size.height(), 1, 0,
12633 gl_image->GetInternalFormat(), GL_UNSIGNED_BYTE, true);
12634 texture_manager()->SetLevelImage(texture_ref, target, 0, gl_image);
12637 void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(
12638 GLenum target, GLint image_id) {
12639 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM");
12641 // Default target might be conceptually valid, but disallow it to avoid
12642 // accidents.
12643 TextureRef* texture_ref =
12644 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
12645 if (!texture_ref) {
12646 LOCAL_SET_GL_ERROR(
12647 GL_INVALID_OPERATION,
12648 "glReleaseTexImage2DCHROMIUM", "no texture bound");
12649 return;
12652 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
12653 if (!gl_image) {
12654 LOCAL_SET_GL_ERROR(
12655 GL_INVALID_OPERATION,
12656 "glReleaseTexImage2DCHROMIUM", "no image found with the given ID");
12657 return;
12660 // Do nothing when image is not currently bound.
12661 if (texture_ref->texture()->GetLevelImage(target, 0) != gl_image)
12662 return;
12665 ScopedGLErrorSuppressor suppressor(
12666 "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", GetErrorState());
12667 gl_image->ReleaseTexImage(target);
12670 texture_manager()->SetLevelInfo(
12671 texture_ref, target, 0, gl_image->GetInternalFormat(), 0, 0, 1, 0,
12672 gl_image->GetInternalFormat(), GL_UNSIGNED_BYTE, false);
12675 error::Error GLES2DecoderImpl::HandleTraceBeginCHROMIUM(
12676 uint32 immediate_data_size,
12677 const void* cmd_data) {
12678 const gles2::cmds::TraceBeginCHROMIUM& c =
12679 *static_cast<const gles2::cmds::TraceBeginCHROMIUM*>(cmd_data);
12680 Bucket* category_bucket = GetBucket(c.category_bucket_id);
12681 Bucket* name_bucket = GetBucket(c.name_bucket_id);
12682 if (!category_bucket || category_bucket->size() == 0 ||
12683 !name_bucket || name_bucket->size() == 0) {
12684 return error::kInvalidArguments;
12687 std::string category_name;
12688 std::string trace_name;
12689 if (!category_bucket->GetAsString(&category_name) ||
12690 !name_bucket->GetAsString(&trace_name)) {
12691 return error::kInvalidArguments;
12694 if (!gpu_tracer_->Begin(category_name, trace_name, kTraceCHROMIUM)) {
12695 LOCAL_SET_GL_ERROR(
12696 GL_INVALID_OPERATION,
12697 "glTraceBeginCHROMIUM", "unable to create begin trace");
12698 return error::kNoError;
12700 return error::kNoError;
12703 void GLES2DecoderImpl::DoTraceEndCHROMIUM() {
12704 if (!gpu_tracer_->End(kTraceCHROMIUM)) {
12705 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
12706 "glTraceEndCHROMIUM", "no trace begin found");
12707 return;
12711 void GLES2DecoderImpl::DoDrawBuffersEXT(
12712 GLsizei count, const GLenum* bufs) {
12713 if (count > static_cast<GLsizei>(group_->max_draw_buffers())) {
12714 LOCAL_SET_GL_ERROR(
12715 GL_INVALID_VALUE,
12716 "glDrawBuffersEXT", "greater than GL_MAX_DRAW_BUFFERS_EXT");
12717 return;
12720 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
12721 if (framebuffer) {
12722 for (GLsizei i = 0; i < count; ++i) {
12723 if (bufs[i] != static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i) &&
12724 bufs[i] != GL_NONE) {
12725 LOCAL_SET_GL_ERROR(
12726 GL_INVALID_OPERATION,
12727 "glDrawBuffersEXT",
12728 "bufs[i] not GL_NONE or GL_COLOR_ATTACHMENTi_EXT");
12729 return;
12732 glDrawBuffersARB(count, bufs);
12733 framebuffer->SetDrawBuffers(count, bufs);
12734 } else { // backbuffer
12735 if (count > 1 ||
12736 (bufs[0] != GL_BACK && bufs[0] != GL_NONE)) {
12737 LOCAL_SET_GL_ERROR(
12738 GL_INVALID_OPERATION,
12739 "glDrawBuffersEXT",
12740 "more than one buffer or bufs not GL_NONE or GL_BACK");
12741 return;
12743 GLenum mapped_buf = bufs[0];
12744 if (GetBackbufferServiceId() != 0 && // emulated backbuffer
12745 bufs[0] == GL_BACK) {
12746 mapped_buf = GL_COLOR_ATTACHMENT0;
12748 glDrawBuffersARB(count, &mapped_buf);
12749 group_->set_draw_buffer(bufs[0]);
12753 void GLES2DecoderImpl::DoLoseContextCHROMIUM(GLenum current, GLenum other) {
12754 MarkContextLost(GetContextLostReasonFromResetStatus(current));
12755 group_->LoseContexts(GetContextLostReasonFromResetStatus(other));
12756 reset_by_robustness_extension_ = true;
12759 void GLES2DecoderImpl::DoMatrixLoadfCHROMIUM(GLenum matrix_mode,
12760 const GLfloat* matrix) {
12761 DCHECK(matrix_mode == GL_PATH_PROJECTION_CHROMIUM ||
12762 matrix_mode == GL_PATH_MODELVIEW_CHROMIUM);
12763 if (!features().chromium_path_rendering) {
12764 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
12765 "glMatrixLoadfCHROMIUM",
12766 "function not available");
12767 return;
12770 GLfloat* target_matrix = matrix_mode == GL_PATH_PROJECTION_CHROMIUM
12771 ? state_.projection_matrix
12772 : state_.modelview_matrix;
12773 memcpy(target_matrix, matrix, sizeof(GLfloat) * 16);
12774 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
12775 // since the values of the _NV and _CHROMIUM tokens match.
12776 glMatrixLoadfEXT(matrix_mode, matrix);
12779 void GLES2DecoderImpl::DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode) {
12780 DCHECK(matrix_mode == GL_PATH_PROJECTION_CHROMIUM ||
12781 matrix_mode == GL_PATH_MODELVIEW_CHROMIUM);
12783 if (!features().chromium_path_rendering) {
12784 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
12785 "glMatrixLoadIdentityCHROMIUM",
12786 "function not available");
12787 return;
12790 GLfloat* target_matrix = matrix_mode == GL_PATH_PROJECTION_CHROMIUM
12791 ? state_.projection_matrix
12792 : state_.modelview_matrix;
12793 memcpy(target_matrix, kIdentityMatrix, sizeof(kIdentityMatrix));
12794 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
12795 // since the values of the _NV and _CHROMIUM tokens match.
12796 glMatrixLoadIdentityEXT(matrix_mode);
12799 bool GLES2DecoderImpl::ValidateAsyncTransfer(
12800 const char* function_name,
12801 TextureRef* texture_ref,
12802 GLenum target,
12803 GLint level,
12804 const void * data) {
12805 // We only support async uploads to 2D textures for now.
12806 if (GL_TEXTURE_2D != target) {
12807 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
12808 return false;
12810 // We only support uploads to level zero for now.
12811 if (level != 0) {
12812 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "level != 0");
12813 return false;
12815 // A transfer buffer must be bound, even for asyncTexImage2D.
12816 if (data == NULL) {
12817 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, "buffer == 0");
12818 return false;
12820 // We only support one async transfer in progress.
12821 if (!texture_ref ||
12822 async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
12823 LOCAL_SET_GL_ERROR(
12824 GL_INVALID_OPERATION,
12825 function_name, "transfer already in progress");
12826 return false;
12828 return true;
12831 base::Closure GLES2DecoderImpl::AsyncUploadTokenCompletionClosure(
12832 uint32 async_upload_token,
12833 uint32 sync_data_shm_id,
12834 uint32 sync_data_shm_offset) {
12835 scoped_refptr<gpu::Buffer> buffer = GetSharedMemoryBuffer(sync_data_shm_id);
12836 if (!buffer.get() ||
12837 !buffer->GetDataAddress(sync_data_shm_offset, sizeof(AsyncUploadSync)))
12838 return base::Closure();
12840 AsyncMemoryParams mem_params(buffer,
12841 sync_data_shm_offset,
12842 sizeof(AsyncUploadSync));
12844 scoped_refptr<AsyncUploadTokenCompletionObserver> observer(
12845 new AsyncUploadTokenCompletionObserver(async_upload_token));
12847 return base::Bind(
12848 &AsyncPixelTransferManager::AsyncNotifyCompletion,
12849 base::Unretained(GetAsyncPixelTransferManager()),
12850 mem_params,
12851 observer);
12854 error::Error GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM(
12855 uint32 immediate_data_size,
12856 const void* cmd_data) {
12857 const gles2::cmds::AsyncTexImage2DCHROMIUM& c =
12858 *static_cast<const gles2::cmds::AsyncTexImage2DCHROMIUM*>(cmd_data);
12859 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM");
12860 GLenum target = static_cast<GLenum>(c.target);
12861 GLint level = static_cast<GLint>(c.level);
12862 GLenum internal_format = static_cast<GLenum>(c.internalformat);
12863 GLsizei width = static_cast<GLsizei>(c.width);
12864 GLsizei height = static_cast<GLsizei>(c.height);
12865 GLint border = static_cast<GLint>(c.border);
12866 GLenum format = static_cast<GLenum>(c.format);
12867 GLenum type = static_cast<GLenum>(c.type);
12868 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
12869 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
12870 uint32 pixels_size;
12871 uint32 async_upload_token = static_cast<uint32>(c.async_upload_token);
12872 uint32 sync_data_shm_id = static_cast<uint32>(c.sync_data_shm_id);
12873 uint32 sync_data_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
12875 base::ScopedClosureRunner scoped_completion_callback;
12876 if (async_upload_token) {
12877 base::Closure completion_closure =
12878 AsyncUploadTokenCompletionClosure(async_upload_token,
12879 sync_data_shm_id,
12880 sync_data_shm_offset);
12881 if (completion_closure.is_null())
12882 return error::kInvalidArguments;
12884 scoped_completion_callback.Reset(completion_closure);
12887 // TODO(epenner): Move this and copies of this memory validation
12888 // into ValidateTexImage2D step.
12889 if (!GLES2Util::ComputeImageDataSizes(
12890 width, height, 1, format, type, state_.unpack_alignment, &pixels_size,
12891 NULL, NULL)) {
12892 return error::kOutOfBounds;
12894 const void* pixels = NULL;
12895 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
12896 pixels = GetSharedMemoryAs<const void*>(
12897 pixels_shm_id, pixels_shm_offset, pixels_size);
12898 if (!pixels) {
12899 return error::kOutOfBounds;
12903 TextureManager::DoTexImageArguments args = {
12904 target, level, internal_format, width, height, 1, border, format, type,
12905 pixels, pixels_size, TextureManager::DoTexImageArguments::kTexImage2D };
12906 TextureRef* texture_ref;
12907 // All the normal glTexSubImage2D validation.
12908 if (!texture_manager()->ValidateTexImage(
12909 &state_, "glAsyncTexImage2DCHROMIUM", args, &texture_ref)) {
12910 return error::kNoError;
12913 // Extra async validation.
12914 Texture* texture = texture_ref->texture();
12915 if (!ValidateAsyncTransfer(
12916 "glAsyncTexImage2DCHROMIUM", texture_ref, target, level, pixels))
12917 return error::kNoError;
12919 // Don't allow async redefinition of a textures.
12920 if (texture->IsDefined()) {
12921 LOCAL_SET_GL_ERROR(
12922 GL_INVALID_OPERATION,
12923 "glAsyncTexImage2DCHROMIUM", "already defined");
12924 return error::kNoError;
12927 if (!EnsureGPUMemoryAvailable(pixels_size)) {
12928 LOCAL_SET_GL_ERROR(
12929 GL_OUT_OF_MEMORY, "glAsyncTexImage2DCHROMIUM", "out of memory");
12930 return error::kNoError;
12933 // Setup the parameters.
12934 AsyncTexImage2DParams tex_params = {
12935 target, level, static_cast<GLenum>(internal_format),
12936 width, height, border, format, type};
12937 AsyncMemoryParams mem_params(
12938 GetSharedMemoryBuffer(c.pixels_shm_id), c.pixels_shm_offset, pixels_size);
12940 // Set up the async state if needed, and make the texture
12941 // immutable so the async state stays valid. The level info
12942 // is set up lazily when the transfer completes.
12943 AsyncPixelTransferDelegate* delegate =
12944 async_pixel_transfer_manager_->CreatePixelTransferDelegate(texture_ref,
12945 tex_params);
12946 texture->SetImmutable(true);
12948 delegate->AsyncTexImage2D(
12949 tex_params,
12950 mem_params,
12951 base::Bind(&TextureManager::SetLevelInfoFromParams,
12952 // The callback is only invoked if the transfer delegate still
12953 // exists, which implies through manager->texture_ref->state
12954 // ownership that both of these pointers are valid.
12955 base::Unretained(texture_manager()),
12956 base::Unretained(texture_ref),
12957 tex_params));
12958 return error::kNoError;
12961 error::Error GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM(
12962 uint32 immediate_data_size,
12963 const void* cmd_data) {
12964 const gles2::cmds::AsyncTexSubImage2DCHROMIUM& c =
12965 *static_cast<const gles2::cmds::AsyncTexSubImage2DCHROMIUM*>(cmd_data);
12966 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM");
12967 GLenum target = static_cast<GLenum>(c.target);
12968 GLint level = static_cast<GLint>(c.level);
12969 GLint xoffset = static_cast<GLint>(c.xoffset);
12970 GLint yoffset = static_cast<GLint>(c.yoffset);
12971 GLsizei width = static_cast<GLsizei>(c.width);
12972 GLsizei height = static_cast<GLsizei>(c.height);
12973 GLenum format = static_cast<GLenum>(c.format);
12974 GLenum type = static_cast<GLenum>(c.type);
12975 uint32 async_upload_token = static_cast<uint32>(c.async_upload_token);
12976 uint32 sync_data_shm_id = static_cast<uint32>(c.sync_data_shm_id);
12977 uint32 sync_data_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
12979 base::ScopedClosureRunner scoped_completion_callback;
12980 if (async_upload_token) {
12981 base::Closure completion_closure =
12982 AsyncUploadTokenCompletionClosure(async_upload_token,
12983 sync_data_shm_id,
12984 sync_data_shm_offset);
12985 if (completion_closure.is_null())
12986 return error::kInvalidArguments;
12988 scoped_completion_callback.Reset(completion_closure);
12991 // TODO(epenner): Move this and copies of this memory validation
12992 // into ValidateTexSubImage2D step.
12993 uint32 data_size;
12994 if (!GLES2Util::ComputeImageDataSizes(
12995 width, height, 1, format, type, state_.unpack_alignment, &data_size,
12996 NULL, NULL)) {
12997 return error::kOutOfBounds;
12999 const void* pixels = GetSharedMemoryAs<const void*>(
13000 c.data_shm_id, c.data_shm_offset, data_size);
13002 // All the normal glTexSubImage2D validation.
13003 error::Error error = error::kNoError;
13004 if (!ValidateTexSubImage2D(&error, "glAsyncTexSubImage2DCHROMIUM",
13005 target, level, xoffset, yoffset, width, height, format, type, pixels)) {
13006 return error;
13009 // Extra async validation.
13010 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
13011 &state_, target);
13012 Texture* texture = texture_ref->texture();
13013 if (!ValidateAsyncTransfer(
13014 "glAsyncTexSubImage2DCHROMIUM", texture_ref, target, level, pixels))
13015 return error::kNoError;
13017 // Guarantee async textures are always 'cleared' as follows:
13018 // - AsyncTexImage2D can not redefine an existing texture
13019 // - AsyncTexImage2D must initialize the entire image via non-null buffer.
13020 // - AsyncTexSubImage2D clears synchronously if not already cleared.
13021 // - Textures become immutable after an async call.
13022 // This way we know in all cases that an async texture is always clear.
13023 if (!texture->SafeToRenderFrom()) {
13024 if (!texture_manager()->ClearTextureLevel(this, texture_ref,
13025 target, level)) {
13026 LOCAL_SET_GL_ERROR(
13027 GL_OUT_OF_MEMORY,
13028 "glAsyncTexSubImage2DCHROMIUM", "dimensions too big");
13029 return error::kNoError;
13033 // Setup the parameters.
13034 AsyncTexSubImage2DParams tex_params = {target, level, xoffset, yoffset,
13035 width, height, format, type};
13036 AsyncMemoryParams mem_params(
13037 GetSharedMemoryBuffer(c.data_shm_id), c.data_shm_offset, data_size);
13038 AsyncPixelTransferDelegate* delegate =
13039 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
13040 if (!delegate) {
13041 // TODO(epenner): We may want to enforce exclusive use
13042 // of async APIs in which case this should become an error,
13043 // (the texture should have been async defined).
13044 AsyncTexImage2DParams define_params = {target, level,
13045 0, 0, 0, 0, 0, 0};
13046 texture->GetLevelSize(
13047 target, level, &define_params.width, &define_params.height, nullptr);
13048 texture->GetLevelType(
13049 target, level, &define_params.type, &define_params.internal_format);
13050 // Set up the async state if needed, and make the texture
13051 // immutable so the async state stays valid.
13052 delegate = async_pixel_transfer_manager_->CreatePixelTransferDelegate(
13053 texture_ref, define_params);
13054 texture->SetImmutable(true);
13057 delegate->AsyncTexSubImage2D(tex_params, mem_params);
13058 return error::kNoError;
13061 error::Error GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM(
13062 uint32 immediate_data_size,
13063 const void* cmd_data) {
13064 const gles2::cmds::WaitAsyncTexImage2DCHROMIUM& c =
13065 *static_cast<const gles2::cmds::WaitAsyncTexImage2DCHROMIUM*>(cmd_data);
13066 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
13067 GLenum target = static_cast<GLenum>(c.target);
13069 if (GL_TEXTURE_2D != target) {
13070 LOCAL_SET_GL_ERROR(
13071 GL_INVALID_ENUM, "glWaitAsyncTexImage2DCHROMIUM", "target");
13072 return error::kNoError;
13074 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
13075 &state_, target);
13076 if (!texture_ref) {
13077 LOCAL_SET_GL_ERROR(
13078 GL_INVALID_OPERATION,
13079 "glWaitAsyncTexImage2DCHROMIUM", "unknown texture");
13080 return error::kNoError;
13082 AsyncPixelTransferDelegate* delegate =
13083 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
13084 if (!delegate) {
13085 LOCAL_SET_GL_ERROR(
13086 GL_INVALID_OPERATION,
13087 "glWaitAsyncTexImage2DCHROMIUM", "No async transfer started");
13088 return error::kNoError;
13090 delegate->WaitForTransferCompletion();
13091 ProcessFinishedAsyncTransfers();
13092 return error::kNoError;
13095 error::Error GLES2DecoderImpl::HandleWaitAllAsyncTexImage2DCHROMIUM(
13096 uint32 immediate_data_size,
13097 const void* data) {
13098 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
13100 GetAsyncPixelTransferManager()->WaitAllAsyncTexImage2D();
13101 ProcessFinishedAsyncTransfers();
13102 return error::kNoError;
13105 error::Error GLES2DecoderImpl::HandleUniformBlockBinding(
13106 uint32_t immediate_data_size, const void* cmd_data) {
13107 if (!unsafe_es3_apis_enabled())
13108 return error::kUnknownCommand;
13109 const gles2::cmds::UniformBlockBinding& c =
13110 *static_cast<const gles2::cmds::UniformBlockBinding*>(cmd_data);
13111 GLuint client_id = c.program;
13112 GLuint index = static_cast<GLuint>(c.index);
13113 GLuint binding = static_cast<GLuint>(c.binding);
13114 Program* program = GetProgramInfoNotShader(
13115 client_id, "glUniformBlockBinding");
13116 if (!program) {
13117 return error::kNoError;
13119 GLuint service_id = program->service_id();
13120 glUniformBlockBinding(service_id, index, binding);
13121 return error::kNoError;
13124 error::Error GLES2DecoderImpl::HandleClientWaitSync(
13125 uint32_t immediate_data_size, const void* cmd_data) {
13126 if (!unsafe_es3_apis_enabled())
13127 return error::kUnknownCommand;
13128 const gles2::cmds::ClientWaitSync& c =
13129 *static_cast<const gles2::cmds::ClientWaitSync*>(cmd_data);
13130 GLuint sync = static_cast<GLuint>(c.sync);
13131 GLbitfield flags = static_cast<GLbitfield>(c.flags);
13132 GLuint64 timeout = GLES2Util::MapTwoUint32ToUint64(c.timeout_0, c.timeout_1);
13133 typedef cmds::ClientWaitSync::Result Result;
13134 Result* result_dst = GetSharedMemoryAs<Result*>(
13135 c.result_shm_id, c.result_shm_offset, sizeof(*result_dst));
13136 if (!result_dst) {
13137 return error::kOutOfBounds;
13139 if (*result_dst != GL_WAIT_FAILED) {
13140 return error::kInvalidArguments;
13142 GLsync service_sync = 0;
13143 if (!group_->GetSyncServiceId(sync, &service_sync)) {
13144 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "ClientWaitSync", "invalid sync");
13145 return error::kNoError;
13147 *result_dst = glClientWaitSync(service_sync, flags, timeout);
13148 return error::kNoError;
13151 error::Error GLES2DecoderImpl::HandleWaitSync(
13152 uint32_t immediate_data_size, const void* cmd_data) {
13153 if (!unsafe_es3_apis_enabled())
13154 return error::kUnknownCommand;
13155 const gles2::cmds::WaitSync& c =
13156 *static_cast<const gles2::cmds::WaitSync*>(cmd_data);
13157 GLuint sync = static_cast<GLuint>(c.sync);
13158 GLbitfield flags = static_cast<GLbitfield>(c.flags);
13159 GLuint64 timeout = GLES2Util::MapTwoUint32ToUint64(c.timeout_0, c.timeout_1);
13160 GLsync service_sync = 0;
13161 if (!group_->GetSyncServiceId(sync, &service_sync)) {
13162 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "WaitSync", "invalid sync");
13163 return error::kNoError;
13165 glWaitSync(service_sync, flags, timeout);
13166 return error::kNoError;
13169 error::Error GLES2DecoderImpl::HandleMapBufferRange(
13170 uint32_t immediate_data_size, const void* cmd_data) {
13171 if (!unsafe_es3_apis_enabled()) {
13172 return error::kUnknownCommand;
13174 const gles2::cmds::MapBufferRange& c =
13175 *static_cast<const gles2::cmds::MapBufferRange*>(cmd_data);
13176 GLenum target = static_cast<GLenum>(c.target);
13177 GLbitfield access = static_cast<GLbitfield>(c.access);
13178 GLintptr offset = static_cast<GLintptr>(c.offset);
13179 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
13181 typedef cmds::MapBufferRange::Result Result;
13182 Result* result = GetSharedMemoryAs<Result*>(
13183 c.result_shm_id, c.result_shm_offset, sizeof(*result));
13184 if (!result) {
13185 return error::kOutOfBounds;
13187 if (*result != 0) {
13188 *result = 0;
13189 return error::kInvalidArguments;
13191 int8_t* mem =
13192 GetSharedMemoryAs<int8_t*>(c.data_shm_id, c.data_shm_offset, size);
13193 if (!mem) {
13194 return error::kOutOfBounds;
13197 GLbitfield mask = GL_MAP_INVALIDATE_BUFFER_BIT;
13198 if ((access & mask) == mask) {
13199 // TODO(zmo): To be on the safe side, always map
13200 // GL_MAP_INVALIDATE_BUFFER_BIT to GL_MAP_INVALIDATE_RANGE_BIT.
13201 access = (access & ~GL_MAP_INVALIDATE_BUFFER_BIT);
13202 access = (access | GL_MAP_INVALIDATE_RANGE_BIT);
13204 // TODO(zmo): Always filter out GL_MAP_UNSYNCHRONIZED_BIT to get rid of
13205 // undefined behaviors.
13206 mask = GL_MAP_READ_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
13207 if ((access & mask) == mask) {
13208 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "MapBufferRange",
13209 "incompatible access bits");
13210 return error::kNoError;
13212 access = (access & ~GL_MAP_UNSYNCHRONIZED_BIT);
13213 if ((access & GL_MAP_WRITE_BIT) == GL_MAP_WRITE_BIT &&
13214 (access & GL_MAP_INVALIDATE_RANGE_BIT) == 0) {
13215 access = (access | GL_MAP_READ_BIT);
13217 void* ptr = glMapBufferRange(target, offset, size, access);
13218 if (ptr == nullptr) {
13219 return error::kNoError;
13221 Buffer* buffer = buffer_manager()->GetBufferInfoForTarget(&state_, target);
13222 DCHECK(buffer);
13223 buffer->SetMappedRange(offset, size, access, ptr,
13224 GetSharedMemoryBuffer(c.data_shm_id));
13225 if ((access & GL_MAP_INVALIDATE_RANGE_BIT) == 0) {
13226 memcpy(mem, ptr, size);
13228 *result = 1;
13229 return error::kNoError;
13232 error::Error GLES2DecoderImpl::HandleUnmapBuffer(
13233 uint32_t immediate_data_size, const void* cmd_data) {
13234 if (!unsafe_es3_apis_enabled()) {
13235 return error::kUnknownCommand;
13237 const gles2::cmds::UnmapBuffer& c =
13238 *static_cast<const gles2::cmds::UnmapBuffer*>(cmd_data);
13239 GLenum target = static_cast<GLenum>(c.target);
13241 Buffer* buffer = buffer_manager()->GetBufferInfoForTarget(&state_, target);
13242 if (!buffer) {
13243 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "UnmapBuffer", "no buffer bound");
13244 return error::kNoError;
13246 const Buffer::MappedRange* mapped_range = buffer->GetMappedRange();
13247 if (!mapped_range) {
13248 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "UnmapBuffer",
13249 "buffer is unmapped");
13250 return error::kNoError;
13252 if ((mapped_range->access & GL_MAP_WRITE_BIT) == 0 ||
13253 (mapped_range->access & GL_MAP_FLUSH_EXPLICIT_BIT) ==
13254 GL_MAP_FLUSH_EXPLICIT_BIT) {
13255 // If we don't need to write back, or explict flush is required, no copying
13256 // back is needed.
13257 } else {
13258 void* mem = mapped_range->GetShmPointer();
13259 if (!mem) {
13260 return error::kOutOfBounds;
13262 DCHECK(mapped_range->pointer);
13263 memcpy(mapped_range->pointer, mem, mapped_range->size);
13265 buffer->RemoveMappedRange();
13266 GLboolean rt = glUnmapBuffer(target);
13267 if (rt == GL_FALSE) {
13268 // At this point, we have already done the necessary validation, so
13269 // GL_FALSE indicates data corruption.
13270 // TODO(zmo): We could redo the map / copy data / unmap to recover, but
13271 // the second unmap could still return GL_FALSE. For now, we simply lose
13272 // the contexts in the share group.
13273 LOG(ERROR) << "glUnmapBuffer unexpectedly returned GL_FALSE";
13274 // Need to lose current context before broadcasting!
13275 MarkContextLost(error::kGuilty);
13276 group_->LoseContexts(error::kInnocent);
13277 return error::kLostContext;
13279 return error::kNoError;
13282 void GLES2DecoderImpl::OnTextureRefDetachedFromFramebuffer(
13283 TextureRef* texture_ref) {
13284 Texture* texture = texture_ref->texture();
13285 DoDidUseTexImageIfNeeded(texture, texture->target());
13288 // Note that GL_LOST_CONTEXT is specific to GLES.
13289 // For desktop GL we have to query the reset status proactively.
13290 void GLES2DecoderImpl::OnContextLostError() {
13291 if (!WasContextLost()) {
13292 // Need to lose current context before broadcasting!
13293 CheckResetStatus();
13294 group_->LoseContexts(error::kUnknown);
13295 reset_by_robustness_extension_ = true;
13299 void GLES2DecoderImpl::OnOutOfMemoryError() {
13300 if (lose_context_when_out_of_memory_ && !WasContextLost()) {
13301 error::ContextLostReason other = error::kOutOfMemory;
13302 if (CheckResetStatus()) {
13303 other = error::kUnknown;
13304 } else {
13305 // Need to lose current context before broadcasting!
13306 MarkContextLost(error::kOutOfMemory);
13308 group_->LoseContexts(other);
13312 // Include the auto-generated part of this file. We split this because it means
13313 // we can easily edit the non-auto generated parts right here in this file
13314 // instead of having to edit some template or the code generator.
13315 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
13317 } // namespace gles2
13318 } // namespace gpu