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 4329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4340 GLint internalformat, | 4340 GLint internalformat, |
4341 GLint xoffset, | 4341 GLint xoffset, |
4342 GLint yoffset, | 4342 GLint yoffset, |
4343 GLint zoffset, | 4343 GLint zoffset, |
4344 GLenum format, | 4344 GLenum format, |
4345 GLenum type, | 4345 GLenum type, |
4346 Image* image, | 4346 Image* image, |
4347 WebGLImageConversion::ImageHtmlDomSource domSource, | 4347 WebGLImageConversion::ImageHtmlDomSource domSource, |
4348 bool flipY, | 4348 bool flipY, |
4349 bool premultiplyAlpha, | 4349 bool premultiplyAlpha, |
4350 const IntRect& sourceImageRect) { | 4350 const IntRect& sourceImageRect, |
| 4351 GLsizei depth, |
| 4352 GLint unpackImageHeight) { |
4351 const char* funcName = getTexImageFunctionName(functionID); | 4353 const char* funcName = getTexImageFunctionName(functionID); |
4352 // All calling functions check isContextLost, so a duplicate check is not | 4354 // All calling functions check isContextLost, so a duplicate check is not |
4353 // needed here. | 4355 // needed here. |
4354 if (type == GL_UNSIGNED_INT_10F_11F_11F_REV) { | 4356 if (type == GL_UNSIGNED_INT_10F_11F_11F_REV) { |
4355 // The UNSIGNED_INT_10F_11F_11F_REV type pack/unpack isn't implemented. | 4357 // The UNSIGNED_INT_10F_11F_11F_REV type pack/unpack isn't implemented. |
4356 type = GL_FLOAT; | 4358 type = GL_FLOAT; |
4357 } | 4359 } |
4358 Vector<uint8_t> data; | 4360 Vector<uint8_t> data; |
4359 | 4361 |
4360 IntRect subRect = sourceImageRect; | 4362 IntRect subRect = sourceImageRect; |
(...skipping 19 matching lines...) Expand all Loading... |
4380 | 4382 |
4381 if (subRect.x() < 0 || subRect.y() < 0 || subRect.maxX() > image->width() || | 4383 if (subRect.x() < 0 || subRect.y() < 0 || subRect.maxX() > image->width() || |
4382 subRect.maxY() > image->height() || subRect.width() < 0 || | 4384 subRect.maxY() > image->height() || subRect.width() < 0 || |
4383 subRect.height() < 0) { | 4385 subRect.height() < 0) { |
4384 synthesizeGLError(GL_INVALID_OPERATION, funcName, | 4386 synthesizeGLError(GL_INVALID_OPERATION, funcName, |
4385 "source sub-rectangle specified via pixel unpack " | 4387 "source sub-rectangle specified via pixel unpack " |
4386 "parameters is invalid"); | 4388 "parameters is invalid"); |
4387 return; | 4389 return; |
4388 } | 4390 } |
4389 | 4391 |
| 4392 if (functionID == TexImage3D || functionID == TexSubImage3D) { |
| 4393 DCHECK_GE(unpackImageHeight, 0); |
| 4394 |
| 4395 // Verify that the image data can cover the required depth. |
| 4396 CheckedNumeric<GLint> maxDepthSupported = 1; |
| 4397 if (unpackImageHeight) { |
| 4398 maxDepthSupported = subRect.height(); |
| 4399 maxDepthSupported /= unpackImageHeight; |
| 4400 } |
| 4401 |
| 4402 if (!maxDepthSupported.IsValid() || |
| 4403 maxDepthSupported.ValueOrDie() < depth) { |
| 4404 synthesizeGLError( |
| 4405 GL_INVALID_OPERATION, funcName, |
| 4406 "Not enough data supplied to upload to a 3D texture with depth > 1"); |
| 4407 return; |
| 4408 } |
| 4409 } else { |
| 4410 DCHECK_EQ(depth, 1); |
| 4411 DCHECK_EQ(unpackImageHeight, 0); |
| 4412 } |
| 4413 |
4390 // Adjust the source image rectangle if doing a y-flip. | 4414 // Adjust the source image rectangle if doing a y-flip. |
4391 IntRect adjustedSourceImageRect = subRect; | 4415 IntRect adjustedSourceImageRect = subRect; |
4392 if (flipY) { | 4416 if (flipY) { |
4393 adjustedSourceImageRect.setY(image->height() - | 4417 adjustedSourceImageRect.setY(image->height() - |
4394 adjustedSourceImageRect.maxY()); | 4418 adjustedSourceImageRect.maxY()); |
4395 } | 4419 } |
4396 | 4420 |
4397 WebGLImageConversion::ImageExtractor imageExtractor( | 4421 WebGLImageConversion::ImageExtractor imageExtractor( |
4398 image, domSource, premultiplyAlpha, | 4422 image, domSource, premultiplyAlpha, |
4399 m_unpackColorspaceConversion == GL_NONE); | 4423 m_unpackColorspaceConversion == GL_NONE); |
(...skipping 29 matching lines...) Expand all Loading... |
4429 texImage2DBase(target, level, internalformat, | 4453 texImage2DBase(target, level, internalformat, |
4430 adjustedSourceImageRect.width(), | 4454 adjustedSourceImageRect.width(), |
4431 adjustedSourceImageRect.height(), 0, format, type, | 4455 adjustedSourceImageRect.height(), 0, format, type, |
4432 needConversion ? data.data() : imagePixelData); | 4456 needConversion ? data.data() : imagePixelData); |
4433 } else if (functionID == TexSubImage2D) { | 4457 } else if (functionID == TexSubImage2D) { |
4434 contextGL()->TexSubImage2D(target, level, xoffset, yoffset, | 4458 contextGL()->TexSubImage2D(target, level, xoffset, yoffset, |
4435 adjustedSourceImageRect.width(), | 4459 adjustedSourceImageRect.width(), |
4436 adjustedSourceImageRect.height(), format, type, | 4460 adjustedSourceImageRect.height(), format, type, |
4437 needConversion ? data.data() : imagePixelData); | 4461 needConversion ? data.data() : imagePixelData); |
4438 } else { | 4462 } else { |
4439 DCHECK_EQ(functionID, TexSubImage3D); | 4463 // 3D functions. |
4440 contextGL()->TexSubImage3D( | 4464 GLint uploadHeight = adjustedSourceImageRect.height(); |
4441 target, level, xoffset, yoffset, zoffset, | 4465 if (unpackImageHeight) { |
4442 adjustedSourceImageRect.width(), adjustedSourceImageRect.height(), 1, | 4466 // GL_UNPACK_IMAGE_HEIGHT overrides the passed-in height. |
4443 format, type, needConversion ? data.data() : imagePixelData); | 4467 uploadHeight = unpackImageHeight; |
| 4468 } |
| 4469 if (functionID == TexImage3D) { |
| 4470 contextGL()->TexImage3D(target, level, internalformat, |
| 4471 adjustedSourceImageRect.width(), uploadHeight, |
| 4472 depth, 0, format, type, |
| 4473 needConversion ? data.data() : imagePixelData); |
| 4474 } else { |
| 4475 DCHECK_EQ(functionID, TexSubImage3D); |
| 4476 contextGL()->TexSubImage3D(target, level, xoffset, yoffset, zoffset, |
| 4477 adjustedSourceImageRect.width(), uploadHeight, |
| 4478 depth, format, type, |
| 4479 needConversion ? data.data() : imagePixelData); |
| 4480 } |
4444 } | 4481 } |
4445 restoreUnpackParameters(); | 4482 restoreUnpackParameters(); |
4446 } | 4483 } |
4447 | 4484 |
4448 bool WebGLRenderingContextBase::validateTexFunc( | 4485 bool WebGLRenderingContextBase::validateTexFunc( |
4449 const char* functionName, | 4486 const char* functionName, |
4450 TexImageFunctionType functionType, | 4487 TexImageFunctionType functionType, |
4451 TexFuncValidationSourceType sourceType, | 4488 TexFuncValidationSourceType sourceType, |
4452 GLenum target, | 4489 GLenum target, |
4453 GLint level, | 4490 GLint level, |
(...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4757 GLenum target, | 4794 GLenum target, |
4758 GLint level, | 4795 GLint level, |
4759 GLint internalformat, | 4796 GLint internalformat, |
4760 GLenum format, | 4797 GLenum format, |
4761 GLenum type, | 4798 GLenum type, |
4762 GLint xoffset, | 4799 GLint xoffset, |
4763 GLint yoffset, | 4800 GLint yoffset, |
4764 GLint zoffset, | 4801 GLint zoffset, |
4765 HTMLImageElement* image, | 4802 HTMLImageElement* image, |
4766 const IntRect& sourceImageRect, | 4803 const IntRect& sourceImageRect, |
| 4804 GLsizei depth, |
| 4805 GLint unpackImageHeight, |
4767 ExceptionState& exceptionState) { | 4806 ExceptionState& exceptionState) { |
4768 const char* funcName = getTexImageFunctionName(functionID); | 4807 const char* funcName = getTexImageFunctionName(functionID); |
4769 if (isContextLost()) | 4808 if (isContextLost()) |
4770 return; | 4809 return; |
4771 if (!validateHTMLImageElement(funcName, image, exceptionState)) | 4810 if (!validateHTMLImageElement(funcName, image, exceptionState)) |
4772 return; | 4811 return; |
4773 if (!validateTexImageBinding(funcName, functionID, target)) | 4812 if (!validateTexImageBinding(funcName, functionID, target)) |
4774 return; | 4813 return; |
4775 | 4814 |
4776 RefPtr<Image> imageForRender = image->cachedImage()->getImage(); | 4815 RefPtr<Image> imageForRender = image->cachedImage()->getImage(); |
4777 if (imageForRender && imageForRender->isSVGImage()) | 4816 if (imageForRender && imageForRender->isSVGImage()) |
4778 imageForRender = drawImageIntoBuffer( | 4817 imageForRender = drawImageIntoBuffer( |
4779 imageForRender.release(), image->width(), image->height(), funcName); | 4818 imageForRender.release(), image->width(), image->height(), funcName); |
4780 | 4819 |
4781 TexImageFunctionType functionType; | 4820 TexImageFunctionType functionType; |
4782 if (functionID == TexImage2D) | 4821 if (functionID == TexImage2D) |
4783 functionType = TexImage; | 4822 functionType = TexImage; |
4784 else | 4823 else |
4785 functionType = TexSubImage; | 4824 functionType = TexSubImage; |
4786 if (!imageForRender || | 4825 if (!imageForRender || |
4787 !validateTexFunc(funcName, functionType, SourceHTMLImageElement, target, | 4826 !validateTexFunc(funcName, functionType, SourceHTMLImageElement, target, |
4788 level, internalformat, imageForRender->width(), | 4827 level, internalformat, imageForRender->width(), |
4789 imageForRender->height(), 1, 0, format, type, xoffset, | 4828 imageForRender->height(), depth, 0, format, type, |
4790 yoffset, zoffset)) | 4829 xoffset, yoffset, zoffset)) |
4791 return; | 4830 return; |
4792 | 4831 |
4793 texImageImpl(functionID, target, level, internalformat, xoffset, yoffset, | 4832 texImageImpl(functionID, target, level, internalformat, xoffset, yoffset, |
4794 zoffset, format, type, imageForRender.get(), | 4833 zoffset, format, type, imageForRender.get(), |
4795 WebGLImageConversion::HtmlDomImage, m_unpackFlipY, | 4834 WebGLImageConversion::HtmlDomImage, m_unpackFlipY, |
4796 m_unpackPremultiplyAlpha, sourceImageRect); | 4835 m_unpackPremultiplyAlpha, sourceImageRect, depth, |
| 4836 unpackImageHeight); |
4797 } | 4837 } |
4798 | 4838 |
4799 void WebGLRenderingContextBase::texImage2D(GLenum target, | 4839 void WebGLRenderingContextBase::texImage2D(GLenum target, |
4800 GLint level, | 4840 GLint level, |
4801 GLint internalformat, | 4841 GLint internalformat, |
4802 GLenum format, | 4842 GLenum format, |
4803 GLenum type, | 4843 GLenum type, |
4804 HTMLImageElement* image, | 4844 HTMLImageElement* image, |
4805 ExceptionState& exceptionState) { | 4845 ExceptionState& exceptionState) { |
4806 texImageHelperHTMLImageElement(TexImage2D, target, level, internalformat, | 4846 texImageHelperHTMLImageElement(TexImage2D, target, level, internalformat, |
4807 format, type, 0, 0, 0, image, | 4847 format, type, 0, 0, 0, image, |
4808 sentinelEmptyRect(), exceptionState); | 4848 sentinelEmptyRect(), 1, 0, exceptionState); |
4809 } | 4849 } |
4810 | 4850 |
4811 bool WebGLRenderingContextBase::canUseTexImageByGPU( | 4851 bool WebGLRenderingContextBase::canUseTexImageByGPU( |
4812 TexImageFunctionID functionID, | 4852 TexImageFunctionID functionID, |
4813 GLint internalformat, | 4853 GLint internalformat, |
4814 GLenum type) { | 4854 GLenum type) { |
4815 if (functionID == TexImage2D && | 4855 if (functionID == TexImage2D && |
4816 (isFloatType(type) || isIntegerFormat(internalformat) || | 4856 (isFloatType(type) || isIntegerFormat(internalformat) || |
4817 isSRGBFormat(internalformat))) | 4857 isSRGBFormat(internalformat))) |
4818 return false; | 4858 return false; |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4966 // upgraded to handle more formats. | 5006 // upgraded to handle more formats. |
4967 if (!canvas->renderingContext() || | 5007 if (!canvas->renderingContext() || |
4968 !canvas->renderingContext()->isAccelerated() || | 5008 !canvas->renderingContext()->isAccelerated() || |
4969 !canUseTexImageByGPU(functionID, internalformat, type)) { | 5009 !canUseTexImageByGPU(functionID, internalformat, type)) { |
4970 // 2D canvas has only FrontBuffer. | 5010 // 2D canvas has only FrontBuffer. |
4971 texImageImpl(functionID, target, level, internalformat, xoffset, yoffset, | 5011 texImageImpl(functionID, target, level, internalformat, xoffset, yoffset, |
4972 zoffset, format, type, | 5012 zoffset, format, type, |
4973 canvas->copiedImage(FrontBuffer, PreferAcceleration).get(), | 5013 canvas->copiedImage(FrontBuffer, PreferAcceleration).get(), |
4974 WebGLImageConversion::HtmlDomCanvas, m_unpackFlipY, | 5014 WebGLImageConversion::HtmlDomCanvas, m_unpackFlipY, |
4975 m_unpackPremultiplyAlpha, | 5015 m_unpackPremultiplyAlpha, |
4976 IntRect(0, 0, canvas->width(), canvas->height())); | 5016 IntRect(0, 0, canvas->width(), canvas->height()), 1, 0); |
4977 return; | 5017 return; |
4978 } | 5018 } |
4979 | 5019 |
4980 if (functionID == TexImage2D) { | 5020 if (functionID == TexImage2D) { |
4981 texImage2DBase(target, level, internalformat, canvas->width(), | 5021 texImage2DBase(target, level, internalformat, canvas->width(), |
4982 canvas->height(), 0, format, type, 0); | 5022 canvas->height(), 0, format, type, 0); |
4983 texImageByGPU(TexImage2DByGPU, texture, target, level, internalformat, | 5023 texImageByGPU(TexImage2DByGPU, texture, target, level, internalformat, |
4984 type, 0, 0, 0, canvas); | 5024 type, 0, 0, 0, canvas); |
4985 } else { | 5025 } else { |
4986 texImageByGPU(TexSubImage2DByGPU, texture, target, level, GL_RGBA, type, | 5026 texImageByGPU(TexSubImage2DByGPU, texture, target, level, GL_RGBA, type, |
4987 xoffset, yoffset, 0, canvas); | 5027 xoffset, yoffset, 0, canvas); |
4988 } | 5028 } |
4989 } else { | 5029 } else { |
4990 DCHECK_EQ(functionID, TexSubImage3D); | 5030 DCHECK_EQ(functionID, TexSubImage3D); |
4991 // FIXME: Implement GPU-to-GPU copy path (crbug.com/586269). | 5031 // FIXME: Implement GPU-to-GPU copy path (crbug.com/586269). |
4992 texImageImpl(TexSubImage3D, target, level, 0, xoffset, yoffset, zoffset, | 5032 texImageImpl(TexSubImage3D, target, level, 0, xoffset, yoffset, zoffset, |
4993 format, type, | 5033 format, type, |
4994 canvas->copiedImage(FrontBuffer, PreferAcceleration).get(), | 5034 canvas->copiedImage(FrontBuffer, PreferAcceleration).get(), |
4995 WebGLImageConversion::HtmlDomCanvas, m_unpackFlipY, | 5035 WebGLImageConversion::HtmlDomCanvas, m_unpackFlipY, |
4996 m_unpackPremultiplyAlpha, | 5036 m_unpackPremultiplyAlpha, |
4997 IntRect(0, 0, canvas->width(), canvas->height())); | 5037 IntRect(0, 0, canvas->width(), canvas->height()), 1, 0); |
4998 } | 5038 } |
4999 } | 5039 } |
5000 | 5040 |
5001 void WebGLRenderingContextBase::texImage2D(GLenum target, | 5041 void WebGLRenderingContextBase::texImage2D(GLenum target, |
5002 GLint level, | 5042 GLint level, |
5003 GLint internalformat, | 5043 GLint internalformat, |
5004 GLenum format, | 5044 GLenum format, |
5005 GLenum type, | 5045 GLenum type, |
5006 HTMLCanvasElement* canvas, | 5046 HTMLCanvasElement* canvas, |
5007 ExceptionState& exceptionState) { | 5047 ExceptionState& exceptionState) { |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5098 } | 5138 } |
5099 } | 5139 } |
5100 | 5140 |
5101 RefPtr<Image> image = videoFrameToImage(video); | 5141 RefPtr<Image> image = videoFrameToImage(video); |
5102 if (!image) | 5142 if (!image) |
5103 return; | 5143 return; |
5104 texImageImpl(functionID, target, level, internalformat, xoffset, yoffset, | 5144 texImageImpl(functionID, target, level, internalformat, xoffset, yoffset, |
5105 zoffset, format, type, image.get(), | 5145 zoffset, format, type, image.get(), |
5106 WebGLImageConversion::HtmlDomVideo, m_unpackFlipY, | 5146 WebGLImageConversion::HtmlDomVideo, m_unpackFlipY, |
5107 m_unpackPremultiplyAlpha, | 5147 m_unpackPremultiplyAlpha, |
5108 IntRect(0, 0, video->videoWidth(), video->videoHeight())); | 5148 IntRect(0, 0, video->videoWidth(), video->videoHeight()), 1, 0); |
5109 } | 5149 } |
5110 | 5150 |
5111 void WebGLRenderingContextBase::texImageBitmapByGPU(ImageBitmap* bitmap, | 5151 void WebGLRenderingContextBase::texImageBitmapByGPU(ImageBitmap* bitmap, |
5112 GLuint targetTexture, | 5152 GLuint targetTexture, |
5113 GLenum targetInternalformat, | 5153 GLenum targetInternalformat, |
5114 GLenum targetType, | 5154 GLenum targetType, |
5115 GLint targetLevel, | 5155 GLint targetLevel, |
5116 bool flipY) { | 5156 bool flipY) { |
5117 bitmap->bitmapImage()->copyToTexture(drawingBuffer()->contextProvider(), | 5157 bitmap->bitmapImage()->copyToTexture(drawingBuffer()->contextProvider(), |
5118 targetTexture, targetInternalformat, | 5158 targetTexture, targetInternalformat, |
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5350 void WebGLRenderingContextBase::texSubImage2D(GLenum target, | 5390 void WebGLRenderingContextBase::texSubImage2D(GLenum target, |
5351 GLint level, | 5391 GLint level, |
5352 GLint xoffset, | 5392 GLint xoffset, |
5353 GLint yoffset, | 5393 GLint yoffset, |
5354 GLenum format, | 5394 GLenum format, |
5355 GLenum type, | 5395 GLenum type, |
5356 HTMLImageElement* image, | 5396 HTMLImageElement* image, |
5357 ExceptionState& exceptionState) { | 5397 ExceptionState& exceptionState) { |
5358 texImageHelperHTMLImageElement(TexSubImage2D, target, level, 0, format, type, | 5398 texImageHelperHTMLImageElement(TexSubImage2D, target, level, 0, format, type, |
5359 xoffset, yoffset, 0, image, | 5399 xoffset, yoffset, 0, image, |
5360 sentinelEmptyRect(), exceptionState); | 5400 sentinelEmptyRect(), 1, 0, exceptionState); |
5361 } | 5401 } |
5362 | 5402 |
5363 void WebGLRenderingContextBase::texSubImage2D(GLenum target, | 5403 void WebGLRenderingContextBase::texSubImage2D(GLenum target, |
5364 GLint level, | 5404 GLint level, |
5365 GLint xoffset, | 5405 GLint xoffset, |
5366 GLint yoffset, | 5406 GLint yoffset, |
5367 GLenum format, | 5407 GLenum format, |
5368 GLenum type, | 5408 GLenum type, |
5369 HTMLCanvasElement* canvas, | 5409 HTMLCanvasElement* canvas, |
5370 ExceptionState& exceptionState) { | 5410 ExceptionState& exceptionState) { |
(...skipping 2248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7619 | 7659 |
7620 void WebGLRenderingContextBase::getHTMLOrOffscreenCanvas( | 7660 void WebGLRenderingContextBase::getHTMLOrOffscreenCanvas( |
7621 HTMLCanvasElementOrOffscreenCanvas& result) const { | 7661 HTMLCanvasElementOrOffscreenCanvas& result) const { |
7622 if (canvas()) | 7662 if (canvas()) |
7623 result.setHTMLCanvasElement(canvas()); | 7663 result.setHTMLCanvasElement(canvas()); |
7624 else | 7664 else |
7625 result.setOffscreenCanvas(getOffscreenCanvas()); | 7665 result.setOffscreenCanvas(getOffscreenCanvas()); |
7626 } | 7666 } |
7627 | 7667 |
7628 } // namespace blink | 7668 } // namespace blink |
OLD | NEW |