| Index: gpu/command_buffer/service/gles2_cmd_decoder.cc
|
| diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
|
| index f97710e86a61009ce7b6b54517f63040d5f8cb3b..7257dfa17d1d6f20ed0468db7f79a665b378fdd6 100644
|
| --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
|
| +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
|
| @@ -167,6 +167,25 @@ static gfx::OverlayTransform GetGFXOverlayTransform(GLenum plane_transform) {
|
| }
|
| }
|
|
|
| +static size_t BitsPerPixel(GLenum format) {
|
| + switch (format) {
|
| + case GL_RGB:
|
| + return 24;
|
| + case GL_RGBA:
|
| + return 32;
|
| + case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
|
| + case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
|
| + return 8;
|
| + case GL_ATC_RGB_AMD:
|
| + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
|
| + case GL_ETC1_RGB8_OES:
|
| + return 4;
|
| + }
|
| +
|
| + NOTREACHED();
|
| + return 0;
|
| +}
|
| +
|
| } // namespace
|
|
|
| class GLES2DecoderImpl;
|
| @@ -944,6 +963,12 @@ class GLES2DecoderImpl : public GLES2Decoder,
|
| GLenum internal_format,
|
| GLenum dest_type);
|
|
|
| + void DoCopyCompressedTextureCHROMIUM(GLenum target,
|
| + GLuint source_id,
|
| + GLuint target_id,
|
| + GLenum internal_format,
|
| + GLenum dest_type);
|
| +
|
| // Wrapper for TexStorage2DEXT.
|
| void DoTexStorage2DEXT(
|
| GLenum target,
|
| @@ -1652,6 +1677,18 @@ class GLES2DecoderImpl : public GLES2Decoder,
|
| GLsizei width, GLsizei height, GLenum format,
|
| Texture* texture);
|
|
|
| + bool ValidateCompressedTexSubImage2D(error::Error* error,
|
| + const char* function_name,
|
| + GLenum target,
|
| + GLint level,
|
| + GLint xoffset,
|
| + GLint yoffset,
|
| + GLsizei width,
|
| + GLsizei height,
|
| + GLenum format,
|
| + GLsizei image_size,
|
| + const void* data);
|
| +
|
| void RenderWarning(const char* filename, int line, const std::string& msg);
|
| void PerformanceWarning(
|
| const char* filename, int line, const std::string& msg);
|
| @@ -2839,8 +2876,12 @@ Capabilities GLES2DecoderImpl::GetCapabilities() {
|
|
|
| caps.egl_image_external =
|
| feature_info_->feature_flags().oes_egl_image_external;
|
| + caps.texture_format_atc =
|
| + feature_info_->feature_flags().ext_texture_format_atc;
|
| caps.texture_format_bgra8888 =
|
| feature_info_->feature_flags().ext_texture_format_bgra8888;
|
| + caps.texture_format_dxt =
|
| + feature_info_->feature_flags().ext_texture_format_dxt;
|
| caps.texture_format_etc1 =
|
| feature_info_->feature_flags().oes_compressed_etc1_rgb8_texture;
|
| caps.texture_format_etc1_npot =
|
| @@ -8343,70 +8384,18 @@ bool GLES2DecoderImpl::ClearLevel(
|
| return true;
|
| }
|
|
|
| -namespace {
|
| -
|
| -const int kS3TCBlockWidth = 4;
|
| -const int kS3TCBlockHeight = 4;
|
| -const int kS3TCDXT1BlockSize = 8;
|
| -const int kS3TCDXT3AndDXT5BlockSize = 16;
|
| -
|
| -bool IsValidDXTSize(GLint level, GLsizei size) {
|
| - return (size == 1) ||
|
| - (size == 2) || !(size % kS3TCBlockWidth);
|
| -}
|
| -
|
| -bool IsValidPVRTCSize(GLint level, GLsizei size) {
|
| - return GLES2Util::IsPOT(size);
|
| -}
|
| -
|
| -} // anonymous namespace.
|
| -
|
| bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
|
| const char* function_name,
|
| GLsizei width, GLsizei height, GLenum format, size_t size) {
|
| - unsigned int bytes_required = 0;
|
| + int bytes_required = 0;
|
|
|
| - switch (format) {
|
| - case GL_ATC_RGB_AMD:
|
| - case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
|
| - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
|
| - case GL_ETC1_RGB8_OES: {
|
| - int num_blocks_across =
|
| - (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
|
| - int num_blocks_down =
|
| - (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
|
| - int num_blocks = num_blocks_across * num_blocks_down;
|
| - bytes_required = num_blocks * kS3TCDXT1BlockSize;
|
| - break;
|
| - }
|
| - case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
|
| - case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
|
| - case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
|
| - case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
|
| - int num_blocks_across =
|
| - (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
|
| - int num_blocks_down =
|
| - (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
|
| - int num_blocks = num_blocks_across * num_blocks_down;
|
| - bytes_required = num_blocks * kS3TCDXT3AndDXT5BlockSize;
|
| - break;
|
| - }
|
| - case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
|
| - case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG: {
|
| - bytes_required = (std::max(width, 8) * std::max(height, 8) * 4 + 7)/8;
|
| - break;
|
| - }
|
| - case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
|
| - case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
|
| - bytes_required = (std::max(width, 16) * std::max(height, 8) * 2 + 7)/8;
|
| - break;
|
| - }
|
| - default:
|
| - LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, format, "format");
|
| - return false;
|
| + if (!GLES2Util::ComputeCompressedImageSize(width, height, format,
|
| + &bytes_required)) {
|
| + LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, format, "format");
|
| + return false;
|
| }
|
|
|
| - if (size != bytes_required) {
|
| + if (size != static_cast<size_t>(bytes_required)) {
|
| LOCAL_SET_GL_ERROR(
|
| GL_INVALID_VALUE, function_name, "size is not correct for dimensions");
|
| return false;
|
| @@ -8418,47 +8407,13 @@ bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
|
| bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
|
| const char* function_name,
|
| GLint level, GLsizei width, GLsizei height, GLenum format) {
|
| - switch (format) {
|
| - case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
|
| - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
|
| - case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
|
| - case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
|
| - if (!IsValidDXTSize(level, width) || !IsValidDXTSize(level, height)) {
|
| - LOCAL_SET_GL_ERROR(
|
| - GL_INVALID_OPERATION, function_name,
|
| - "width or height invalid for level");
|
| - return false;
|
| - }
|
| - return true;
|
| - }
|
| - case GL_ATC_RGB_AMD:
|
| - case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
|
| - case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
|
| - case GL_ETC1_RGB8_OES: {
|
| - if (width <= 0 || height <= 0) {
|
| - LOCAL_SET_GL_ERROR(
|
| - GL_INVALID_OPERATION, function_name,
|
| - "width or height invalid for level");
|
| - return false;
|
| - }
|
| - return true;
|
| - }
|
| - case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
|
| - case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
|
| - case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
|
| - case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
|
| - if (!IsValidPVRTCSize(level, width) ||
|
| - !IsValidPVRTCSize(level, height)) {
|
| - LOCAL_SET_GL_ERROR(
|
| - GL_INVALID_OPERATION, function_name,
|
| - "width or height invalid for level");
|
| - return false;
|
| - }
|
| - return true;
|
| - }
|
| - default:
|
| - return false;
|
| + if (!GLES2Util::IsValidCompressedImageSize(level, width, height, format)) {
|
| + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
|
| + "width or height invalid for level");
|
| + return false;
|
| }
|
| +
|
| + return true;
|
| }
|
|
|
| bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
|
| @@ -8473,10 +8428,13 @@ bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
|
| }
|
|
|
| switch (format) {
|
| + case GL_ATC_RGB_AMD:
|
| + case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
|
| case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
|
| case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
|
| case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
|
| - case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
|
| + case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
|
| + case GL_ETC1_RGB8_OES: {
|
| const int kBlockWidth = 4;
|
| const int kBlockHeight = 4;
|
| if ((xoffset % kBlockWidth) || (yoffset % kBlockHeight)) {
|
| @@ -8497,20 +8455,12 @@ bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
|
| return ValidateCompressedTexDimensions(
|
| function_name, level, width, height, format);
|
| }
|
| - case GL_ATC_RGB_AMD:
|
| - case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
|
| - case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD: {
|
| + case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD: {
|
| LOCAL_SET_GL_ERROR(
|
| GL_INVALID_OPERATION, function_name,
|
| "not supported for ATC textures");
|
| return false;
|
| }
|
| - case GL_ETC1_RGB8_OES: {
|
| - LOCAL_SET_GL_ERROR(
|
| - GL_INVALID_OPERATION, function_name,
|
| - "not supported for ECT1_RGB8_OES textures");
|
| - return false;
|
| - }
|
| case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
|
| case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
|
| case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
|
| @@ -8539,6 +8489,72 @@ bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
|
| }
|
| }
|
|
|
| +bool GLES2DecoderImpl::ValidateCompressedTexSubImage2D(
|
| + error::Error* error,
|
| + const char* function_name,
|
| + GLenum target,
|
| + GLint level,
|
| + GLint xoffset,
|
| + GLint yoffset,
|
| + GLsizei width,
|
| + GLsizei height,
|
| + GLenum format,
|
| + GLsizei image_size,
|
| + const void* data) {
|
| + (*error) = error::kNoError;
|
| + if (!validators_->texture_target.IsValid(target)) {
|
| + LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
|
| + return false;
|
| + }
|
| + if (width < 0) {
|
| + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "width < 0");
|
| + return false;
|
| + }
|
| + if (height < 0) {
|
| + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "height < 0");
|
| + return false;
|
| + }
|
| + TextureRef* texture_ref =
|
| + texture_manager()->GetTextureInfoForTarget(&state_, target);
|
| + if (!texture_ref) {
|
| + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
|
| + "unknown texture for target");
|
| + return false;
|
| + }
|
| + Texture* texture = texture_ref->texture();
|
| + GLenum current_type = 0;
|
| + GLenum internal_format = 0;
|
| + if (!texture->GetLevelType(target, level, ¤t_type, &internal_format)) {
|
| + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
|
| + "level does not exist.");
|
| + return false;
|
| + }
|
| + if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
|
| + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
|
| + "async upload pending for texture");
|
| + return false;
|
| + }
|
| + if (!ValidateCompressedTexFuncData(function_name, width, height, format,
|
| + image_size)) {
|
| + return false;
|
| + }
|
| + if (!ValidateCompressedTexSubDimensions(function_name, target, level, xoffset,
|
| + yoffset, width, height, format,
|
| + texture)) {
|
| + return false;
|
| + }
|
| + if (!texture->ValidForTexture(target, level, xoffset, yoffset, width, height,
|
| + GL_UNSIGNED_BYTE)) {
|
| + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "bad dimensions.");
|
| + return false;
|
| + }
|
| + if (data == NULL) {
|
| + (*error) = error::kOutOfBounds;
|
| + return false;
|
| + }
|
| + return true;
|
| +}
|
| +
|
| error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
|
| GLenum target,
|
| GLint level,
|
| @@ -10587,6 +10603,149 @@ void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
|
| DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
|
| }
|
|
|
| +void GLES2DecoderImpl::DoCopyCompressedTextureCHROMIUM(GLenum target,
|
| + GLuint source_id,
|
| + GLuint dest_id,
|
| + GLenum internal_format,
|
| + GLenum dest_type) {
|
| + TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopyCompressedTextureCHROMIUM");
|
| +
|
| + TextureRef* dest_texture_ref = GetTexture(dest_id);
|
| + TextureRef* source_texture_ref = GetTexture(source_id);
|
| +
|
| + if (!source_texture_ref || !dest_texture_ref) {
|
| + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopyCompressedTextureCHROMIUM",
|
| + "unknown texture id");
|
| + return;
|
| + }
|
| +
|
| + if (GL_TEXTURE_2D != target) {
|
| + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopyCompressedTextureCHROMIUM",
|
| + "invalid texture target");
|
| + return;
|
| + }
|
| +
|
| + Texture* source_texture = source_texture_ref->texture();
|
| + Texture* dest_texture = dest_texture_ref->texture();
|
| + if (dest_texture->target() != GL_TEXTURE_2D ||
|
| + (source_texture->target() != GL_TEXTURE_2D &&
|
| + source_texture->target() != GL_TEXTURE_RECTANGLE_ARB &&
|
| + source_texture->target() != GL_TEXTURE_EXTERNAL_OES)) {
|
| + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopyCompressedTextureCHROMIUM",
|
| + "invalid texture target binding");
|
| + return;
|
| + }
|
| +
|
| + gfx::GLImage* image =
|
| + source_texture->GetLevelImage(source_texture->target(), 0);
|
| + if (!image) {
|
| + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopyCompressedTextureCHROMIUM",
|
| + "source texture has no level 0");
|
| + return;
|
| + }
|
| +
|
| + gfx::Size size = image->GetSize();
|
| + int source_width = size.width();
|
| + int source_height = size.height();
|
| + if (source_width <= 0 || source_height <= 0) {
|
| + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopyCompressedTextureCHROMIUM",
|
| + "invalid image size");
|
| + return;
|
| + }
|
| +
|
| + // Clear the source texture if necessary.
|
| + if (!texture_manager()->ClearTextureLevel(this, source_texture_ref,
|
| + source_texture->target(), 0)) {
|
| + LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyCompressedTextureCHROMIUM",
|
| + "dimensions too big");
|
| + return;
|
| + }
|
| +
|
| + GLenum source_type = 0;
|
| + GLenum source_internal_format = 0;
|
| + source_texture->GetLevelType(source_texture->target(), 0, &source_type,
|
| + &source_internal_format);
|
| +
|
| + // The destination format should be one of the supported compressed formats.
|
| + bool valid_dest_format =
|
| + internal_format == GL_ATC_RGB_AMD ||
|
| + internal_format == GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD ||
|
| + internal_format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||
|
| + internal_format == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT ||
|
| + internal_format == GL_ETC1_RGB8_OES;
|
| + bool valid_source_format = source_internal_format == GL_ALPHA ||
|
| + source_internal_format == GL_RGB ||
|
| + source_internal_format == GL_RGBA ||
|
| + source_internal_format == GL_LUMINANCE ||
|
| + source_internal_format == GL_LUMINANCE_ALPHA ||
|
| + source_internal_format == GL_BGRA_EXT;
|
| + if (!valid_source_format || !valid_dest_format) {
|
| + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCopyCompressedTextureCHROMIUM",
|
| + "invalid internal format");
|
| + return;
|
| + }
|
| +
|
| + // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
|
| + // needed because it takes 10s of milliseconds to initialize.
|
| + if (!copy_texture_CHROMIUM_.get()) {
|
| + LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyCompressedTextureCHROMIUM");
|
| + copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
|
| + copy_texture_CHROMIUM_->Initialize(this);
|
| + RestoreCurrentFramebufferBindings();
|
| + if (LOCAL_PEEK_GL_ERROR("glCopyCompressedTextureCHROMIUM") != GL_NO_ERROR)
|
| + return;
|
| + }
|
| +
|
| + GLenum dest_type_previous = dest_type;
|
| + GLenum dest_internal_format = internal_format;
|
| + int dest_width = 0, dest_height = 0;
|
| + bool dest_level_defined =
|
| + dest_texture->GetLevelSize(GL_TEXTURE_2D, 0, &dest_width, &dest_height);
|
| +
|
| + if (dest_level_defined) {
|
| + dest_texture->GetLevelType(GL_TEXTURE_2D, 0, &dest_type_previous,
|
| + &dest_internal_format);
|
| + }
|
| +
|
| + // Resize the destination texture to the dimensions of the source texture.
|
| + if (!dest_level_defined || dest_width != source_width ||
|
| + dest_height != source_height || dest_internal_format != internal_format ||
|
| + dest_type_previous != dest_type) {
|
| + // Compute image byte size.
|
| + GLsizei image_size =
|
| + source_width * source_height * BitsPerPixel(internal_format) / 8;
|
| +
|
| + // Ensure that the glCompressedTexImage2D succeeds.
|
| + LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyCompressedTextureCHROMIUM");
|
| + glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
|
| + glCompressedTexImage2D(GL_TEXTURE_2D, 0, internal_format, source_width,
|
| + source_height, 0, image_size, NULL);
|
| +
|
| + GLenum error = LOCAL_PEEK_GL_ERROR("glCopyCompressedTextureCHROMIUM");
|
| + if (error != GL_NO_ERROR) {
|
| + RestoreCurrentTextureBindings(&state_, GL_TEXTURE_2D);
|
| + return;
|
| + }
|
| +
|
| + texture_manager()->SetLevelInfo(
|
| + dest_texture_ref, GL_TEXTURE_2D, 0, internal_format, source_width,
|
| + source_height, 1, 0, internal_format, dest_type, true);
|
| + } else {
|
| + texture_manager()->SetLevelCleared(dest_texture_ref, GL_TEXTURE_2D, 0,
|
| + true);
|
| + }
|
| +
|
| + ScopedModifyPixels modify(dest_texture_ref);
|
| +
|
| + DCHECK(!unpack_flip_y_);
|
| + DCHECK(!(unpack_premultiply_alpha_ ^ unpack_unpremultiply_alpha_));
|
| +
|
| + // Copying compressed textures is only supported using GLImage::CopyTexImage.
|
| + glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
|
| + bool copy_result = image->CopyTexImage(GL_TEXTURE_2D);
|
| + DCHECK(copy_result);
|
| +}
|
| +
|
| static GLenum ExtractTypeFromStorageFormat(GLenum internalformat) {
|
| switch (internalformat) {
|
| case GL_RGB565:
|
| @@ -11472,6 +11631,214 @@ error::Error GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM(
|
| return error::kNoError;
|
| }
|
|
|
| +error::Error GLES2DecoderImpl::HandleAsyncCompressedTexImage2DCHROMIUM(
|
| + uint32 immediate_data_size,
|
| + const void* cmd_data) {
|
| + const gles2::cmds::AsyncCompressedTexImage2DCHROMIUM& c =
|
| + *static_cast<const gles2::cmds::AsyncCompressedTexImage2DCHROMIUM*>(
|
| + cmd_data);
|
| + GLenum target = static_cast<GLenum>(c.target);
|
| + GLint level = static_cast<GLint>(c.level);
|
| + // TODO(kloveless): Change HandleAsyncTexImage2DCHROMIUM command to use
|
| + // unsigned integer for internalformat.
|
| + GLenum internal_format = static_cast<GLenum>(c.internalformat);
|
| + GLsizei width = static_cast<GLsizei>(c.width);
|
| + GLsizei height = static_cast<GLsizei>(c.height);
|
| + GLint border = static_cast<GLint>(c.border);
|
| + GLsizei image_size = static_cast<GLenum>(c.imagesize);
|
| + uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
|
| + uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
|
| + uint32 async_upload_token = static_cast<uint32>(c.async_upload_token);
|
| + uint32 sync_data_shm_id = static_cast<uint32>(c.sync_data_shm_id);
|
| + uint32 sync_data_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
|
| +
|
| + base::ScopedClosureRunner scoped_completion_callback;
|
| + if (async_upload_token) {
|
| + base::Closure completion_closure = AsyncUploadTokenCompletionClosure(
|
| + async_upload_token, sync_data_shm_id, sync_data_shm_offset);
|
| + if (completion_closure.is_null())
|
| + return error::kInvalidArguments;
|
| +
|
| + scoped_completion_callback.Reset(completion_closure);
|
| + }
|
| +
|
| + const void* pixels = NULL;
|
| + if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
|
| + pixels = GetSharedMemoryAs<const void*>(pixels_shm_id, pixels_shm_offset,
|
| + image_size);
|
| + if (!pixels) {
|
| + return error::kOutOfBounds;
|
| + }
|
| + }
|
| +
|
| + TextureManager::DoCompressedTexImage2DArguments args = {target,
|
| + level,
|
| + internal_format,
|
| + width,
|
| + height,
|
| + border,
|
| + image_size,
|
| + pixels};
|
| + TextureRef* texture_ref;
|
| + // All the normal glCompressedTexImage2D validation.
|
| + if (!texture_manager()->ValidateCompressedTexImage2D(
|
| + &state_, "glAsyncCompressedTexImage2DCHROMIUM", args, &texture_ref)) {
|
| + return error::kNoError;
|
| + }
|
| +
|
| + // Extra async validation.
|
| + Texture* texture = texture_ref->texture();
|
| + if (!ValidateAsyncTransfer("glAsyncCompressedTexImage2DCHROMIUM", texture_ref,
|
| + target, level, pixels))
|
| + return error::kNoError;
|
| +
|
| + // Don't allow async redefinition of a textures.
|
| + if (texture->IsDefined()) {
|
| + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
|
| + "glAsyncCompressedTexImage2DCHROMIUM",
|
| + "already defined");
|
| + return error::kNoError;
|
| + }
|
| +
|
| + if (!EnsureGPUMemoryAvailable(image_size)) {
|
| + LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glAsyncCompressedTexImage2DCHROMIUM",
|
| + "out of memory");
|
| + return error::kNoError;
|
| + }
|
| +
|
| + // Setup the parameters.
|
| + AsyncCompressedTexImage2DParams tex_params = {
|
| + target,
|
| + level,
|
| + static_cast<GLenum>(internal_format),
|
| + width,
|
| + height,
|
| + border,
|
| + image_size};
|
| + AsyncMemoryParams mem_params(GetSharedMemoryBuffer(c.pixels_shm_id),
|
| + c.pixels_shm_offset, image_size);
|
| +
|
| + // Set up the async state if needed, and make the texture
|
| + // immutable so the async state stays valid. The level info
|
| + // is set up lazily when the transfer completes.
|
| + AsyncPixelTransferDelegate* delegate =
|
| + async_pixel_transfer_manager_->CreatePixelTransferDelegate(texture_ref,
|
| + tex_params);
|
| + texture->SetImmutable(true);
|
| +
|
| + delegate->AsyncCompressedTexImage2D(
|
| + tex_params, mem_params,
|
| + base::Bind(&TextureManager::SetCompressedLevelInfoFromParams,
|
| + // The callback is only invoked if the transfer delegate still
|
| + // exists, which implies through manager->texture_ref->state
|
| + // ownership that both of these pointers are valid.
|
| + base::Unretained(texture_manager()),
|
| + base::Unretained(texture_ref), tex_params));
|
| + return error::kNoError;
|
| +}
|
| +
|
| +error::Error GLES2DecoderImpl::HandleAsyncCompressedTexSubImage2DCHROMIUM(
|
| + uint32 immediate_data_size,
|
| + const void* cmd_data) {
|
| + const gles2::cmds::AsyncCompressedTexSubImage2DCHROMIUM& c =
|
| + *static_cast<const gles2::cmds::AsyncCompressedTexSubImage2DCHROMIUM*>(
|
| + cmd_data);
|
| + TRACE_EVENT0("gpu",
|
| + "GLES2DecoderImpl::HandleAsyncCompressedTexSubImage2DCHROMIUM");
|
| + GLenum target = static_cast<GLenum>(c.target);
|
| + GLint level = static_cast<GLint>(c.level);
|
| + GLint xoffset = static_cast<GLint>(c.xoffset);
|
| + GLint yoffset = static_cast<GLint>(c.yoffset);
|
| + GLsizei width = static_cast<GLsizei>(c.width);
|
| + GLsizei height = static_cast<GLsizei>(c.height);
|
| + GLenum format = static_cast<GLenum>(c.format);
|
| + GLsizei image_size = static_cast<GLsizei>(c.imagesize);
|
| + uint32 async_upload_token = static_cast<uint32>(c.async_upload_token);
|
| + uint32 sync_data_shm_id = static_cast<uint32>(c.sync_data_shm_id);
|
| + uint32 sync_data_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
|
| +
|
| + base::ScopedClosureRunner scoped_completion_callback;
|
| + if (async_upload_token) {
|
| + base::Closure completion_closure = AsyncUploadTokenCompletionClosure(
|
| + async_upload_token, sync_data_shm_id, sync_data_shm_offset);
|
| + if (completion_closure.is_null())
|
| + return error::kInvalidArguments;
|
| +
|
| + scoped_completion_callback.Reset(completion_closure);
|
| + }
|
| +
|
| + const void* pixels = GetSharedMemoryAs<const void*>(
|
| + c.data_shm_id, c.data_shm_offset, image_size);
|
| +
|
| + // All the normal glCompressedTexSubImage2D validation.
|
| + error::Error error = error::kNoError;
|
| + if (!ValidateCompressedTexSubImage2D(
|
| + &error, "glAsyncCompressedTexSubImage2DCHROMIUM", target, level,
|
| + xoffset, yoffset, width, height, format, image_size, pixels)) {
|
| + return error;
|
| + }
|
| +
|
| + // Extra async validation.
|
| + TextureRef* texture_ref =
|
| + texture_manager()->GetTextureInfoForTarget(&state_, target);
|
| + Texture* texture = texture_ref->texture();
|
| + if (!ValidateAsyncTransfer("glAsyncCompressedTexSubImage2DCHROMIUM",
|
| + texture_ref, target, level, pixels))
|
| + return error::kNoError;
|
| +
|
| + // Guarantee async textures are always 'cleared' as follows:
|
| + // - AsyncCompressedTexImage2D can not redefine an existing texture
|
| + // - AsyncCompressedTexImage2D must initialize the entire image via non-null
|
| + // buffer.
|
| + // - AsyncCompressedTexSubImage2D clears synchronously if not already cleared.
|
| + // - Textures become immutable after an async call.
|
| + // This way we know in all cases that an async texture is always clear.
|
| + if (!texture->SafeToRenderFrom()) {
|
| + if (!texture_manager()->ClearTextureLevel(this, texture_ref, target,
|
| + level)) {
|
| + LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY,
|
| + "glAsyncCompressedTexSubImage2DCHROMIUM",
|
| + "dimensions too big");
|
| + return error::kNoError;
|
| + }
|
| + }
|
| +
|
| + // Setup the parameters.
|
| + AsyncCompressedTexSubImage2DParams tex_params = {target,
|
| + level,
|
| + xoffset,
|
| + yoffset,
|
| + width,
|
| + height,
|
| + static_cast<GLenum>(format),
|
| + image_size};
|
| + AsyncMemoryParams mem_params(GetSharedMemoryBuffer(c.data_shm_id),
|
| + c.data_shm_offset, image_size);
|
| + AsyncPixelTransferDelegate* delegate =
|
| + async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
|
| + if (!delegate) {
|
| + // TODO(epenner): We may want to enforce exclusive use
|
| + // of async APIs in which case this should become an error,
|
| + // (the texture should have been async defined).
|
| + AsyncCompressedTexImage2DParams define_params = {
|
| + target, level, 0, 0, 0, 0, 0};
|
| + texture->GetLevelSize(target, level, &define_params.width,
|
| + &define_params.height);
|
| + GLenum dummy_type;
|
| + texture->GetLevelType(target, level, &dummy_type,
|
| + &define_params.internal_format);
|
| +
|
| + // Set up the async state if needed, and make the texture
|
| + // immutable so the async state stays valid.
|
| + delegate = async_pixel_transfer_manager_->CreatePixelTransferDelegate(
|
| + texture_ref, define_params);
|
| + texture->SetImmutable(true);
|
| + }
|
| +
|
| + delegate->AsyncCompressedTexSubImage2D(tex_params, mem_params);
|
| + return error::kNoError;
|
| +}
|
| +
|
| error::Error GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM(
|
| uint32 immediate_data_size,
|
| const void* cmd_data) {
|
|
|