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 483 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
494 public: | 494 public: |
495 explicit ScopedFramebufferRestorer(WebGLRenderingContextBase* context) | 495 explicit ScopedFramebufferRestorer(WebGLRenderingContextBase* context) |
496 : m_context(context) {} | 496 : m_context(context) {} |
497 | 497 |
498 ~ScopedFramebufferRestorer() { m_context->restoreCurrentFramebuffer(); } | 498 ~ScopedFramebufferRestorer() { m_context->restoreCurrentFramebuffer(); } |
499 | 499 |
500 private: | 500 private: |
501 Member<WebGLRenderingContextBase> m_context; | 501 Member<WebGLRenderingContextBase> m_context; |
502 }; | 502 }; |
503 | 503 |
| 504 class ScopedUnpackParametersResetRestore { |
| 505 STACK_ALLOCATED(); |
| 506 |
| 507 public: |
| 508 explicit ScopedUnpackParametersResetRestore( |
| 509 WebGLRenderingContextBase* context, |
| 510 bool enabled = true) |
| 511 : m_context(context), m_enabled(enabled) { |
| 512 if (enabled) |
| 513 m_context->resetUnpackParameters(); |
| 514 } |
| 515 |
| 516 ~ScopedUnpackParametersResetRestore() { |
| 517 if (m_enabled) |
| 518 m_context->restoreUnpackParameters(); |
| 519 } |
| 520 |
| 521 private: |
| 522 Member<WebGLRenderingContextBase> m_context; |
| 523 bool m_enabled; |
| 524 }; |
| 525 |
504 static void formatWebGLStatusString(const StringView& glInfo, | 526 static void formatWebGLStatusString(const StringView& glInfo, |
505 const StringView& infoString, | 527 const StringView& infoString, |
506 StringBuilder& builder) { | 528 StringBuilder& builder) { |
507 if (infoString.isEmpty()) | 529 if (infoString.isEmpty()) |
508 return; | 530 return; |
509 builder.append(", "); | 531 builder.append(", "); |
510 builder.append(glInfo); | 532 builder.append(glInfo); |
511 builder.append(" = "); | 533 builder.append(" = "); |
512 builder.append(infoString); | 534 builder.append(infoString); |
513 } | 535 } |
(...skipping 3823 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4337 if (!WebGLImageConversion::packImageData( | 4359 if (!WebGLImageConversion::packImageData( |
4338 image, imagePixelData, format, type, flipY, alphaOp, | 4360 image, imagePixelData, format, type, flipY, alphaOp, |
4339 sourceDataFormat, imageExtractor.imageWidth(), | 4361 sourceDataFormat, imageExtractor.imageWidth(), |
4340 imageExtractor.imageHeight(), | 4362 imageExtractor.imageHeight(), |
4341 imageExtractor.imageSourceUnpackAlignment(), data)) { | 4363 imageExtractor.imageSourceUnpackAlignment(), data)) { |
4342 synthesizeGLError(GL_INVALID_VALUE, funcName, "packImage error"); | 4364 synthesizeGLError(GL_INVALID_VALUE, funcName, "packImage error"); |
4343 return; | 4365 return; |
4344 } | 4366 } |
4345 } | 4367 } |
4346 | 4368 |
4347 resetUnpackParameters(); | 4369 ScopedUnpackParametersResetRestore temporaryResetUnpack(this); |
4348 if (functionID == TexImage2D) { | 4370 if (functionID == TexImage2D) { |
4349 texImage2DBase(target, level, internalformat, imageExtractor.imageWidth(), | 4371 texImage2DBase(target, level, internalformat, imageExtractor.imageWidth(), |
4350 imageExtractor.imageHeight(), 0, format, type, | 4372 imageExtractor.imageHeight(), 0, format, type, |
4351 needConversion ? data.data() : imagePixelData); | 4373 needConversion ? data.data() : imagePixelData); |
4352 } else if (functionID == TexSubImage2D) { | 4374 } else if (functionID == TexSubImage2D) { |
4353 contextGL()->TexSubImage2D(target, level, xoffset, yoffset, | 4375 contextGL()->TexSubImage2D(target, level, xoffset, yoffset, |
4354 imageExtractor.imageWidth(), | 4376 imageExtractor.imageWidth(), |
4355 imageExtractor.imageHeight(), format, type, | 4377 imageExtractor.imageHeight(), format, type, |
4356 needConversion ? data.data() : imagePixelData); | 4378 needConversion ? data.data() : imagePixelData); |
4357 } else { | 4379 } else { |
4358 DCHECK_EQ(functionID, TexSubImage3D); | 4380 DCHECK_EQ(functionID, TexSubImage3D); |
4359 contextGL()->TexSubImage3D(target, level, xoffset, yoffset, zoffset, | 4381 contextGL()->TexSubImage3D(target, level, xoffset, yoffset, zoffset, |
4360 imageExtractor.imageWidth(), | 4382 imageExtractor.imageWidth(), |
4361 imageExtractor.imageHeight(), 1, format, type, | 4383 imageExtractor.imageHeight(), 1, format, type, |
4362 needConversion ? data.data() : imagePixelData); | 4384 needConversion ? data.data() : imagePixelData); |
4363 } | 4385 } |
4364 restoreUnpackParameters(); | |
4365 } | 4386 } |
4366 | 4387 |
4367 bool WebGLRenderingContextBase::validateTexFunc( | 4388 bool WebGLRenderingContextBase::validateTexFunc( |
4368 const char* functionName, | 4389 const char* functionName, |
4369 TexImageFunctionType functionType, | 4390 TexImageFunctionType functionType, |
4370 TexFuncValidationSourceType sourceType, | 4391 TexFuncValidationSourceType sourceType, |
4371 GLenum target, | 4392 GLenum target, |
4372 GLint level, | 4393 GLint level, |
4373 GLenum internalformat, | 4394 GLenum internalformat, |
4374 GLsizei width, | 4395 GLsizei width, |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4540 convertTexInternalFormat(internalformat, type), | 4561 convertTexInternalFormat(internalformat, type), |
4541 width, height, depth, border, format, type, data); | 4562 width, height, depth, border, format, type, data); |
4542 return; | 4563 return; |
4543 } | 4564 } |
4544 if (functionID == TexSubImage3D) { | 4565 if (functionID == TexSubImage3D) { |
4545 contextGL()->TexSubImage3D(target, level, xoffset, yoffset, zoffset, width, | 4566 contextGL()->TexSubImage3D(target, level, xoffset, yoffset, zoffset, width, |
4546 height, depth, format, type, data); | 4567 height, depth, format, type, data); |
4547 return; | 4568 return; |
4548 } | 4569 } |
4549 | 4570 |
4550 if (changeUnpackAlignment) | 4571 ScopedUnpackParametersResetRestore temporaryResetUnpack( |
4551 resetUnpackParameters(); | 4572 this, changeUnpackAlignment); |
4552 if (functionID == TexImage2D) | 4573 if (functionID == TexImage2D) |
4553 texImage2DBase(target, level, internalformat, width, height, border, format, | 4574 texImage2DBase(target, level, internalformat, width, height, border, format, |
4554 type, data); | 4575 type, data); |
4555 else if (functionID == TexSubImage2D) | 4576 else if (functionID == TexSubImage2D) |
4556 contextGL()->TexSubImage2D(target, level, xoffset, yoffset, width, height, | 4577 contextGL()->TexSubImage2D(target, level, xoffset, yoffset, width, height, |
4557 format, type, data); | 4578 format, type, data); |
4558 if (changeUnpackAlignment) | |
4559 restoreUnpackParameters(); | |
4560 } | 4579 } |
4561 | 4580 |
4562 void WebGLRenderingContextBase::texImage2D(GLenum target, | 4581 void WebGLRenderingContextBase::texImage2D(GLenum target, |
4563 GLint level, | 4582 GLint level, |
4564 GLint internalformat, | 4583 GLint internalformat, |
4565 GLsizei width, | 4584 GLsizei width, |
4566 GLsizei height, | 4585 GLsizei height, |
4567 GLint border, | 4586 GLint border, |
4568 GLenum format, | 4587 GLenum format, |
4569 GLenum type, | 4588 GLenum type, |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4623 type = GL_FLOAT; | 4642 type = GL_FLOAT; |
4624 } | 4643 } |
4625 if (!WebGLImageConversion::extractImageData( | 4644 if (!WebGLImageConversion::extractImageData( |
4626 pixels->data()->data(), | 4645 pixels->data()->data(), |
4627 WebGLImageConversion::DataFormat::DataFormatRGBA8, pixels->size(), | 4646 WebGLImageConversion::DataFormat::DataFormatRGBA8, pixels->size(), |
4628 format, type, m_unpackFlipY, m_unpackPremultiplyAlpha, data)) { | 4647 format, type, m_unpackFlipY, m_unpackPremultiplyAlpha, data)) { |
4629 synthesizeGLError(GL_INVALID_VALUE, funcName, "bad image data"); | 4648 synthesizeGLError(GL_INVALID_VALUE, funcName, "bad image data"); |
4630 return; | 4649 return; |
4631 } | 4650 } |
4632 } | 4651 } |
4633 resetUnpackParameters(); | 4652 ScopedUnpackParametersResetRestore temporaryResetUnpack(this); |
4634 if (functionID == TexImage2D) { | 4653 if (functionID == TexImage2D) { |
4635 texImage2DBase(target, level, internalformat, pixels->width(), | 4654 texImage2DBase(target, level, internalformat, pixels->width(), |
4636 pixels->height(), border, format, type, | 4655 pixels->height(), border, format, type, |
4637 needConversion ? data.data() : pixels->data()->data()); | 4656 needConversion ? data.data() : pixels->data()->data()); |
4638 } else if (functionID == TexSubImage2D) { | 4657 } else if (functionID == TexSubImage2D) { |
4639 contextGL()->TexSubImage2D( | 4658 contextGL()->TexSubImage2D( |
4640 target, level, xoffset, yoffset, pixels->width(), pixels->height(), | 4659 target, level, xoffset, yoffset, pixels->width(), pixels->height(), |
4641 format, type, needConversion ? data.data() : pixels->data()->data()); | 4660 format, type, needConversion ? data.data() : pixels->data()->data()); |
4642 } else { | 4661 } else { |
4643 DCHECK_EQ(functionID, TexSubImage3D); | 4662 DCHECK_EQ(functionID, TexSubImage3D); |
4644 contextGL()->TexSubImage3D( | 4663 contextGL()->TexSubImage3D( |
4645 target, level, xoffset, yoffset, zoffset, pixels->width(), | 4664 target, level, xoffset, yoffset, zoffset, pixels->width(), |
4646 pixels->height(), depth, format, type, | 4665 pixels->height(), depth, format, type, |
4647 needConversion ? data.data() : pixels->data()->data()); | 4666 needConversion ? data.data() : pixels->data()->data()); |
4648 } | 4667 } |
4649 restoreUnpackParameters(); | |
4650 } | 4668 } |
4651 | 4669 |
4652 void WebGLRenderingContextBase::texImage2D(GLenum target, | 4670 void WebGLRenderingContextBase::texImage2D(GLenum target, |
4653 GLint level, | 4671 GLint level, |
4654 GLint internalformat, | 4672 GLint internalformat, |
4655 GLenum format, | 4673 GLenum format, |
4656 GLenum type, | 4674 GLenum type, |
4657 ImageData* pixels) { | 4675 ImageData* pixels) { |
4658 texImageHelperImageData(TexImage2D, target, level, internalformat, 0, format, | 4676 texImageHelperImageData(TexImage2D, target, level, internalformat, 0, format, |
4659 type, 1, 0, 0, 0, pixels); | 4677 type, 1, 0, 0, 0, pixels); |
(...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4950 if (functionID == TexImage2D) | 4968 if (functionID == TexImage2D) |
4951 functionType = TexImage; | 4969 functionType = TexImage; |
4952 else | 4970 else |
4953 functionType = TexSubImage; | 4971 functionType = TexSubImage; |
4954 if (!validateTexFunc(funcName, functionType, SourceHTMLVideoElement, target, | 4972 if (!validateTexFunc(funcName, functionType, SourceHTMLVideoElement, target, |
4955 level, internalformat, video->videoWidth(), | 4973 level, internalformat, video->videoWidth(), |
4956 video->videoHeight(), 1, 0, format, type, xoffset, | 4974 video->videoHeight(), 1, 0, format, type, xoffset, |
4957 yoffset, zoffset)) | 4975 yoffset, zoffset)) |
4958 return; | 4976 return; |
4959 | 4977 |
4960 if (functionID == TexImage2D) { | 4978 const bool useCopyTextureChromium = |
| 4979 functionID == TexImage2D && GL_TEXTURE_2D == target && |
| 4980 Extensions3DUtil::canUseCopyTextureCHROMIUM(target, internalformat, type, |
| 4981 level); |
| 4982 if (useCopyTextureChromium) { |
4961 // Go through the fast path doing a GPU-GPU textures copy without a readback | 4983 // Go through the fast path doing a GPU-GPU textures copy without a readback |
4962 // to system memory if possible. Otherwise, it will fall back to the normal | 4984 // to system memory if possible. |
4963 // SW path. | 4985 // Otherwise, it will fall back to the normal SW path. |
4964 if (GL_TEXTURE_2D == target) { | 4986 if (video->copyVideoTextureToPlatformTexture( |
4965 if (Extensions3DUtil::canUseCopyTextureCHROMIUM(target, internalformat, | 4987 contextGL(), texture->object(), internalformat, type, |
4966 type, level) && | 4988 m_unpackPremultiplyAlpha, m_unpackFlipY)) { |
4967 video->copyVideoTextureToPlatformTexture( | 4989 return; |
4968 contextGL(), texture->object(), internalformat, type, | 4990 } |
4969 m_unpackPremultiplyAlpha, m_unpackFlipY)) { | 4991 } |
4970 return; | |
4971 } | |
4972 | 4992 |
4973 // Try using an accelerated image buffer, this allows YUV conversion to be | 4993 { |
4974 // done on the GPU. | 4994 // Try using optimized CPU-GPU path for some formats: e.g. Y16 and Y8. It |
4975 std::unique_ptr<ImageBufferSurface> surface = | 4995 // leaves early for other formats or if frame is stored on GPU. |
4976 wrapUnique(new AcceleratedImageBufferSurface( | 4996 ScopedUnpackParametersResetRestore( |
4977 IntSize(video->videoWidth(), video->videoHeight()))); | 4997 this, m_unpackFlipY || m_unpackPremultiplyAlpha); |
4978 if (surface->isValid()) { | 4998 if (video->texImageImpl(getTexImageFunctionName(functionID), target, |
4979 std::unique_ptr<ImageBuffer> imageBuffer( | 4999 contextGL(), level, internalformat, format, type, |
4980 ImageBuffer::create(std::move(surface))); | 5000 xoffset, yoffset, zoffset, m_unpackFlipY, |
4981 if (imageBuffer) { | 5001 m_unpackPremultiplyAlpha && |
4982 // The video element paints an RGBA frame into our surface here. By | 5002 m_unpackColorspaceConversion == GL_NONE)) |
4983 // using an AcceleratedImageBufferSurface, we enable the | 5003 return; |
4984 // WebMediaPlayer implementation to do any necessary color space | 5004 } |
4985 // conversion on the GPU (though it | |
4986 // may still do a CPU conversion and upload the results). | |
4987 video->paintCurrentFrame( | |
4988 imageBuffer->canvas(), | |
4989 IntRect(0, 0, video->videoWidth(), video->videoHeight()), | |
4990 nullptr); | |
4991 | 5005 |
4992 // This is a straight GPU-GPU copy, any necessary color space | 5006 if (useCopyTextureChromium) { |
4993 // conversion was handled in the paintCurrentFrameInContext() call. | 5007 // Try using an accelerated image buffer, this allows YUV conversion to be |
4994 if (imageBuffer->copyToPlatformTexture( | 5008 // done on the GPU. |
4995 contextGL(), texture->object(), internalformat, type, level, | 5009 std::unique_ptr<ImageBufferSurface> surface = |
4996 m_unpackPremultiplyAlpha, m_unpackFlipY)) { | 5010 wrapUnique(new AcceleratedImageBufferSurface( |
4997 return; | 5011 IntSize(video->videoWidth(), video->videoHeight()))); |
4998 } | 5012 if (surface->isValid()) { |
| 5013 std::unique_ptr<ImageBuffer> imageBuffer( |
| 5014 ImageBuffer::create(std::move(surface))); |
| 5015 if (imageBuffer) { |
| 5016 // The video element paints an RGBA frame into our surface here. By |
| 5017 // using an AcceleratedImageBufferSurface, we enable the WebMediaPlayer |
| 5018 // implementation to do any necessary color space conversion on the GPU |
| 5019 // (though it may still do a CPU conversion and upload the results). |
| 5020 video->paintCurrentFrame( |
| 5021 imageBuffer->canvas(), |
| 5022 IntRect(0, 0, video->videoWidth(), video->videoHeight()), nullptr); |
| 5023 |
| 5024 // This is a straight GPU-GPU copy, any necessary color space conversion |
| 5025 // was handled in the paintCurrentFrameInContext() call. |
| 5026 if (imageBuffer->copyToPlatformTexture( |
| 5027 contextGL(), texture->object(), internalformat, type, level, |
| 5028 m_unpackPremultiplyAlpha, m_unpackFlipY)) { |
| 5029 return; |
4999 } | 5030 } |
5000 } | 5031 } |
5001 } | 5032 } |
5002 } | 5033 } |
5003 | 5034 |
5004 RefPtr<Image> image = videoFrameToImage(video); | 5035 RefPtr<Image> image = videoFrameToImage(video); |
5005 if (!image) | 5036 if (!image) |
5006 return; | 5037 return; |
5007 texImageImpl(functionID, target, level, internalformat, xoffset, yoffset, | 5038 texImageImpl(functionID, target, level, internalformat, xoffset, yoffset, |
5008 zoffset, format, type, image.get(), | 5039 zoffset, format, type, image.get(), |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5113 pixelDataPtr, WebGLImageConversion::DataFormat::DataFormatBGRA8, | 5144 pixelDataPtr, WebGLImageConversion::DataFormat::DataFormatBGRA8, |
5114 bitmap->size(), format, type, false, false, data)) || | 5145 bitmap->size(), format, type, false, false, data)) || |
5115 (isPixelDataRGBA && | 5146 (isPixelDataRGBA && |
5116 !WebGLImageConversion::extractImageData( | 5147 !WebGLImageConversion::extractImageData( |
5117 pixelDataPtr, WebGLImageConversion::DataFormat::DataFormatRGBA8, | 5148 pixelDataPtr, WebGLImageConversion::DataFormat::DataFormatRGBA8, |
5118 bitmap->size(), format, type, false, false, data))) { | 5149 bitmap->size(), format, type, false, false, data))) { |
5119 synthesizeGLError(GL_INVALID_VALUE, funcName, "bad image data"); | 5150 synthesizeGLError(GL_INVALID_VALUE, funcName, "bad image data"); |
5120 return; | 5151 return; |
5121 } | 5152 } |
5122 } | 5153 } |
5123 resetUnpackParameters(); | 5154 ScopedUnpackParametersResetRestore temporaryResetUnpack(this); |
5124 if (functionID == TexImage2D) { | 5155 if (functionID == TexImage2D) { |
5125 texImage2DBase(target, level, internalformat, bitmap->width(), | 5156 texImage2DBase(target, level, internalformat, bitmap->width(), |
5126 bitmap->height(), 0, format, type, | 5157 bitmap->height(), 0, format, type, |
5127 needConversion ? data.data() : pixelDataPtr); | 5158 needConversion ? data.data() : pixelDataPtr); |
5128 } else if (functionID == TexSubImage2D) { | 5159 } else if (functionID == TexSubImage2D) { |
5129 contextGL()->TexSubImage2D(target, level, xoffset, yoffset, bitmap->width(), | 5160 contextGL()->TexSubImage2D(target, level, xoffset, yoffset, bitmap->width(), |
5130 bitmap->height(), format, type, | 5161 bitmap->height(), format, type, |
5131 needConversion ? data.data() : pixelDataPtr); | 5162 needConversion ? data.data() : pixelDataPtr); |
5132 } else { | 5163 } else { |
5133 DCHECK_EQ(functionID, TexSubImage3D); | 5164 DCHECK_EQ(functionID, TexSubImage3D); |
5134 contextGL()->TexSubImage3D(target, level, xoffset, yoffset, zoffset, | 5165 contextGL()->TexSubImage3D(target, level, xoffset, yoffset, zoffset, |
5135 bitmap->width(), bitmap->height(), 1, format, | 5166 bitmap->width(), bitmap->height(), 1, format, |
5136 type, | 5167 type, |
5137 needConversion ? data.data() : pixelDataPtr); | 5168 needConversion ? data.data() : pixelDataPtr); |
5138 } | 5169 } |
5139 restoreUnpackParameters(); | |
5140 } | 5170 } |
5141 | 5171 |
5142 void WebGLRenderingContextBase::texImage2D(GLenum target, | 5172 void WebGLRenderingContextBase::texImage2D(GLenum target, |
5143 GLint level, | 5173 GLint level, |
5144 GLint internalformat, | 5174 GLint internalformat, |
5145 GLenum format, | 5175 GLenum format, |
5146 GLenum type, | 5176 GLenum type, |
5147 ImageBitmap* bitmap, | 5177 ImageBitmap* bitmap, |
5148 ExceptionState& exceptionState) { | 5178 ExceptionState& exceptionState) { |
5149 texImageHelperImageBitmap(TexImage2D, target, level, internalformat, format, | 5179 texImageHelperImageBitmap(TexImage2D, target, level, internalformat, format, |
(...skipping 2370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7520 | 7550 |
7521 void WebGLRenderingContextBase::getHTMLOrOffscreenCanvas( | 7551 void WebGLRenderingContextBase::getHTMLOrOffscreenCanvas( |
7522 HTMLCanvasElementOrOffscreenCanvas& result) const { | 7552 HTMLCanvasElementOrOffscreenCanvas& result) const { |
7523 if (canvas()) | 7553 if (canvas()) |
7524 result.setHTMLCanvasElement(canvas()); | 7554 result.setHTMLCanvasElement(canvas()); |
7525 else | 7555 else |
7526 result.setOffscreenCanvas(getOffscreenCanvas()); | 7556 result.setOffscreenCanvas(getOffscreenCanvas()); |
7527 } | 7557 } |
7528 | 7558 |
7529 } // namespace blink | 7559 } // namespace blink |
OLD | NEW |