blob: e0cfe936ba0a021c8de228ce98a36ac72d840ef3 [file] [log] [blame]
daniel@transgaming.coma8aac672012-12-20 21:08:00 +00001//
2// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// Image11.h: Implements the rx::Image11 class, which acts as the interface to
8// the actual underlying resources of a Texture
9
10#include "libGLESv2/renderer/Renderer11.h"
11#include "libGLESv2/renderer/Image11.h"
12
13#include "libGLESv2/main.h"
14#include "libGLESv2/mathutil.h"
15#include "libGLESv2/renderer/renderer11_utils.h"
16
17namespace rx
18{
19
20Image11::Image11()
21{
22 mStagingTexture = NULL;
23 mRenderer = NULL;
24 mDXGIFormat = DXGI_FORMAT_UNKNOWN;
25}
26
27Image11::~Image11()
28{
29 if (mStagingTexture)
30 {
31 mStagingTexture->Release();
32 }
33}
34
35Image11 *Image11::makeImage11(Image *img)
36{
37 ASSERT(dynamic_cast<rx::Image11*>(img) != NULL);
38 return static_cast<rx::Image11*>(img);
39}
40
41bool Image11::isDirty() const
42{
43 return (mStagingTexture && mDirty);
44}
45
daniel@transgaming.com87705f82012-12-20 21:10:45 +000046bool Image11::updateSurface(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
daniel@transgaming.coma8aac672012-12-20 21:08:00 +000047{
48 // TODO - relies on TextureStorage11 implementation
49 UNIMPLEMENTED();
50 return false;
51}
52
daniel@transgaming.com87705f82012-12-20 21:10:45 +000053bool Image11::updateSurface(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
daniel@transgaming.coma8aac672012-12-20 21:08:00 +000054{
55 // TODO - relies on TextureStorage11 implementation
56 UNIMPLEMENTED();
57 return false;
58}
59
60bool Image11::redefine(Renderer *renderer, GLint internalformat, GLsizei width, GLsizei height, bool forceRelease)
61{
62 if (mWidth != width ||
63 mHeight != height ||
64 mInternalFormat != internalformat ||
65 forceRelease)
66 {
67 mRenderer = Renderer11::makeRenderer11(renderer);
68
69 mWidth = width;
70 mHeight = height;
71 mInternalFormat = internalformat;
72 // compute the d3d format that will be used
73 mDXGIFormat = gl_d3d11::ConvertTextureFormat(internalformat);
74 mActualFormat = d3d11_gl::ConvertTextureInternalFormat(mDXGIFormat);
75
76 if (mStagingTexture)
77 {
78 mStagingTexture->Release();
79 mStagingTexture = NULL;
80 }
81
82 return true;
83 }
84
85 return false;
86}
87
88bool Image11::isRenderableFormat() const
89{
90 // TODO - relies on TextureStorage11 implementation
91 UNIMPLEMENTED();
92 return false;
93}
94
95DXGI_FORMAT Image11::getDXGIFormat() const
96{
97 // this should only happen if the image hasn't been redefined first
98 // which would be a bug by the caller
99 ASSERT(mDXGIFormat != DXGI_FORMAT_UNKNOWN);
100
101 return mDXGIFormat;
102}
103
104// Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input
105// into the target pixel rectangle.
106void Image11::loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
107 GLint unpackAlignment, const void *input)
108{
109 D3D11_MAPPED_SUBRESOURCE mappedImage;
110 HRESULT result = map(&mappedImage);
111 if (FAILED(result))
112 {
113 ERR("Could not map image for loading.");
114 return;
115 }
116
117 GLsizei inputPitch = gl::ComputePitch(width, mInternalFormat, unpackAlignment);
118 size_t pixelSize = d3d11::ComputePixelSizeBits(mDXGIFormat) / 8;
119 void* offsetMappedData = (void*)((BYTE *)mappedImage.pData + (yoffset * mappedImage.RowPitch + xoffset * pixelSize));
120
121 switch (mInternalFormat)
122 {
123 case GL_ALPHA8_EXT:
124 UNIMPLEMENTED(); // TODO - new function for D3D11-supported formats
125 break;
126 case GL_LUMINANCE8_EXT:
daniel@transgaming.com8ca7d372012-12-20 21:11:22 +0000127 loadLuminanceDataToNativeOrBGRA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData, false);
daniel@transgaming.coma8aac672012-12-20 21:08:00 +0000128 break;
129 case GL_ALPHA32F_EXT:
daniel@transgaming.com8ca7d372012-12-20 21:11:22 +0000130 loadAlphaFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
daniel@transgaming.coma8aac672012-12-20 21:08:00 +0000131 break;
132 case GL_LUMINANCE32F_EXT:
133 UNIMPLEMENTED(); // TODO - new function for D3D11-supported formats
134 break;
135 case GL_ALPHA16F_EXT:
daniel@transgaming.com8ca7d372012-12-20 21:11:22 +0000136 loadAlphaHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
daniel@transgaming.coma8aac672012-12-20 21:08:00 +0000137 break;
138 case GL_LUMINANCE16F_EXT:
daniel@transgaming.com8ca7d372012-12-20 21:11:22 +0000139 loadLuminanceHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
daniel@transgaming.coma8aac672012-12-20 21:08:00 +0000140 break;
141 case GL_LUMINANCE8_ALPHA8_EXT:
daniel@transgaming.com8ca7d372012-12-20 21:11:22 +0000142 loadLuminanceAlphaDataToNativeOrBGRA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData, false);
daniel@transgaming.coma8aac672012-12-20 21:08:00 +0000143 break;
144 case GL_LUMINANCE_ALPHA32F_EXT:
daniel@transgaming.com8ca7d372012-12-20 21:11:22 +0000145 loadLuminanceAlphaFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
daniel@transgaming.coma8aac672012-12-20 21:08:00 +0000146 break;
147 case GL_LUMINANCE_ALPHA16F_EXT:
daniel@transgaming.com8ca7d372012-12-20 21:11:22 +0000148 loadLuminanceAlphaHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
daniel@transgaming.coma8aac672012-12-20 21:08:00 +0000149 break;
150 case GL_RGB8_OES:
daniel@transgaming.com005979d2012-12-20 21:11:29 +0000151 loadRGBUByteDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
daniel@transgaming.coma8aac672012-12-20 21:08:00 +0000152 break;
153 case GL_RGB565:
daniel@transgaming.com005979d2012-12-20 21:11:29 +0000154 loadRGB565DataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
daniel@transgaming.coma8aac672012-12-20 21:08:00 +0000155 break;
156 case GL_RGBA8_OES:
daniel@transgaming.com005979d2012-12-20 21:11:29 +0000157 loadRGBAUByteDataToNative(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
daniel@transgaming.coma8aac672012-12-20 21:08:00 +0000158 break;
159 case GL_RGBA4:
daniel@transgaming.com005979d2012-12-20 21:11:29 +0000160 loadRGBA4444DataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
daniel@transgaming.coma8aac672012-12-20 21:08:00 +0000161 break;
162 case GL_RGB5_A1:
daniel@transgaming.com005979d2012-12-20 21:11:29 +0000163 loadRGBA5551DataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
daniel@transgaming.coma8aac672012-12-20 21:08:00 +0000164 break;
165 case GL_BGRA8_EXT:
daniel@transgaming.com8ca7d372012-12-20 21:11:22 +0000166 loadBGRADataToBGRA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
daniel@transgaming.coma8aac672012-12-20 21:08:00 +0000167 break;
168 case GL_RGB32F_EXT:
daniel@transgaming.com005979d2012-12-20 21:11:29 +0000169 loadRGBFloatDataToNative(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
daniel@transgaming.coma8aac672012-12-20 21:08:00 +0000170 break;
171 case GL_RGB16F_EXT:
daniel@transgaming.com8ca7d372012-12-20 21:11:22 +0000172 loadRGBHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
daniel@transgaming.coma8aac672012-12-20 21:08:00 +0000173 break;
174 case GL_RGBA32F_EXT:
daniel@transgaming.com8ca7d372012-12-20 21:11:22 +0000175 loadRGBAFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
daniel@transgaming.coma8aac672012-12-20 21:08:00 +0000176 break;
177 case GL_RGBA16F_EXT:
daniel@transgaming.com8ca7d372012-12-20 21:11:22 +0000178 loadRGBAHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
daniel@transgaming.coma8aac672012-12-20 21:08:00 +0000179 break;
180 default: UNREACHABLE();
181 }
182
183 unmap();
184}
185
186void Image11::loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
187 const void *input)
188{
189 ASSERT(xoffset % 4 == 0);
190 ASSERT(yoffset % 4 == 0);
191
192 D3D11_MAPPED_SUBRESOURCE mappedImage;
193 HRESULT result = map(&mappedImage);
194 if (FAILED(result))
195 {
196 ERR("Could not map image for loading.");
197 return;
198 }
199
200 // Size computation assumes a 4x4 block compressed texture format
201 size_t blockSize = d3d11::ComputeBlockSizeBits(mDXGIFormat) / 8;
202 void* offsetMappedData = (void*)((BYTE *)mappedImage.pData + ((yoffset / 4) * mappedImage.RowPitch + (xoffset / 4) * blockSize));
203
204 GLsizei inputSize = gl::ComputeCompressedSize(width, height, mInternalFormat);
205 GLsizei inputPitch = gl::ComputeCompressedPitch(width, mInternalFormat);
206 int rows = inputSize / inputPitch;
207 for (int i = 0; i < rows; ++i)
208 {
209 memcpy((void*)((BYTE*)offsetMappedData + i * mappedImage.RowPitch), (void*)((BYTE*)input + i * inputPitch), inputPitch);
210 }
211
212 unmap();
213}
214
215void Image11::copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source)
216{
217 // TODO
218 UNIMPLEMENTED();
219}
220
221void Image11::createStagingTexture()
222{
223 if (mStagingTexture)
224 {
225 return;
226 }
227
228 ID3D11Texture2D *newTexture = NULL;
229 const DXGI_FORMAT dxgiFormat = getDXGIFormat();
230 ASSERT(dxgiFormat != DXGI_FORMAT_D24_UNORM_S8_UINT); // We should never get here for depth textures
231
232 if (mWidth != 0 && mHeight != 0)
233 {
234 ID3D11Device *device = mRenderer->getDevice();
235
236 D3D11_TEXTURE2D_DESC desc;
237 desc.Width = mWidth;
238 desc.Height = mHeight;
239 desc.MipLevels = desc.ArraySize = 1;
240 desc.Format = dxgiFormat;
241 desc.SampleDesc.Count = 1;
242 desc.SampleDesc.Quality = 0;
243 desc.Usage = D3D11_USAGE_STAGING;
244 desc.BindFlags = 0;
245 desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
246 desc.MiscFlags = 0;
247
248 HRESULT result = device->CreateTexture2D(&desc, NULL, &newTexture);
249
250 if (FAILED(result))
251 {
252 ASSERT(result == E_OUTOFMEMORY);
253 ERR("Creating image failed.");
254 return error(GL_OUT_OF_MEMORY);
255 }
256 }
257
258 mStagingTexture = newTexture;
259 mDirty = false;
260}
261
262HRESULT Image11::map(D3D11_MAPPED_SUBRESOURCE *map)
263{
264 createStagingTexture();
265
266 HRESULT result = D3DERR_INVALIDCALL;
267
268 if (mStagingTexture)
269 {
270 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
271 result = deviceContext->Map(mStagingTexture, 0, D3D11_MAP_WRITE, 0, map);
272 ASSERT(SUCCEEDED(result));
273
274 mDirty = true;
275 }
276
277 return result;
278}
279
280void Image11::unmap()
281{
282 if (mStagingTexture)
283 {
284 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
285 deviceContext->Unmap(mStagingTexture, 0);
286 }
287}
288
289}