OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2009 Apple Inc. All rights reserved. | 2 * Copyright (C) 2009 Apple Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
(...skipping 482 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
493 public: | 493 public: |
494 explicit ScopedFramebufferRestorer(WebGLRenderingContextBase* context) | 494 explicit ScopedFramebufferRestorer(WebGLRenderingContextBase* context) |
495 : m_context(context) {} | 495 : m_context(context) {} |
496 | 496 |
497 ~ScopedFramebufferRestorer() { m_context->restoreCurrentFramebuffer(); } | 497 ~ScopedFramebufferRestorer() { m_context->restoreCurrentFramebuffer(); } |
498 | 498 |
499 private: | 499 private: |
500 Member<WebGLRenderingContextBase> m_context; | 500 Member<WebGLRenderingContextBase> m_context; |
501 }; | 501 }; |
502 | 502 |
| 503 class ScopedUnpackParametersResetRestore { |
| 504 STACK_ALLOCATED(); |
| 505 |
| 506 public: |
| 507 explicit ScopedUnpackParametersResetRestore( |
| 508 WebGLRenderingContextBase* context, |
| 509 bool enabled = true) |
| 510 : m_context(context), m_enabled(enabled) { |
| 511 if (enabled) |
| 512 m_context->resetUnpackParameters(); |
| 513 } |
| 514 |
| 515 ~ScopedUnpackParametersResetRestore() { |
| 516 if (m_enabled) |
| 517 m_context->restoreUnpackParameters(); |
| 518 } |
| 519 |
| 520 private: |
| 521 Member<WebGLRenderingContextBase> m_context; |
| 522 bool m_enabled; |
| 523 }; |
| 524 |
503 static void formatWebGLStatusString(const StringView& glInfo, | 525 static void formatWebGLStatusString(const StringView& glInfo, |
504 const StringView& infoString, | 526 const StringView& infoString, |
505 StringBuilder& builder) { | 527 StringBuilder& builder) { |
506 if (infoString.isEmpty()) | 528 if (infoString.isEmpty()) |
507 return; | 529 return; |
508 builder.append(", "); | 530 builder.append(", "); |
509 builder.append(glInfo); | 531 builder.append(glInfo); |
510 builder.append(" = "); | 532 builder.append(" = "); |
511 builder.append(infoString); | 533 builder.append(infoString); |
512 } | 534 } |
(...skipping 3884 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4397 if (!WebGLImageConversion::packImageData( | 4419 if (!WebGLImageConversion::packImageData( |
4398 image, imagePixelData, format, type, flipY, alphaOp, | 4420 image, imagePixelData, format, type, flipY, alphaOp, |
4399 sourceDataFormat, imageExtractor.imageWidth(), | 4421 sourceDataFormat, imageExtractor.imageWidth(), |
4400 imageExtractor.imageHeight(), | 4422 imageExtractor.imageHeight(), |
4401 imageExtractor.imageSourceUnpackAlignment(), data)) { | 4423 imageExtractor.imageSourceUnpackAlignment(), data)) { |
4402 synthesizeGLError(GL_INVALID_VALUE, funcName, "packImage error"); | 4424 synthesizeGLError(GL_INVALID_VALUE, funcName, "packImage error"); |
4403 return; | 4425 return; |
4404 } | 4426 } |
4405 } | 4427 } |
4406 | 4428 |
4407 resetUnpackParameters(); | 4429 ScopedUnpackParametersResetRestore temporaryResetUnpack(this); |
4408 if (functionID == TexImage2D) { | 4430 if (functionID == TexImage2D) { |
4409 texImage2DBase(target, level, internalformat, imageExtractor.imageWidth(), | 4431 texImage2DBase(target, level, internalformat, imageExtractor.imageWidth(), |
4410 imageExtractor.imageHeight(), 0, format, type, | 4432 imageExtractor.imageHeight(), 0, format, type, |
4411 needConversion ? data.data() : imagePixelData); | 4433 needConversion ? data.data() : imagePixelData); |
4412 } else if (functionID == TexSubImage2D) { | 4434 } else if (functionID == TexSubImage2D) { |
4413 contextGL()->TexSubImage2D(target, level, xoffset, yoffset, | 4435 contextGL()->TexSubImage2D(target, level, xoffset, yoffset, |
4414 imageExtractor.imageWidth(), | 4436 imageExtractor.imageWidth(), |
4415 imageExtractor.imageHeight(), format, type, | 4437 imageExtractor.imageHeight(), format, type, |
4416 needConversion ? data.data() : imagePixelData); | 4438 needConversion ? data.data() : imagePixelData); |
4417 } else { | 4439 } else { |
4418 DCHECK_EQ(functionID, TexSubImage3D); | 4440 DCHECK_EQ(functionID, TexSubImage3D); |
4419 contextGL()->TexSubImage3D(target, level, xoffset, yoffset, zoffset, | 4441 contextGL()->TexSubImage3D(target, level, xoffset, yoffset, zoffset, |
4420 imageExtractor.imageWidth(), | 4442 imageExtractor.imageWidth(), |
4421 imageExtractor.imageHeight(), 1, format, type, | 4443 imageExtractor.imageHeight(), 1, format, type, |
4422 needConversion ? data.data() : imagePixelData); | 4444 needConversion ? data.data() : imagePixelData); |
4423 } | 4445 } |
4424 restoreUnpackParameters(); | |
4425 } | 4446 } |
4426 | 4447 |
4427 bool WebGLRenderingContextBase::validateTexFunc( | 4448 bool WebGLRenderingContextBase::validateTexFunc( |
4428 const char* functionName, | 4449 const char* functionName, |
4429 TexImageFunctionType functionType, | 4450 TexImageFunctionType functionType, |
4430 TexFuncValidationSourceType sourceType, | 4451 TexFuncValidationSourceType sourceType, |
4431 GLenum target, | 4452 GLenum target, |
4432 GLint level, | 4453 GLint level, |
4433 GLenum internalformat, | 4454 GLenum internalformat, |
4434 GLsizei width, | 4455 GLsizei width, |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4600 convertTexInternalFormat(internalformat, type), | 4621 convertTexInternalFormat(internalformat, type), |
4601 width, height, depth, border, format, type, data); | 4622 width, height, depth, border, format, type, data); |
4602 return; | 4623 return; |
4603 } | 4624 } |
4604 if (functionID == TexSubImage3D) { | 4625 if (functionID == TexSubImage3D) { |
4605 contextGL()->TexSubImage3D(target, level, xoffset, yoffset, zoffset, width, | 4626 contextGL()->TexSubImage3D(target, level, xoffset, yoffset, zoffset, width, |
4606 height, depth, format, type, data); | 4627 height, depth, format, type, data); |
4607 return; | 4628 return; |
4608 } | 4629 } |
4609 | 4630 |
4610 if (changeUnpackAlignment) | 4631 ScopedUnpackParametersResetRestore temporaryResetUnpack( |
4611 resetUnpackParameters(); | 4632 this, changeUnpackAlignment); |
4612 if (functionID == TexImage2D) | 4633 if (functionID == TexImage2D) |
4613 texImage2DBase(target, level, internalformat, width, height, border, format, | 4634 texImage2DBase(target, level, internalformat, width, height, border, format, |
4614 type, data); | 4635 type, data); |
4615 else if (functionID == TexSubImage2D) | 4636 else if (functionID == TexSubImage2D) |
4616 contextGL()->TexSubImage2D(target, level, xoffset, yoffset, width, height, | 4637 contextGL()->TexSubImage2D(target, level, xoffset, yoffset, width, height, |
4617 format, type, data); | 4638 format, type, data); |
4618 if (changeUnpackAlignment) | |
4619 restoreUnpackParameters(); | |
4620 } | 4639 } |
4621 | 4640 |
4622 void WebGLRenderingContextBase::texImage2D(GLenum target, | 4641 void WebGLRenderingContextBase::texImage2D(GLenum target, |
4623 GLint level, | 4642 GLint level, |
4624 GLint internalformat, | 4643 GLint internalformat, |
4625 GLsizei width, | 4644 GLsizei width, |
4626 GLsizei height, | 4645 GLsizei height, |
4627 GLint border, | 4646 GLint border, |
4628 GLenum format, | 4647 GLenum format, |
4629 GLenum type, | 4648 GLenum type, |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4683 type = GL_FLOAT; | 4702 type = GL_FLOAT; |
4684 } | 4703 } |
4685 if (!WebGLImageConversion::extractImageData( | 4704 if (!WebGLImageConversion::extractImageData( |
4686 pixels->data()->data(), | 4705 pixels->data()->data(), |
4687 WebGLImageConversion::DataFormat::DataFormatRGBA8, pixels->size(), | 4706 WebGLImageConversion::DataFormat::DataFormatRGBA8, pixels->size(), |
4688 format, type, m_unpackFlipY, m_unpackPremultiplyAlpha, data)) { | 4707 format, type, m_unpackFlipY, m_unpackPremultiplyAlpha, data)) { |
4689 synthesizeGLError(GL_INVALID_VALUE, funcName, "bad image data"); | 4708 synthesizeGLError(GL_INVALID_VALUE, funcName, "bad image data"); |
4690 return; | 4709 return; |
4691 } | 4710 } |
4692 } | 4711 } |
4693 resetUnpackParameters(); | 4712 ScopedUnpackParametersResetRestore temporaryResetUnpack(this); |
4694 if (functionID == TexImage2D) { | 4713 if (functionID == TexImage2D) { |
4695 texImage2DBase(target, level, internalformat, pixels->width(), | 4714 texImage2DBase(target, level, internalformat, pixels->width(), |
4696 pixels->height(), border, format, type, | 4715 pixels->height(), border, format, type, |
4697 needConversion ? data.data() : pixels->data()->data()); | 4716 needConversion ? data.data() : pixels->data()->data()); |
4698 } else if (functionID == TexSubImage2D) { | 4717 } else if (functionID == TexSubImage2D) { |
4699 contextGL()->TexSubImage2D( | 4718 contextGL()->TexSubImage2D( |
4700 target, level, xoffset, yoffset, pixels->width(), pixels->height(), | 4719 target, level, xoffset, yoffset, pixels->width(), pixels->height(), |
4701 format, type, needConversion ? data.data() : pixels->data()->data()); | 4720 format, type, needConversion ? data.data() : pixels->data()->data()); |
4702 } else { | 4721 } else { |
4703 DCHECK_EQ(functionID, TexSubImage3D); | 4722 DCHECK_EQ(functionID, TexSubImage3D); |
4704 contextGL()->TexSubImage3D( | 4723 contextGL()->TexSubImage3D( |
4705 target, level, xoffset, yoffset, zoffset, pixels->width(), | 4724 target, level, xoffset, yoffset, zoffset, pixels->width(), |
4706 pixels->height(), depth, format, type, | 4725 pixels->height(), depth, format, type, |
4707 needConversion ? data.data() : pixels->data()->data()); | 4726 needConversion ? data.data() : pixels->data()->data()); |
4708 } | 4727 } |
4709 restoreUnpackParameters(); | |
4710 } | 4728 } |
4711 | 4729 |
4712 void WebGLRenderingContextBase::texImage2D(GLenum target, | 4730 void WebGLRenderingContextBase::texImage2D(GLenum target, |
4713 GLint level, | 4731 GLint level, |
4714 GLint internalformat, | 4732 GLint internalformat, |
4715 GLenum format, | 4733 GLenum format, |
4716 GLenum type, | 4734 GLenum type, |
4717 ImageData* pixels) { | 4735 ImageData* pixels) { |
4718 texImageHelperImageData(TexImage2D, target, level, internalformat, 0, format, | 4736 texImageHelperImageData(TexImage2D, target, level, internalformat, 0, format, |
4719 type, 1, 0, 0, 0, pixels); | 4737 type, 1, 0, 0, 0, pixels); |
(...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5010 if (functionID == TexImage2D) | 5028 if (functionID == TexImage2D) |
5011 functionType = TexImage; | 5029 functionType = TexImage; |
5012 else | 5030 else |
5013 functionType = TexSubImage; | 5031 functionType = TexSubImage; |
5014 if (!validateTexFunc(funcName, functionType, SourceHTMLVideoElement, target, | 5032 if (!validateTexFunc(funcName, functionType, SourceHTMLVideoElement, target, |
5015 level, internalformat, video->videoWidth(), | 5033 level, internalformat, video->videoWidth(), |
5016 video->videoHeight(), 1, 0, format, type, xoffset, | 5034 video->videoHeight(), 1, 0, format, type, xoffset, |
5017 yoffset, zoffset)) | 5035 yoffset, zoffset)) |
5018 return; | 5036 return; |
5019 | 5037 |
5020 if (functionID == TexImage2D) { | 5038 const bool useCopyTextureChromium = |
| 5039 functionID == TexImage2D && GL_TEXTURE_2D == target && |
| 5040 Extensions3DUtil::canUseCopyTextureCHROMIUM(target, internalformat, type, |
| 5041 level); |
| 5042 if (useCopyTextureChromium) { |
5021 // Go through the fast path doing a GPU-GPU textures copy without a readback | 5043 // Go through the fast path doing a GPU-GPU textures copy without a readback |
5022 // to system memory if possible. Otherwise, it will fall back to the normal | 5044 // to system memory if possible. |
5023 // SW path. | 5045 // Otherwise, it will fall back to the normal SW path. |
5024 if (GL_TEXTURE_2D == target) { | 5046 if (video->copyVideoTextureToPlatformTexture( |
5025 if (Extensions3DUtil::canUseCopyTextureCHROMIUM(target, internalformat, | 5047 contextGL(), texture->object(), internalformat, type, |
5026 type, level) && | 5048 m_unpackPremultiplyAlpha, m_unpackFlipY)) { |
5027 video->copyVideoTextureToPlatformTexture( | 5049 return; |
5028 contextGL(), texture->object(), internalformat, type, | 5050 } |
5029 m_unpackPremultiplyAlpha, m_unpackFlipY)) { | 5051 } |
5030 return; | |
5031 } | |
5032 | 5052 |
5033 // Try using an accelerated image buffer, this allows YUV conversion to be | 5053 { |
5034 // done on the GPU. | 5054 // Try using optimized CPU-GPU path for some formats: e.g. Y16 and Y8. It |
5035 std::unique_ptr<ImageBufferSurface> surface = | 5055 // leaves early for other formats or if frame is stored on GPU. |
5036 wrapUnique(new AcceleratedImageBufferSurface( | 5056 ScopedUnpackParametersResetRestore( |
5037 IntSize(video->videoWidth(), video->videoHeight()))); | 5057 this, m_unpackFlipY || m_unpackPremultiplyAlpha); |
5038 if (surface->isValid()) { | 5058 if (video->texImageImpl(getTexImageFunctionName(functionID), target, |
5039 std::unique_ptr<ImageBuffer> imageBuffer( | 5059 contextGL(), level, internalformat, format, type, |
5040 ImageBuffer::create(std::move(surface))); | 5060 xoffset, yoffset, zoffset, m_unpackFlipY, |
5041 if (imageBuffer) { | 5061 m_unpackPremultiplyAlpha && |
5042 // The video element paints an RGBA frame into our surface here. By | 5062 m_unpackColorspaceConversion == GL_NONE)) |
5043 // using an AcceleratedImageBufferSurface, we enable the | 5063 return; |
5044 // WebMediaPlayer implementation to do any necessary color space | 5064 } |
5045 // conversion on the GPU (though it | |
5046 // may still do a CPU conversion and upload the results). | |
5047 video->paintCurrentFrame( | |
5048 imageBuffer->canvas(), | |
5049 IntRect(0, 0, video->videoWidth(), video->videoHeight()), | |
5050 nullptr); | |
5051 | 5065 |
5052 // This is a straight GPU-GPU copy, any necessary color space | 5066 if (useCopyTextureChromium) { |
5053 // conversion was handled in the paintCurrentFrameInContext() call. | 5067 // Try using an accelerated image buffer, this allows YUV conversion to be |
5054 if (imageBuffer->copyToPlatformTexture( | 5068 // done on the GPU. |
5055 contextGL(), texture->object(), internalformat, type, level, | 5069 std::unique_ptr<ImageBufferSurface> surface = |
5056 m_unpackPremultiplyAlpha, m_unpackFlipY)) { | 5070 wrapUnique(new AcceleratedImageBufferSurface( |
5057 return; | 5071 IntSize(video->videoWidth(), video->videoHeight()))); |
5058 } | 5072 if (surface->isValid()) { |
| 5073 std::unique_ptr<ImageBuffer> imageBuffer( |
| 5074 ImageBuffer::create(std::move(surface))); |
| 5075 if (imageBuffer) { |
| 5076 // The video element paints an RGBA frame into our surface here. By |
| 5077 // using an AcceleratedImageBufferSurface, we enable the WebMediaPlayer |
| 5078 // implementation to do any necessary color space conversion on the GPU |
| 5079 // (though it may still do a CPU conversion and upload the results). |
| 5080 video->paintCurrentFrame( |
| 5081 imageBuffer->canvas(), |
| 5082 IntRect(0, 0, video->videoWidth(), video->videoHeight()), nullptr); |
| 5083 |
| 5084 // This is a straight GPU-GPU copy, any necessary color space conversion |
| 5085 // was handled in the paintCurrentFrameInContext() call. |
| 5086 if (imageBuffer->copyToPlatformTexture( |
| 5087 contextGL(), texture->object(), internalformat, type, level, |
| 5088 m_unpackPremultiplyAlpha, m_unpackFlipY)) { |
| 5089 return; |
5059 } | 5090 } |
5060 } | 5091 } |
5061 } | 5092 } |
5062 } | 5093 } |
5063 | 5094 |
5064 RefPtr<Image> image = videoFrameToImage(video); | 5095 RefPtr<Image> image = videoFrameToImage(video); |
5065 if (!image) | 5096 if (!image) |
5066 return; | 5097 return; |
5067 texImageImpl(functionID, target, level, internalformat, xoffset, yoffset, | 5098 texImageImpl(functionID, target, level, internalformat, xoffset, yoffset, |
5068 zoffset, format, type, image.get(), | 5099 zoffset, format, type, image.get(), |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5173 pixelDataPtr, WebGLImageConversion::DataFormat::DataFormatBGRA8, | 5204 pixelDataPtr, WebGLImageConversion::DataFormat::DataFormatBGRA8, |
5174 bitmap->size(), format, type, false, false, data)) || | 5205 bitmap->size(), format, type, false, false, data)) || |
5175 (isPixelDataRGBA && | 5206 (isPixelDataRGBA && |
5176 !WebGLImageConversion::extractImageData( | 5207 !WebGLImageConversion::extractImageData( |
5177 pixelDataPtr, WebGLImageConversion::DataFormat::DataFormatRGBA8, | 5208 pixelDataPtr, WebGLImageConversion::DataFormat::DataFormatRGBA8, |
5178 bitmap->size(), format, type, false, false, data))) { | 5209 bitmap->size(), format, type, false, false, data))) { |
5179 synthesizeGLError(GL_INVALID_VALUE, funcName, "bad image data"); | 5210 synthesizeGLError(GL_INVALID_VALUE, funcName, "bad image data"); |
5180 return; | 5211 return; |
5181 } | 5212 } |
5182 } | 5213 } |
5183 resetUnpackParameters(); | 5214 ScopedUnpackParametersResetRestore temporaryResetUnpack(this); |
5184 if (functionID == TexImage2D) { | 5215 if (functionID == TexImage2D) { |
5185 texImage2DBase(target, level, internalformat, bitmap->width(), | 5216 texImage2DBase(target, level, internalformat, bitmap->width(), |
5186 bitmap->height(), 0, format, type, | 5217 bitmap->height(), 0, format, type, |
5187 needConversion ? data.data() : pixelDataPtr); | 5218 needConversion ? data.data() : pixelDataPtr); |
5188 } else if (functionID == TexSubImage2D) { | 5219 } else if (functionID == TexSubImage2D) { |
5189 contextGL()->TexSubImage2D(target, level, xoffset, yoffset, bitmap->width(), | 5220 contextGL()->TexSubImage2D(target, level, xoffset, yoffset, bitmap->width(), |
5190 bitmap->height(), format, type, | 5221 bitmap->height(), format, type, |
5191 needConversion ? data.data() : pixelDataPtr); | 5222 needConversion ? data.data() : pixelDataPtr); |
5192 } else { | 5223 } else { |
5193 DCHECK_EQ(functionID, TexSubImage3D); | 5224 DCHECK_EQ(functionID, TexSubImage3D); |
5194 contextGL()->TexSubImage3D(target, level, xoffset, yoffset, zoffset, | 5225 contextGL()->TexSubImage3D(target, level, xoffset, yoffset, zoffset, |
5195 bitmap->width(), bitmap->height(), 1, format, | 5226 bitmap->width(), bitmap->height(), 1, format, |
5196 type, | 5227 type, |
5197 needConversion ? data.data() : pixelDataPtr); | 5228 needConversion ? data.data() : pixelDataPtr); |
5198 } | 5229 } |
5199 restoreUnpackParameters(); | |
5200 } | 5230 } |
5201 | 5231 |
5202 void WebGLRenderingContextBase::texImage2D(GLenum target, | 5232 void WebGLRenderingContextBase::texImage2D(GLenum target, |
5203 GLint level, | 5233 GLint level, |
5204 GLint internalformat, | 5234 GLint internalformat, |
5205 GLenum format, | 5235 GLenum format, |
5206 GLenum type, | 5236 GLenum type, |
5207 ImageBitmap* bitmap, | 5237 ImageBitmap* bitmap, |
5208 ExceptionState& exceptionState) { | 5238 ExceptionState& exceptionState) { |
5209 texImageHelperImageBitmap(TexImage2D, target, level, internalformat, format, | 5239 texImageHelperImageBitmap(TexImage2D, target, level, internalformat, format, |
(...skipping 2321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7531 | 7561 |
7532 void WebGLRenderingContextBase::getHTMLOrOffscreenCanvas( | 7562 void WebGLRenderingContextBase::getHTMLOrOffscreenCanvas( |
7533 HTMLCanvasElementOrOffscreenCanvas& result) const { | 7563 HTMLCanvasElementOrOffscreenCanvas& result) const { |
7534 if (canvas()) | 7564 if (canvas()) |
7535 result.setHTMLCanvasElement(canvas()); | 7565 result.setHTMLCanvasElement(canvas()); |
7536 else | 7566 else |
7537 result.setOffscreenCanvas(getOffscreenCanvas()); | 7567 result.setOffscreenCanvas(getOffscreenCanvas()); |
7538 } | 7568 } |
7539 | 7569 |
7540 } // namespace blink | 7570 } // namespace blink |
OLD | NEW |