1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/angle/src/libGLESv2/renderer/Image11.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,457 @@ 1.4 +#include "precompiled.h" 1.5 +// 1.6 +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. 1.7 +// Use of this source code is governed by a BSD-style license that can be 1.8 +// found in the LICENSE file. 1.9 +// 1.10 + 1.11 +// Image11.h: Implements the rx::Image11 class, which acts as the interface to 1.12 +// the actual underlying resources of a Texture 1.13 + 1.14 +#include "libGLESv2/renderer/Renderer11.h" 1.15 +#include "libGLESv2/renderer/Image11.h" 1.16 +#include "libGLESv2/renderer/TextureStorage11.h" 1.17 +#include "libGLESv2/Framebuffer.h" 1.18 +#include "libGLESv2/Renderbuffer.h" 1.19 + 1.20 +#include "libGLESv2/main.h" 1.21 +#include "libGLESv2/utilities.h" 1.22 +#include "libGLESv2/renderer/renderer11_utils.h" 1.23 +#include "libGLESv2/renderer/generatemip.h" 1.24 + 1.25 +namespace rx 1.26 +{ 1.27 + 1.28 +Image11::Image11() 1.29 +{ 1.30 + mStagingTexture = NULL; 1.31 + mRenderer = NULL; 1.32 + mDXGIFormat = DXGI_FORMAT_UNKNOWN; 1.33 +} 1.34 + 1.35 +Image11::~Image11() 1.36 +{ 1.37 + if (mStagingTexture) 1.38 + { 1.39 + mStagingTexture->Release(); 1.40 + } 1.41 +} 1.42 + 1.43 +Image11 *Image11::makeImage11(Image *img) 1.44 +{ 1.45 + ASSERT(HAS_DYNAMIC_TYPE(rx::Image11*, img)); 1.46 + return static_cast<rx::Image11*>(img); 1.47 +} 1.48 + 1.49 +void Image11::generateMipmap(Image11 *dest, Image11 *src) 1.50 +{ 1.51 + ASSERT(src->getDXGIFormat() == dest->getDXGIFormat()); 1.52 + ASSERT(src->getWidth() == 1 || src->getWidth() / 2 == dest->getWidth()); 1.53 + ASSERT(src->getHeight() == 1 || src->getHeight() / 2 == dest->getHeight()); 1.54 + 1.55 + D3D11_MAPPED_SUBRESOURCE destMapped, srcMapped; 1.56 + dest->map(&destMapped); 1.57 + src->map(&srcMapped); 1.58 + 1.59 + const unsigned char *sourceData = reinterpret_cast<const unsigned char*>(srcMapped.pData); 1.60 + unsigned char *destData = reinterpret_cast<unsigned char*>(destMapped.pData); 1.61 + 1.62 + if (sourceData && destData) 1.63 + { 1.64 + switch (src->getDXGIFormat()) 1.65 + { 1.66 + case DXGI_FORMAT_R8G8B8A8_UNORM: 1.67 + case DXGI_FORMAT_B8G8R8A8_UNORM: 1.68 + GenerateMip<R8G8B8A8>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); 1.69 + break; 1.70 + case DXGI_FORMAT_A8_UNORM: 1.71 + GenerateMip<A8>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); 1.72 + break; 1.73 + case DXGI_FORMAT_R8_UNORM: 1.74 + GenerateMip<R8>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); 1.75 + break; 1.76 + case DXGI_FORMAT_R32G32B32A32_FLOAT: 1.77 + GenerateMip<A32B32G32R32F>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); 1.78 + break; 1.79 + case DXGI_FORMAT_R32G32B32_FLOAT: 1.80 + GenerateMip<R32G32B32F>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); 1.81 + break; 1.82 + case DXGI_FORMAT_R16G16B16A16_FLOAT: 1.83 + GenerateMip<A16B16G16R16F>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); 1.84 + break; 1.85 + case DXGI_FORMAT_R8G8_UNORM: 1.86 + GenerateMip<R8G8>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); 1.87 + break; 1.88 + case DXGI_FORMAT_R16_FLOAT: 1.89 + GenerateMip<R16F>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); 1.90 + break; 1.91 + case DXGI_FORMAT_R16G16_FLOAT: 1.92 + GenerateMip<R16G16F>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); 1.93 + break; 1.94 + case DXGI_FORMAT_R32_FLOAT: 1.95 + GenerateMip<R32F>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); 1.96 + break; 1.97 + case DXGI_FORMAT_R32G32_FLOAT: 1.98 + GenerateMip<R32G32F>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); 1.99 + break; 1.100 + default: 1.101 + UNREACHABLE(); 1.102 + break; 1.103 + } 1.104 + 1.105 + dest->unmap(); 1.106 + src->unmap(); 1.107 + } 1.108 + 1.109 + dest->markDirty(); 1.110 +} 1.111 + 1.112 +bool Image11::isDirty() const 1.113 +{ 1.114 + return (mStagingTexture && mDirty); 1.115 +} 1.116 + 1.117 +bool Image11::updateSurface(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) 1.118 +{ 1.119 + TextureStorage11_2D *storage11 = TextureStorage11_2D::makeTextureStorage11_2D(storage->getStorageInstance()); 1.120 + return storage11->updateSubresourceLevel(getStagingTexture(), getStagingSubresource(), level, 0, xoffset, yoffset, width, height); 1.121 +} 1.122 + 1.123 +bool Image11::updateSurface(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) 1.124 +{ 1.125 + TextureStorage11_Cube *storage11 = TextureStorage11_Cube::makeTextureStorage11_Cube(storage->getStorageInstance()); 1.126 + return storage11->updateSubresourceLevel(getStagingTexture(), getStagingSubresource(), level, face, xoffset, yoffset, width, height); 1.127 +} 1.128 + 1.129 +bool Image11::redefine(Renderer *renderer, GLint internalformat, GLsizei width, GLsizei height, bool forceRelease) 1.130 +{ 1.131 + if (mWidth != width || 1.132 + mHeight != height || 1.133 + mInternalFormat != internalformat || 1.134 + forceRelease) 1.135 + { 1.136 + mRenderer = Renderer11::makeRenderer11(renderer); 1.137 + 1.138 + mWidth = width; 1.139 + mHeight = height; 1.140 + mInternalFormat = internalformat; 1.141 + // compute the d3d format that will be used 1.142 + mDXGIFormat = gl_d3d11::ConvertTextureFormat(internalformat); 1.143 + mActualFormat = d3d11_gl::ConvertTextureInternalFormat(mDXGIFormat); 1.144 + 1.145 + if (mStagingTexture) 1.146 + { 1.147 + mStagingTexture->Release(); 1.148 + mStagingTexture = NULL; 1.149 + } 1.150 + 1.151 + return true; 1.152 + } 1.153 + 1.154 + return false; 1.155 +} 1.156 + 1.157 +bool Image11::isRenderableFormat() const 1.158 +{ 1.159 + return TextureStorage11::IsTextureFormatRenderable(mDXGIFormat); 1.160 +} 1.161 + 1.162 +DXGI_FORMAT Image11::getDXGIFormat() const 1.163 +{ 1.164 + // this should only happen if the image hasn't been redefined first 1.165 + // which would be a bug by the caller 1.166 + ASSERT(mDXGIFormat != DXGI_FORMAT_UNKNOWN); 1.167 + 1.168 + return mDXGIFormat; 1.169 +} 1.170 + 1.171 +// Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input 1.172 +// into the target pixel rectangle. 1.173 +void Image11::loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, 1.174 + GLint unpackAlignment, const void *input) 1.175 +{ 1.176 + D3D11_MAPPED_SUBRESOURCE mappedImage; 1.177 + HRESULT result = map(&mappedImage); 1.178 + if (FAILED(result)) 1.179 + { 1.180 + ERR("Could not map image for loading."); 1.181 + return; 1.182 + } 1.183 + 1.184 + GLsizei inputPitch = gl::ComputePitch(width, mInternalFormat, unpackAlignment); 1.185 + size_t pixelSize = d3d11::ComputePixelSizeBits(mDXGIFormat) / 8; 1.186 + void* offsetMappedData = (void*)((BYTE *)mappedImage.pData + (yoffset * mappedImage.RowPitch + xoffset * pixelSize)); 1.187 + 1.188 + switch (mInternalFormat) 1.189 + { 1.190 + case GL_ALPHA8_EXT: 1.191 + loadAlphaDataToNative(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); 1.192 + break; 1.193 + case GL_LUMINANCE8_EXT: 1.194 + loadLuminanceDataToNativeOrBGRA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData, false); 1.195 + break; 1.196 + case GL_ALPHA32F_EXT: 1.197 + loadAlphaFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); 1.198 + break; 1.199 + case GL_LUMINANCE32F_EXT: 1.200 + loadLuminanceFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); 1.201 + break; 1.202 + case GL_ALPHA16F_EXT: 1.203 + loadAlphaHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); 1.204 + break; 1.205 + case GL_LUMINANCE16F_EXT: 1.206 + loadLuminanceHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); 1.207 + break; 1.208 + case GL_LUMINANCE8_ALPHA8_EXT: 1.209 + loadLuminanceAlphaDataToNativeOrBGRA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData, false); 1.210 + break; 1.211 + case GL_LUMINANCE_ALPHA32F_EXT: 1.212 + loadLuminanceAlphaFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); 1.213 + break; 1.214 + case GL_LUMINANCE_ALPHA16F_EXT: 1.215 + loadLuminanceAlphaHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); 1.216 + break; 1.217 + case GL_RGB8_OES: 1.218 + loadRGBUByteDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); 1.219 + break; 1.220 + case GL_RGB565: 1.221 + loadRGB565DataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); 1.222 + break; 1.223 + case GL_RGBA8_OES: 1.224 + loadRGBAUByteDataToNative(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); 1.225 + break; 1.226 + case GL_RGBA4: 1.227 + loadRGBA4444DataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); 1.228 + break; 1.229 + case GL_RGB5_A1: 1.230 + loadRGBA5551DataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); 1.231 + break; 1.232 + case GL_BGRA8_EXT: 1.233 + loadBGRADataToBGRA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); 1.234 + break; 1.235 + case GL_RGB32F_EXT: 1.236 + loadRGBFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); 1.237 + break; 1.238 + case GL_RGB16F_EXT: 1.239 + loadRGBHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); 1.240 + break; 1.241 + case GL_RGBA32F_EXT: 1.242 + loadRGBAFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); 1.243 + break; 1.244 + case GL_RGBA16F_EXT: 1.245 + loadRGBAHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); 1.246 + break; 1.247 + default: UNREACHABLE(); 1.248 + } 1.249 + 1.250 + unmap(); 1.251 +} 1.252 + 1.253 +void Image11::loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, 1.254 + const void *input) 1.255 +{ 1.256 + ASSERT(xoffset % 4 == 0); 1.257 + ASSERT(yoffset % 4 == 0); 1.258 + 1.259 + D3D11_MAPPED_SUBRESOURCE mappedImage; 1.260 + HRESULT result = map(&mappedImage); 1.261 + if (FAILED(result)) 1.262 + { 1.263 + ERR("Could not map image for loading."); 1.264 + return; 1.265 + } 1.266 + 1.267 + // Size computation assumes a 4x4 block compressed texture format 1.268 + size_t blockSize = d3d11::ComputeBlockSizeBits(mDXGIFormat) / 8; 1.269 + void* offsetMappedData = (void*)((BYTE *)mappedImage.pData + ((yoffset / 4) * mappedImage.RowPitch + (xoffset / 4) * blockSize)); 1.270 + 1.271 + GLsizei inputSize = gl::ComputeCompressedSize(width, height, mInternalFormat); 1.272 + GLsizei inputPitch = gl::ComputeCompressedPitch(width, mInternalFormat); 1.273 + int rows = inputSize / inputPitch; 1.274 + for (int i = 0; i < rows; ++i) 1.275 + { 1.276 + memcpy((void*)((BYTE*)offsetMappedData + i * mappedImage.RowPitch), (void*)((BYTE*)input + i * inputPitch), inputPitch); 1.277 + } 1.278 + 1.279 + unmap(); 1.280 +} 1.281 + 1.282 +void Image11::copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) 1.283 +{ 1.284 + gl::Renderbuffer *colorbuffer = source->getReadColorbuffer(); 1.285 + 1.286 + if (colorbuffer && colorbuffer->getActualFormat() == (GLuint)mActualFormat) 1.287 + { 1.288 + // No conversion needed-- use copyback fastpath 1.289 + ID3D11Texture2D *colorBufferTexture = NULL; 1.290 + unsigned int subresourceIndex = 0; 1.291 + 1.292 + if (mRenderer->getRenderTargetResource(colorbuffer, &subresourceIndex, &colorBufferTexture)) 1.293 + { 1.294 + D3D11_TEXTURE2D_DESC textureDesc; 1.295 + colorBufferTexture->GetDesc(&textureDesc); 1.296 + 1.297 + ID3D11Device *device = mRenderer->getDevice(); 1.298 + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); 1.299 + 1.300 + ID3D11Texture2D* srcTex = NULL; 1.301 + if (textureDesc.SampleDesc.Count > 1) 1.302 + { 1.303 + D3D11_TEXTURE2D_DESC resolveDesc; 1.304 + resolveDesc.Width = textureDesc.Width; 1.305 + resolveDesc.Height = textureDesc.Height; 1.306 + resolveDesc.MipLevels = 1; 1.307 + resolveDesc.ArraySize = 1; 1.308 + resolveDesc.Format = textureDesc.Format; 1.309 + resolveDesc.SampleDesc.Count = 1; 1.310 + resolveDesc.SampleDesc.Quality = 0; 1.311 + resolveDesc.Usage = D3D11_USAGE_DEFAULT; 1.312 + resolveDesc.BindFlags = 0; 1.313 + resolveDesc.CPUAccessFlags = 0; 1.314 + resolveDesc.MiscFlags = 0; 1.315 + 1.316 + HRESULT result = device->CreateTexture2D(&resolveDesc, NULL, &srcTex); 1.317 + if (FAILED(result)) 1.318 + { 1.319 + ERR("Failed to create resolve texture for Image11::copy, HRESULT: 0x%X.", result); 1.320 + return; 1.321 + } 1.322 + 1.323 + deviceContext->ResolveSubresource(srcTex, 0, colorBufferTexture, subresourceIndex, textureDesc.Format); 1.324 + subresourceIndex = 0; 1.325 + } 1.326 + else 1.327 + { 1.328 + srcTex = colorBufferTexture; 1.329 + srcTex->AddRef(); 1.330 + } 1.331 + 1.332 + D3D11_BOX srcBox; 1.333 + srcBox.left = x; 1.334 + srcBox.right = x + width; 1.335 + srcBox.top = y; 1.336 + srcBox.bottom = y + height; 1.337 + srcBox.front = 0; 1.338 + srcBox.back = 1; 1.339 + 1.340 + deviceContext->CopySubresourceRegion(mStagingTexture, 0, xoffset, yoffset, 0, srcTex, subresourceIndex, &srcBox); 1.341 + 1.342 + srcTex->Release(); 1.343 + colorBufferTexture->Release(); 1.344 + } 1.345 + } 1.346 + else 1.347 + { 1.348 + // This format requires conversion, so we must copy the texture to staging and manually convert via readPixels 1.349 + D3D11_MAPPED_SUBRESOURCE mappedImage; 1.350 + HRESULT result = map(&mappedImage); 1.351 + 1.352 + // determine the offset coordinate into the destination buffer 1.353 + GLsizei rowOffset = gl::ComputePixelSize(mActualFormat) * xoffset; 1.354 + void *dataOffset = static_cast<unsigned char*>(mappedImage.pData) + mappedImage.RowPitch * yoffset + rowOffset; 1.355 + 1.356 + mRenderer->readPixels(source, x, y, width, height, gl::ExtractFormat(mInternalFormat), 1.357 + gl::ExtractType(mInternalFormat), mappedImage.RowPitch, false, 4, dataOffset); 1.358 + 1.359 + unmap(); 1.360 + } 1.361 +} 1.362 + 1.363 +ID3D11Texture2D *Image11::getStagingTexture() 1.364 +{ 1.365 + createStagingTexture(); 1.366 + 1.367 + return mStagingTexture; 1.368 +} 1.369 + 1.370 +unsigned int Image11::getStagingSubresource() 1.371 +{ 1.372 + createStagingTexture(); 1.373 + 1.374 + return mStagingSubresource; 1.375 +} 1.376 + 1.377 +void Image11::createStagingTexture() 1.378 +{ 1.379 + if (mStagingTexture) 1.380 + { 1.381 + return; 1.382 + } 1.383 + 1.384 + ID3D11Texture2D *newTexture = NULL; 1.385 + int lodOffset = 1; 1.386 + const DXGI_FORMAT dxgiFormat = getDXGIFormat(); 1.387 + ASSERT(!d3d11::IsDepthStencilFormat(dxgiFormat)); // We should never get here for depth textures 1.388 + 1.389 + if (mWidth != 0 && mHeight != 0) 1.390 + { 1.391 + GLsizei width = mWidth; 1.392 + GLsizei height = mHeight; 1.393 + 1.394 + // adjust size if needed for compressed textures 1.395 + gl::MakeValidSize(false, d3d11::IsCompressed(dxgiFormat), &width, &height, &lodOffset); 1.396 + ID3D11Device *device = mRenderer->getDevice(); 1.397 + 1.398 + D3D11_TEXTURE2D_DESC desc; 1.399 + desc.Width = width; 1.400 + desc.Height = height; 1.401 + desc.MipLevels = lodOffset + 1; 1.402 + desc.ArraySize = 1; 1.403 + desc.Format = dxgiFormat; 1.404 + desc.SampleDesc.Count = 1; 1.405 + desc.SampleDesc.Quality = 0; 1.406 + desc.Usage = D3D11_USAGE_STAGING; 1.407 + desc.BindFlags = 0; 1.408 + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; 1.409 + desc.MiscFlags = 0; 1.410 + 1.411 + HRESULT result = device->CreateTexture2D(&desc, NULL, &newTexture); 1.412 + 1.413 + if (FAILED(result)) 1.414 + { 1.415 + ASSERT(result == E_OUTOFMEMORY); 1.416 + ERR("Creating image failed."); 1.417 + return gl::error(GL_OUT_OF_MEMORY); 1.418 + } 1.419 + } 1.420 + 1.421 + mStagingTexture = newTexture; 1.422 + mStagingSubresource = D3D11CalcSubresource(lodOffset, 0, lodOffset + 1); 1.423 + mDirty = false; 1.424 +} 1.425 + 1.426 +HRESULT Image11::map(D3D11_MAPPED_SUBRESOURCE *map) 1.427 +{ 1.428 + createStagingTexture(); 1.429 + 1.430 + HRESULT result = E_FAIL; 1.431 + 1.432 + if (mStagingTexture) 1.433 + { 1.434 + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); 1.435 + result = deviceContext->Map(mStagingTexture, mStagingSubresource, D3D11_MAP_WRITE, 0, map); 1.436 + 1.437 + // this can fail if the device is removed (from TDR) 1.438 + if (d3d11::isDeviceLostError(result)) 1.439 + { 1.440 + mRenderer->notifyDeviceLost(); 1.441 + } 1.442 + else if (SUCCEEDED(result)) 1.443 + { 1.444 + mDirty = true; 1.445 + } 1.446 + } 1.447 + 1.448 + return result; 1.449 +} 1.450 + 1.451 +void Image11::unmap() 1.452 +{ 1.453 + if (mStagingTexture) 1.454 + { 1.455 + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); 1.456 + deviceContext->Unmap(mStagingTexture, mStagingSubresource); 1.457 + } 1.458 +} 1.459 + 1.460 +}