Creates Image11 class
TRAC #22208
Author: Shannon Woods
Signed-off-by: Geoff Lang
Signed-off-by: Daniel Koch
git-svn-id: https://angleproject.googlecode.com/svn/branches/dx11proto@1592 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/libGLESv2/renderer/Image11.cpp b/src/libGLESv2/renderer/Image11.cpp
new file mode 100644
index 0000000..68b7ba6
--- /dev/null
+++ b/src/libGLESv2/renderer/Image11.cpp
@@ -0,0 +1,289 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Image11.h: Implements the rx::Image11 class, which acts as the interface to
+// the actual underlying resources of a Texture
+
+#include "libGLESv2/renderer/Renderer11.h"
+#include "libGLESv2/renderer/Image11.h"
+
+#include "libGLESv2/main.h"
+#include "libGLESv2/mathutil.h"
+#include "libGLESv2/renderer/renderer11_utils.h"
+
+namespace rx
+{
+
+Image11::Image11()
+{
+ mStagingTexture = NULL;
+ mRenderer = NULL;
+ mDXGIFormat = DXGI_FORMAT_UNKNOWN;
+}
+
+Image11::~Image11()
+{
+ if (mStagingTexture)
+ {
+ mStagingTexture->Release();
+ }
+}
+
+Image11 *Image11::makeImage11(Image *img)
+{
+ ASSERT(dynamic_cast<rx::Image11*>(img) != NULL);
+ return static_cast<rx::Image11*>(img);
+}
+
+bool Image11::isDirty() const
+{
+ return (mStagingTexture && mDirty);
+}
+
+bool Image11::updateSurface(TextureStorage2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
+{
+ // TODO - relies on TextureStorage11 implementation
+ UNIMPLEMENTED();
+ return false;
+}
+
+bool Image11::updateSurface(TextureStorageCubeMap *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
+{
+ // TODO - relies on TextureStorage11 implementation
+ UNIMPLEMENTED();
+ return false;
+}
+
+bool Image11::redefine(Renderer *renderer, GLint internalformat, GLsizei width, GLsizei height, bool forceRelease)
+{
+ if (mWidth != width ||
+ mHeight != height ||
+ mInternalFormat != internalformat ||
+ forceRelease)
+ {
+ mRenderer = Renderer11::makeRenderer11(renderer);
+
+ mWidth = width;
+ mHeight = height;
+ mInternalFormat = internalformat;
+ // compute the d3d format that will be used
+ mDXGIFormat = gl_d3d11::ConvertTextureFormat(internalformat);
+ mActualFormat = d3d11_gl::ConvertTextureInternalFormat(mDXGIFormat);
+
+ if (mStagingTexture)
+ {
+ mStagingTexture->Release();
+ mStagingTexture = NULL;
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+bool Image11::isRenderableFormat() const
+{
+ // TODO - relies on TextureStorage11 implementation
+ UNIMPLEMENTED();
+ return false;
+}
+
+DXGI_FORMAT Image11::getDXGIFormat() const
+{
+ // this should only happen if the image hasn't been redefined first
+ // which would be a bug by the caller
+ ASSERT(mDXGIFormat != DXGI_FORMAT_UNKNOWN);
+
+ return mDXGIFormat;
+}
+
+// Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input
+// into the target pixel rectangle.
+void Image11::loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ GLint unpackAlignment, const void *input)
+{
+ D3D11_MAPPED_SUBRESOURCE mappedImage;
+ HRESULT result = map(&mappedImage);
+ if (FAILED(result))
+ {
+ ERR("Could not map image for loading.");
+ return;
+ }
+
+ GLsizei inputPitch = gl::ComputePitch(width, mInternalFormat, unpackAlignment);
+ size_t pixelSize = d3d11::ComputePixelSizeBits(mDXGIFormat) / 8;
+ void* offsetMappedData = (void*)((BYTE *)mappedImage.pData + (yoffset * mappedImage.RowPitch + xoffset * pixelSize));
+
+ switch (mInternalFormat)
+ {
+ case GL_ALPHA8_EXT:
+ UNIMPLEMENTED(); // TODO - new function for D3D11-supported formats
+ break;
+ case GL_LUMINANCE8_EXT:
+ loadLuminanceData(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData, false);
+ break;
+ case GL_ALPHA32F_EXT:
+ loadAlphaFloatData(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
+ break;
+ case GL_LUMINANCE32F_EXT:
+ UNIMPLEMENTED(); // TODO - new function for D3D11-supported formats
+ break;
+ case GL_ALPHA16F_EXT:
+ loadAlphaHalfFloatData(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
+ break;
+ case GL_LUMINANCE16F_EXT:
+ loadLuminanceHalfFloatData(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
+ break;
+ case GL_LUMINANCE8_ALPHA8_EXT:
+ loadLuminanceAlphaData(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData, false);
+ break;
+ case GL_LUMINANCE_ALPHA32F_EXT:
+ loadLuminanceAlphaFloatData(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
+ break;
+ case GL_LUMINANCE_ALPHA16F_EXT:
+ loadLuminanceAlphaHalfFloatData(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
+ break;
+ case GL_RGB8_OES:
+ UNIMPLEMENTED(); // TODO - new function for D3D11-supported formats
+ break;
+ case GL_RGB565:
+ UNIMPLEMENTED(); // TODO - new function for D3D11-supported formats
+ break;
+ case GL_RGBA8_OES:
+ UNIMPLEMENTED(); // TODO - new function for D3D11-supported formats
+ break;
+ case GL_RGBA4:
+ UNIMPLEMENTED(); // TODO - new function for D3D11-supported formats
+ break;
+ case GL_RGB5_A1:
+ UNIMPLEMENTED(); // TODO - new function for D3D11-supported formats
+ break;
+ case GL_BGRA8_EXT:
+ loadBGRAData(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
+ break;
+ case GL_RGB32F_EXT:
+ UNIMPLEMENTED(); // TODO - new function for D3D11-supported formats
+ break;
+ case GL_RGB16F_EXT:
+ loadRGBHalfFloatData(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
+ break;
+ case GL_RGBA32F_EXT:
+ loadRGBAFloatData(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
+ break;
+ case GL_RGBA16F_EXT:
+ loadRGBAHalfFloatData(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
+ break;
+ default: UNREACHABLE();
+ }
+
+ unmap();
+}
+
+void Image11::loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ const void *input)
+{
+ ASSERT(xoffset % 4 == 0);
+ ASSERT(yoffset % 4 == 0);
+
+ D3D11_MAPPED_SUBRESOURCE mappedImage;
+ HRESULT result = map(&mappedImage);
+ if (FAILED(result))
+ {
+ ERR("Could not map image for loading.");
+ return;
+ }
+
+ // Size computation assumes a 4x4 block compressed texture format
+ size_t blockSize = d3d11::ComputeBlockSizeBits(mDXGIFormat) / 8;
+ void* offsetMappedData = (void*)((BYTE *)mappedImage.pData + ((yoffset / 4) * mappedImage.RowPitch + (xoffset / 4) * blockSize));
+
+ GLsizei inputSize = gl::ComputeCompressedSize(width, height, mInternalFormat);
+ GLsizei inputPitch = gl::ComputeCompressedPitch(width, mInternalFormat);
+ int rows = inputSize / inputPitch;
+ for (int i = 0; i < rows; ++i)
+ {
+ memcpy((void*)((BYTE*)offsetMappedData + i * mappedImage.RowPitch), (void*)((BYTE*)input + i * inputPitch), inputPitch);
+ }
+
+ unmap();
+}
+
+void Image11::copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source)
+{
+ // TODO
+ UNIMPLEMENTED();
+}
+
+void Image11::createStagingTexture()
+{
+ if (mStagingTexture)
+ {
+ return;
+ }
+
+ ID3D11Texture2D *newTexture = NULL;
+ const DXGI_FORMAT dxgiFormat = getDXGIFormat();
+ ASSERT(dxgiFormat != DXGI_FORMAT_D24_UNORM_S8_UINT); // We should never get here for depth textures
+
+ if (mWidth != 0 && mHeight != 0)
+ {
+ ID3D11Device *device = mRenderer->getDevice();
+
+ D3D11_TEXTURE2D_DESC desc;
+ desc.Width = mWidth;
+ desc.Height = mHeight;
+ desc.MipLevels = desc.ArraySize = 1;
+ desc.Format = dxgiFormat;
+ desc.SampleDesc.Count = 1;
+ desc.SampleDesc.Quality = 0;
+ desc.Usage = D3D11_USAGE_STAGING;
+ desc.BindFlags = 0;
+ desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+ desc.MiscFlags = 0;
+
+ HRESULT result = device->CreateTexture2D(&desc, NULL, &newTexture);
+
+ if (FAILED(result))
+ {
+ ASSERT(result == E_OUTOFMEMORY);
+ ERR("Creating image failed.");
+ return error(GL_OUT_OF_MEMORY);
+ }
+ }
+
+ mStagingTexture = newTexture;
+ mDirty = false;
+}
+
+HRESULT Image11::map(D3D11_MAPPED_SUBRESOURCE *map)
+{
+ createStagingTexture();
+
+ HRESULT result = D3DERR_INVALIDCALL;
+
+ if (mStagingTexture)
+ {
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+ result = deviceContext->Map(mStagingTexture, 0, D3D11_MAP_WRITE, 0, map);
+ ASSERT(SUCCEEDED(result));
+
+ mDirty = true;
+ }
+
+ return result;
+}
+
+void Image11::unmap()
+{
+ if (mStagingTexture)
+ {
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+ deviceContext->Unmap(mStagingTexture, 0);
+ }
+}
+
+}