summaryrefslogtreecommitdiffstats
path: root/gpu
diff options
context:
space:
mode:
authorzmo <zmo@chromium.org>2016-03-14 16:37:04 -0700
committerCommit bot <commit-bot@chromium.org>2016-03-14 23:38:53 +0000
commit1afe4c3c566b3270b346c86f7698086e85b93730 (patch)
treee5dbe5449505ac242bbe4830d833ab974d44e5d1 /gpu
parentd9fd87883c0d8d5b69e07d61a92e149b647b4e38 (diff)
downloadchromium_src-1afe4c3c566b3270b346c86f7698086e85b93730.zip
chromium_src-1afe4c3c566b3270b346c86f7698086e85b93730.tar.gz
chromium_src-1afe4c3c566b3270b346c86f7698086e85b93730.tar.bz2
Implement unpack alignment driver bug workaround.
On some drivers (Linux NVIDIA, Mac AMD, etc), Tex uploading from unpack buffer generates an error if buffer size does not unclude padding for the last row. With this CL, conformance2/textures/misc/tex-unpack-params.html pass on the above mentioned drivers. BUG=429053 TEST=conformance2/textures/misc/tex-unpack-params.html R=piman@chromium.org CQ_INCLUDE_TRYBOTS=tryserver.chromium.win:win_optional_gpu_tests_rel;tryserver.chromium.mac:mac_optional_gpu_tests_rel Review URL: https://codereview.chromium.org/1798193002 Cr-Commit-Position: refs/heads/master@{#381113}
Diffstat (limited to 'gpu')
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.cc22
-rw-r--r--gpu/command_buffer/service/texture_manager.cc174
-rw-r--r--gpu/command_buffer/service/texture_manager.h24
-rw-r--r--gpu/config/gpu_driver_bug_list_json.cc24
-rw-r--r--gpu/config/gpu_driver_bug_workaround_type.h14
5 files changed, 219 insertions, 39 deletions
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index 5a0bfcb..0311e96 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -11298,6 +11298,7 @@ error::Error GLES2DecoderImpl::HandleTexImage2D(uint32_t immediate_data_size,
}
uint32_t pixels_size;
uint32_t skip_size;
+ uint32_t padding;
if (!GLES2Util::ComputeImageDataSizesES3(width, height, 1,
format, type,
params,
@@ -11305,7 +11306,7 @@ error::Error GLES2DecoderImpl::HandleTexImage2D(uint32_t immediate_data_size,
nullptr,
nullptr,
&skip_size,
- nullptr)) {
+ &padding)) {
return error::kOutOfBounds;
}
DCHECK_EQ(0u, skip_size);
@@ -11331,7 +11332,8 @@ error::Error GLES2DecoderImpl::HandleTexImage2D(uint32_t immediate_data_size,
TextureManager::DoTexImageArguments args = {
target, level, internal_format, width, height, 1, border, format, type,
- pixels, pixels_size, TextureManager::DoTexImageArguments::kTexImage2D };
+ pixels, pixels_size, padding,
+ TextureManager::DoTexImageArguments::kTexImage2D };
texture_manager()->ValidateAndDoTexImage(
&texture_state_, &state_, &framebuffer_state_, "glTexImage2D", args);
@@ -11386,6 +11388,7 @@ error::Error GLES2DecoderImpl::HandleTexImage3D(uint32_t immediate_data_size,
}
uint32_t pixels_size;
uint32_t skip_size;
+ uint32_t padding;
if (!GLES2Util::ComputeImageDataSizesES3(width, height, depth,
format, type,
params,
@@ -11393,7 +11396,7 @@ error::Error GLES2DecoderImpl::HandleTexImage3D(uint32_t immediate_data_size,
nullptr,
nullptr,
&skip_size,
- nullptr)) {
+ &padding)) {
return error::kOutOfBounds;
}
DCHECK_EQ(0u, skip_size);
@@ -11419,7 +11422,8 @@ error::Error GLES2DecoderImpl::HandleTexImage3D(uint32_t immediate_data_size,
TextureManager::DoTexImageArguments args = {
target, level, internal_format, width, height, depth, border, format, type,
- pixels, pixels_size, TextureManager::DoTexImageArguments::kTexImage3D };
+ pixels, pixels_size, padding,
+ TextureManager::DoTexImageArguments::kTexImage3D };
texture_manager()->ValidateAndDoTexImage(
&texture_state_, &state_, &framebuffer_state_, "glTexImage3D", args);
@@ -11810,6 +11814,7 @@ error::Error GLES2DecoderImpl::HandleTexSubImage2D(uint32_t immediate_data_size,
}
uint32_t pixels_size;
uint32_t skip_size;
+ uint32_t padding;
if (!GLES2Util::ComputeImageDataSizesES3(width, height, 1,
format, type,
params,
@@ -11817,7 +11822,7 @@ error::Error GLES2DecoderImpl::HandleTexSubImage2D(uint32_t immediate_data_size,
nullptr,
nullptr,
&skip_size,
- nullptr)) {
+ &padding)) {
return error::kOutOfBounds;
}
DCHECK_EQ(0u, skip_size);
@@ -11834,7 +11839,7 @@ error::Error GLES2DecoderImpl::HandleTexSubImage2D(uint32_t immediate_data_size,
TextureManager::DoTexSubImageArguments args = {
target, level, xoffset, yoffset, 0, width, height, 1,
- format, type, pixels, pixels_size,
+ format, type, pixels, pixels_size, padding,
TextureManager::DoTexSubImageArguments::kTexSubImage2D};
texture_manager()->ValidateAndDoTexSubImage(this, &texture_state_, &state_,
&framebuffer_state_,
@@ -11892,6 +11897,7 @@ error::Error GLES2DecoderImpl::HandleTexSubImage3D(uint32_t immediate_data_size,
}
uint32_t pixels_size;
uint32_t skip_size;
+ uint32_t padding;
if (!GLES2Util::ComputeImageDataSizesES3(width, height, depth,
format, type,
params,
@@ -11899,7 +11905,7 @@ error::Error GLES2DecoderImpl::HandleTexSubImage3D(uint32_t immediate_data_size,
nullptr,
nullptr,
&skip_size,
- nullptr)) {
+ &padding)) {
return error::kOutOfBounds;
}
DCHECK_EQ(0u, skip_size);
@@ -11916,7 +11922,7 @@ error::Error GLES2DecoderImpl::HandleTexSubImage3D(uint32_t immediate_data_size,
TextureManager::DoTexSubImageArguments args = {
target, level, xoffset, yoffset, zoffset, width, height, depth,
- format, type, pixels, pixels_size,
+ format, type, pixels, pixels_size, padding,
TextureManager::DoTexSubImageArguments::kTexSubImage3D};
texture_manager()->ValidateAndDoTexSubImage(this, &texture_state_, &state_,
&framebuffer_state_,
diff --git a/gpu/command_buffer/service/texture_manager.cc b/gpu/command_buffer/service/texture_manager.cc
index d2bc325..8297c6d 100644
--- a/gpu/command_buffer/service/texture_manager.cc
+++ b/gpu/command_buffer/service/texture_manager.cc
@@ -2232,7 +2232,7 @@ bool TextureManager::ValidateTexImage(
ERRORSTATE_SET_GL_ERROR(
error_state, GL_INVALID_OPERATION, function_name,
"pixel unpack buffer should not be mapped to client memory");
- return error::kNoError;
+ return false;
}
base::CheckedNumeric<uint32_t> size = args.pixels_size;
GLuint offset = ToGLuint(args.pixels);
@@ -2241,14 +2241,14 @@ bool TextureManager::ValidateTexImage(
ERRORSTATE_SET_GL_ERROR(
error_state, GL_INVALID_VALUE, function_name,
"size + offset overflow");
- return error::kNoError;
+ return false;
}
uint32_t buffer_size = static_cast<uint32_t>(buffer->size());
if (buffer_size < size.ValueOrDefault(0)) {
ERRORSTATE_SET_GL_ERROR(
error_state, GL_INVALID_OPERATION, function_name,
"pixel unpack buffer is not large enough");
- return error::kNoError;
+ return false;
}
size_t type_size = GLES2Util::GetGLTypeSizeForTextures(args.type);
DCHECK_LT(0u, type_size);
@@ -2256,7 +2256,7 @@ bool TextureManager::ValidateTexImage(
ERRORSTATE_SET_GL_ERROR(
error_state, GL_INVALID_OPERATION, function_name,
"offset is not evenly divisible by elements");
- return error::kNoError;
+ return false;
}
}
@@ -2282,6 +2282,8 @@ void TextureManager::ValidateAndDoTexImage(
return;
}
+ Buffer* buffer = state->bound_pixel_unpack_buffer.get();
+
// ValidateTexImage is passed already.
Texture* texture = texture_ref->texture();
bool need_cube_map_workaround =
@@ -2289,7 +2291,8 @@ void TextureManager::ValidateAndDoTexImage(
(texture_state->force_cube_complete ||
(texture_state->force_cube_map_positive_x_allocation &&
args.target != GL_TEXTURE_CUBE_MAP_POSITIVE_X));
- if (need_cube_map_workaround) {
+ if (need_cube_map_workaround && !buffer) {
+ // TODO(zmo): The following code does not work with an unpack buffer bound.
std::vector<GLenum> undefined_faces;
if (texture_state->force_cube_complete) {
int width = 0;
@@ -2311,7 +2314,6 @@ void TextureManager::ValidateAndDoTexImage(
undefined_faces.push_back(GL_TEXTURE_CUBE_MAP_POSITIVE_X);
}
}
-
if (!memory_type_tracker_->EnsureGPUMemoryAvailable(
(undefined_faces.size() + 1) * args.pixels_size)) {
ERRORSTATE_SET_GL_ERROR(state->GetErrorState(), GL_OUT_OF_MEMORY,
@@ -2330,6 +2332,33 @@ void TextureManager::ValidateAndDoTexImage(
}
}
+ if (texture_state->unpack_alignment_workaround_with_unpack_buffer && buffer) {
+ uint32_t buffer_size = static_cast<uint32_t>(buffer->size());
+ if (buffer_size - args.pixels_size - ToGLuint(args.pixels) < args.padding) {
+ // In ValidateTexImage(), we already made sure buffer size is no less
+ // than offset + pixels_size.
+ glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
+ state->SetBoundBuffer(GL_PIXEL_UNPACK_BUFFER, nullptr);
+ DoTexImageArguments new_args = args;
+ new_args.pixels = nullptr;
+ // pixels_size might be incorrect, but it's not used in this case.
+ DoTexImage(texture_state, state, framebuffer_state, function_name,
+ texture_ref, new_args);
+ glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer->service_id());
+ state->SetBoundBuffer(GL_PIXEL_UNPACK_BUFFER, buffer);
+
+ DoTexSubImageArguments sub_args = {
+ args.target, args.level, 0, 0, 0, args.width, args.height, args.depth,
+ args.format, args.type, args.pixels, args.pixels_size, args.padding,
+ args.command_type == DoTexImageArguments::kTexImage3D ?
+ DoTexSubImageArguments::kTexSubImage3D :
+ DoTexSubImageArguments::kTexSubImage2D};
+ DoTexSubImageWithAlignmentWorkaround(texture_state, state, sub_args);
+
+ SetLevelCleared(texture_ref, args.target, args.level, true);
+ return;
+ }
+ }
DoTexImage(texture_state, state, framebuffer_state,
function_name, texture_ref, args);
}
@@ -2449,6 +2478,7 @@ void TextureManager::ValidateAndDoTexSubImage(
bool ok = texture->GetLevelSize(args.target, args.level, &tex_width,
&tex_height, &tex_depth);
DCHECK(ok);
+ bool full_image;
if (args.xoffset != 0 || args.yoffset != 0 || args.zoffset != 0 ||
args.width != tex_width || args.height != tex_height ||
args.depth != tex_depth) {
@@ -2471,20 +2501,22 @@ void TextureManager::ValidateAndDoTexSubImage(
return;
}
}
- ScopedTextureUploadTimer timer(texture_state);
- if (args.command_type == DoTexSubImageArguments::kTexSubImage3D) {
- glTexSubImage3D(args.target, args.level, args.xoffset, args.yoffset,
- args.zoffset, args.width, args.height, args.depth,
- AdjustTexFormat(args.format), args.type, args.pixels);
- } else {
- glTexSubImage2D(args.target, args.level, args.xoffset, args.yoffset,
- args.width, args.height, AdjustTexFormat(args.format),
- args.type, args.pixels);
+ full_image = false;
+ } else {
+ SetLevelCleared(texture_ref, args.target, args.level, true);
+ full_image = true;
+ }
+
+ Buffer* buffer = state->bound_pixel_unpack_buffer.get();
+ if (texture_state->unpack_alignment_workaround_with_unpack_buffer && buffer) {
+ uint32_t buffer_size = static_cast<uint32_t>(buffer->size());
+ if (buffer_size - args.pixels_size - ToGLuint(args.pixels) < args.padding) {
+ DoTexSubImageWithAlignmentWorkaround(texture_state, state, args);
+ return;
}
- return;
}
- if (!texture_state->texsubimage_faster_than_teximage &&
+ if (full_image && !texture_state->texsubimage_faster_than_teximage &&
!texture->IsImmutable() && !texture->HasImages()) {
ScopedTextureUploadTimer timer(texture_state);
GLenum internal_format;
@@ -2514,7 +2546,113 @@ void TextureManager::ValidateAndDoTexSubImage(
args.type, args.pixels);
}
}
- SetLevelCleared(texture_ref, args.target, args.level, true);
+}
+
+void TextureManager::DoTexSubImageWithAlignmentWorkaround(
+ DecoderTextureState* texture_state,
+ ContextState* state,
+ const DoTexSubImageArguments& args) {
+ DCHECK(state->bound_pixel_unpack_buffer.get());
+ DCHECK(args.width > 0 && args.height > 0 && args.depth > 0);
+
+ ScopedTextureUploadTimer timer(texture_state);
+ uint32_t offset = ToGLuint(args.pixels);
+ if (args.command_type == DoTexSubImageArguments::kTexSubImage2D) {
+ PixelStoreParams params = state->GetUnpackParams(ContextState::k2D);
+ if (args.height > 1) {
+ glTexSubImage2D(args.target, args.level, args.xoffset, args.yoffset,
+ args.width, args.height - 1,
+ AdjustTexFormat(args.format), args.type, args.pixels);
+ GLint actual_width = state->unpack_row_length > 0 ?
+ state->unpack_row_length : args.width;
+ uint32_t size;
+ uint32_t padding;
+ // No need to worry about integer overflow here.
+ GLES2Util::ComputeImageDataSizesES3(actual_width, args.height - 1, 1,
+ args.format, args.type,
+ params,
+ &size,
+ nullptr, nullptr, nullptr,
+ &padding);
+ DCHECK_EQ(args.padding, padding);
+ // Last row should be padded, not unpadded.
+ offset += size + padding;
+ }
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ glTexSubImage2D(args.target, args.level, args.xoffset,
+ args.yoffset + args.height - 1,
+ args.width, 1, AdjustTexFormat(args.format), args.type,
+ reinterpret_cast<const void *>(offset));
+ glPixelStorei(GL_UNPACK_ALIGNMENT, state->unpack_alignment);
+ {
+ uint32_t size;
+ GLES2Util::ComputeImageDataSizesES3(args.width, 1, 1,
+ args.format, args.type,
+ params,
+ &size,
+ nullptr, nullptr, nullptr, nullptr);
+ offset += size;
+ }
+ } else { // kTexSubImage3D
+ PixelStoreParams params = state->GetUnpackParams(ContextState::k3D);
+ GLint actual_width = state->unpack_row_length > 0 ?
+ state->unpack_row_length : args.width;
+ if (args.depth > 1) {
+ glTexSubImage3D(args.target, args.level, args.xoffset, args.yoffset,
+ args.zoffset, args.width, args.height, args.depth - 1,
+ AdjustTexFormat(args.format), args.type, args.pixels);
+ GLint actual_height = state->unpack_image_height > 0 ?
+ state->unpack_image_height : args.height;
+ uint32_t size;
+ uint32_t padding;
+ // No need to worry about integer overflow here.
+ GLES2Util::ComputeImageDataSizesES3(actual_width, actual_height,
+ args.depth - 1,
+ args.format, args.type,
+ params,
+ &size,
+ nullptr, nullptr, nullptr,
+ &padding);
+ DCHECK_EQ(args.padding, padding);
+ // Last row should be padded, not unpadded.
+ offset += size + padding;
+ }
+ if (args.height > 1) {
+ glTexSubImage3D(args.target, args.level, args.xoffset, args.yoffset,
+ args.zoffset + args.depth - 1, args.width,
+ args.height - 1, 1, AdjustTexFormat(args.format),
+ args.type, reinterpret_cast<const void*>(offset));
+ uint32_t size;
+ uint32_t padding;
+ // No need to worry about integer overflow here.
+ GLES2Util::ComputeImageDataSizesES3(actual_width, args.height - 1, 1,
+ args.format, args.type,
+ params,
+ &size,
+ nullptr, nullptr, nullptr,
+ &padding);
+ DCHECK_EQ(args.padding, padding);
+ // Last row should be padded, not unpadded.
+ offset += size + padding;
+ }
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ glTexSubImage3D(args.target, args.level, args.xoffset,
+ args.yoffset + args.height - 1,
+ args.zoffset + args.depth - 1,
+ args.width, 1, 1, AdjustTexFormat(args.format), args.type,
+ reinterpret_cast<const void *>(offset));
+ glPixelStorei(GL_UNPACK_ALIGNMENT, state->unpack_alignment);
+ {
+ uint32_t size;
+ GLES2Util::ComputeImageDataSizesES3(args.width, 1, 1,
+ args.format, args.type,
+ params,
+ &size,
+ nullptr, nullptr, nullptr, nullptr);
+ offset += size;
+ }
+ }
+ DCHECK_EQ(ToGLuint(args.pixels) + args.pixels_size, offset);
}
GLenum TextureManager::AdjustTexInternalFormat(GLenum format) const {
diff --git a/gpu/command_buffer/service/texture_manager.h b/gpu/command_buffer/service/texture_manager.h
index 420b872..2485146 100644
--- a/gpu/command_buffer/service/texture_manager.h
+++ b/gpu/command_buffer/service/texture_manager.h
@@ -645,7 +645,9 @@ struct DecoderTextureState {
workarounds.texsubimage_faster_than_teximage),
force_cube_map_positive_x_allocation(
workarounds.force_cube_map_positive_x_allocation),
- force_cube_complete(workarounds.force_cube_complete) {}
+ force_cube_complete(workarounds.force_cube_complete),
+ unpack_alignment_workaround_with_unpack_buffer(
+ workarounds.unpack_alignment_workaround_with_unpack_buffer) {}
// This indicates all the following texSubImage*D calls that are part of the
// failed texImage*D call should be ignored. The client calls have a lock
@@ -660,6 +662,7 @@ struct DecoderTextureState {
bool texsubimage_faster_than_teximage;
bool force_cube_map_positive_x_allocation;
bool force_cube_complete;
+ bool unpack_alignment_workaround_with_unpack_buffer;
};
// This class keeps track of the textures and their sizes so we can do NPOT and
@@ -954,6 +957,7 @@ class GPU_EXPORT TextureManager : public base::trace_event::MemoryDumpProvider {
GLenum type;
const void* pixels;
uint32_t pixels_size;
+ uint32_t padding;
TexImageCommandType command_type;
};
@@ -990,6 +994,7 @@ class GPU_EXPORT TextureManager : public base::trace_event::MemoryDumpProvider {
GLenum type;
const void* pixels;
uint32_t pixels_size;
+ uint32_t padding;
TexSubImageCommandType command_type;
};
@@ -1051,12 +1056,17 @@ class GPU_EXPORT TextureManager : public base::trace_event::MemoryDumpProvider {
GLuint* black_texture);
void DoTexImage(
- DecoderTextureState* texture_state,
- ContextState* state,
- DecoderFramebufferState* framebuffer_state,
- const char* function_name,
- TextureRef* texture_ref,
- const DoTexImageArguments& args);
+ DecoderTextureState* texture_state,
+ ContextState* state,
+ DecoderFramebufferState* framebuffer_state,
+ const char* function_name,
+ TextureRef* texture_ref,
+ const DoTexImageArguments& args);
+
+ void DoTexSubImageWithAlignmentWorkaround(
+ DecoderTextureState* texture_state,
+ ContextState* state,
+ const DoTexSubImageArguments& args);
void StartTracking(TextureRef* texture);
void StopTracking(TextureRef* texture);
diff --git a/gpu/config/gpu_driver_bug_list_json.cc b/gpu/config/gpu_driver_bug_list_json.cc
index 7af4986..032afe3 100644
--- a/gpu/config/gpu_driver_bug_list_json.cc
+++ b/gpu/config/gpu_driver_bug_list_json.cc
@@ -1795,6 +1795,30 @@ LONG_STRING_CONST(
"features": [
"disable_direct_composition"
]
+ },
+ {
+ "id": 150,
+ "cr_bugs": [563714],
+ "description": "Alignment works incorrectly with unpack buffer bound",
+ "os": {
+ "type": "linux"
+ },
+ "vendor_id": "0x10de",
+ "gl_vendor": "NVIDIA.*",
+ "features": [
+ "unpack_alignment_workaround_with_unpack_buffer"
+ ]
+ },
+ {
+ "id": 151,
+ "cr_bugs": [563714],
+ "description": "Alignment works incorrectly with unpack buffer bound",
+ "os": {
+ "type": "macosx"
+ },
+ "features": [
+ "unpack_alignment_workaround_with_unpack_buffer"
+ ]
}
]
}
diff --git a/gpu/config/gpu_driver_bug_workaround_type.h b/gpu/config/gpu_driver_bug_workaround_type.h
index 71ea843..a0af6ad 100644
--- a/gpu/config/gpu_driver_bug_workaround_type.h
+++ b/gpu/config/gpu_driver_bug_workaround_type.h
@@ -32,6 +32,8 @@
disable_d3d11) \
GPU_OP(DISABLE_DEPTH_TEXTURE, \
disable_depth_texture) \
+ GPU_OP(DISABLE_DIRECT_COMPOSITION, \
+ disable_direct_composition) \
GPU_OP(DISABLE_DISCARD_FRAMEBUFFER, \
disable_discard_framebuffer) \
GPU_OP(DISABLE_EXT_DRAW_BUFFERS, \
@@ -118,6 +120,8 @@
scalarize_vec_and_mat_constructor_args) \
GPU_OP(SET_TEXTURE_FILTER_BEFORE_GENERATING_MIPMAP, \
set_texture_filter_before_generating_mipmap) \
+ GPU_OP(SET_ZERO_LEVEL_BEFORE_GENERATING_MIPMAP, \
+ set_zero_level_before_generating_mipmap) \
GPU_OP(SIMULATE_OUT_OF_MEMORY_ON_LARGE_TEXTURES, \
simulate_out_of_memory_on_large_textures) \
GPU_OP(SURFACE_TEXTURE_CANT_DETACH, \
@@ -128,10 +132,14 @@
texsubimage_faster_than_teximage) \
GPU_OP(UNBIND_ATTACHMENTS_ON_BOUND_RENDER_FBO_DELETE, \
unbind_attachments_on_bound_render_fbo_delete) \
+ GPU_OP(UNBIND_EGL_CONTEXT_TO_FLUSH_DRIVER_CACHES, \
+ unbind_egl_context_to_flush_driver_caches) \
GPU_OP(UNBIND_FBO_ON_CONTEXT_SWITCH, \
unbind_fbo_on_context_switch) \
GPU_OP(UNFOLD_SHORT_CIRCUIT_AS_TERNARY_OPERATION, \
unfold_short_circuit_as_ternary_operation) \
+ GPU_OP(UNPACK_ALIGNMENT_WORKAROUND_WITH_UNPACK_BUFFER, \
+ unpack_alignment_workaround_with_unpack_buffer) \
GPU_OP(UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX, \
unroll_for_loop_with_sampler_array_index) \
GPU_OP(USE_CLIENT_SIDE_ARRAYS_FOR_STREAM_BUFFERS, \
@@ -146,12 +154,6 @@
validate_multisample_buffer_allocation) \
GPU_OP(WAKE_UP_GPU_BEFORE_DRAWING, \
wake_up_gpu_before_drawing) \
- GPU_OP(UNBIND_EGL_CONTEXT_TO_FLUSH_DRIVER_CACHES, \
- unbind_egl_context_to_flush_driver_caches) \
- GPU_OP(SET_ZERO_LEVEL_BEFORE_GENERATING_MIPMAP, \
- set_zero_level_before_generating_mipmap) \
- GPU_OP(DISABLE_DIRECT_COMPOSITION, \
- disable_direct_composition) \
namespace gpu {