blob: a1edce12137100667b2fce8d5ebf54ceb84b6cbb [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.com5ea16ef2013-01-11 04:06:30 +000046ID3D11Texture2D *Image11::getStagingTexture()
47{
48 createStagingTexture();
49
50 return mStagingTexture;
51}
52
daniel@transgaming.com87705f82012-12-20 21:10:45 +000053bool Image11::updateSurface(TextureStorageInterface2D *storage, 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
daniel@transgaming.com87705f82012-12-20 21:10:45 +000060bool Image11::updateSurface(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
daniel@transgaming.coma8aac672012-12-20 21:08:00 +000061{
62 // TODO - relies on TextureStorage11 implementation
63 UNIMPLEMENTED();
64 return false;
65}
66
67bool Image11::redefine(Renderer *renderer, GLint internalformat, GLsizei width, GLsizei height, bool forceRelease)
68{
69 if (mWidth != width ||
70 mHeight != height ||
71 mInternalFormat != internalformat ||
72 forceRelease)
73 {
74 mRenderer = Renderer11::makeRenderer11(renderer);
75
76 mWidth = width;
77 mHeight = height;
78 mInternalFormat = internalformat;
79 // compute the d3d format that will be used
80 mDXGIFormat = gl_d3d11::ConvertTextureFormat(internalformat);
81 mActualFormat = d3d11_gl::ConvertTextureInternalFormat(mDXGIFormat);
82
83 if (mStagingTexture)
84 {
85 mStagingTexture->Release();
86 mStagingTexture = NULL;
87 }
88
89 return true;
90 }
91
92 return false;
93}
94
95bool Image11::isRenderableFormat() const
96{
97 // TODO - relies on TextureStorage11 implementation
98 UNIMPLEMENTED();
99 return false;
100}
101
102DXGI_FORMAT Image11::getDXGIFormat() const
103{
104 // this should only happen if the image hasn't been redefined first
105 // which would be a bug by the caller
106 ASSERT(mDXGIFormat != DXGI_FORMAT_UNKNOWN);
107
108 return mDXGIFormat;
109}
110
111// Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input
112// into the target pixel rectangle.
113void Image11::loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
114 GLint unpackAlignment, const void *input)
115{
116 D3D11_MAPPED_SUBRESOURCE mappedImage;
117 HRESULT result = map(&mappedImage);
118 if (FAILED(result))
119 {
120 ERR("Could not map image for loading.");
121 return;
122 }
123
124 GLsizei inputPitch = gl::ComputePitch(width, mInternalFormat, unpackAlignment);
125 size_t pixelSize = d3d11::ComputePixelSizeBits(mDXGIFormat) / 8;
126 void* offsetMappedData = (void*)((BYTE *)mappedImage.pData + (yoffset * mappedImage.RowPitch + xoffset * pixelSize));
127
128 switch (mInternalFormat)
129 {
130 case GL_ALPHA8_EXT:
131 UNIMPLEMENTED(); // TODO - new function for D3D11-supported formats
132 break;
133 case GL_LUMINANCE8_EXT:
daniel@transgaming.com8ca7d372012-12-20 21:11:22 +0000134 loadLuminanceDataToNativeOrBGRA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData, false);
daniel@transgaming.coma8aac672012-12-20 21:08:00 +0000135 break;
136 case GL_ALPHA32F_EXT:
daniel@transgaming.com8ca7d372012-12-20 21:11:22 +0000137 loadAlphaFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
daniel@transgaming.coma8aac672012-12-20 21:08:00 +0000138 break;
139 case GL_LUMINANCE32F_EXT:
140 UNIMPLEMENTED(); // TODO - new function for D3D11-supported formats
141 break;
142 case GL_ALPHA16F_EXT:
daniel@transgaming.com8ca7d372012-12-20 21:11:22 +0000143 loadAlphaHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
daniel@transgaming.coma8aac672012-12-20 21:08:00 +0000144 break;
145 case GL_LUMINANCE16F_EXT:
daniel@transgaming.com8ca7d372012-12-20 21:11:22 +0000146 loadLuminanceHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
daniel@transgaming.coma8aac672012-12-20 21:08:00 +0000147 break;
148 case GL_LUMINANCE8_ALPHA8_EXT:
daniel@transgaming.com8ca7d372012-12-20 21:11:22 +0000149 loadLuminanceAlphaDataToNativeOrBGRA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData, false);
daniel@transgaming.coma8aac672012-12-20 21:08:00 +0000150 break;
151 case GL_LUMINANCE_ALPHA32F_EXT:
daniel@transgaming.com8ca7d372012-12-20 21:11:22 +0000152 loadLuminanceAlphaFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
daniel@transgaming.coma8aac672012-12-20 21:08:00 +0000153 break;
154 case GL_LUMINANCE_ALPHA16F_EXT:
daniel@transgaming.com8ca7d372012-12-20 21:11:22 +0000155 loadLuminanceAlphaHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
daniel@transgaming.coma8aac672012-12-20 21:08:00 +0000156 break;
157 case GL_RGB8_OES:
daniel@transgaming.com005979d2012-12-20 21:11:29 +0000158 loadRGBUByteDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
daniel@transgaming.coma8aac672012-12-20 21:08:00 +0000159 break;
160 case GL_RGB565:
daniel@transgaming.com005979d2012-12-20 21:11:29 +0000161 loadRGB565DataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
daniel@transgaming.coma8aac672012-12-20 21:08:00 +0000162 break;
163 case GL_RGBA8_OES:
daniel@transgaming.com005979d2012-12-20 21:11:29 +0000164 loadRGBAUByteDataToNative(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
daniel@transgaming.coma8aac672012-12-20 21:08:00 +0000165 break;
166 case GL_RGBA4:
daniel@transgaming.com005979d2012-12-20 21:11:29 +0000167 loadRGBA4444DataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
daniel@transgaming.coma8aac672012-12-20 21:08:00 +0000168 break;
169 case GL_RGB5_A1:
daniel@transgaming.com005979d2012-12-20 21:11:29 +0000170 loadRGBA5551DataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
daniel@transgaming.coma8aac672012-12-20 21:08:00 +0000171 break;
172 case GL_BGRA8_EXT:
daniel@transgaming.com8ca7d372012-12-20 21:11:22 +0000173 loadBGRADataToBGRA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
daniel@transgaming.coma8aac672012-12-20 21:08:00 +0000174 break;
175 case GL_RGB32F_EXT:
daniel@transgaming.com005979d2012-12-20 21:11:29 +0000176 loadRGBFloatDataToNative(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
daniel@transgaming.coma8aac672012-12-20 21:08:00 +0000177 break;
178 case GL_RGB16F_EXT:
daniel@transgaming.com8ca7d372012-12-20 21:11:22 +0000179 loadRGBHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
daniel@transgaming.coma8aac672012-12-20 21:08:00 +0000180 break;
181 case GL_RGBA32F_EXT:
daniel@transgaming.com8ca7d372012-12-20 21:11:22 +0000182 loadRGBAFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
daniel@transgaming.coma8aac672012-12-20 21:08:00 +0000183 break;
184 case GL_RGBA16F_EXT:
daniel@transgaming.com8ca7d372012-12-20 21:11:22 +0000185 loadRGBAHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
daniel@transgaming.coma8aac672012-12-20 21:08:00 +0000186 break;
187 default: UNREACHABLE();
188 }
189
190 unmap();
191}
192
193void Image11::loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
194 const void *input)
195{
196 ASSERT(xoffset % 4 == 0);
197 ASSERT(yoffset % 4 == 0);
198
199 D3D11_MAPPED_SUBRESOURCE mappedImage;
200 HRESULT result = map(&mappedImage);
201 if (FAILED(result))
202 {
203 ERR("Could not map image for loading.");
204 return;
205 }
206
207 // Size computation assumes a 4x4 block compressed texture format
208 size_t blockSize = d3d11::ComputeBlockSizeBits(mDXGIFormat) / 8;
209 void* offsetMappedData = (void*)((BYTE *)mappedImage.pData + ((yoffset / 4) * mappedImage.RowPitch + (xoffset / 4) * blockSize));
210
211 GLsizei inputSize = gl::ComputeCompressedSize(width, height, mInternalFormat);
212 GLsizei inputPitch = gl::ComputeCompressedPitch(width, mInternalFormat);
213 int rows = inputSize / inputPitch;
214 for (int i = 0; i < rows; ++i)
215 {
216 memcpy((void*)((BYTE*)offsetMappedData + i * mappedImage.RowPitch), (void*)((BYTE*)input + i * inputPitch), inputPitch);
217 }
218
219 unmap();
220}
221
222void Image11::copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source)
223{
224 // TODO
225 UNIMPLEMENTED();
226}
227
228void Image11::createStagingTexture()
229{
230 if (mStagingTexture)
231 {
232 return;
233 }
234
235 ID3D11Texture2D *newTexture = NULL;
236 const DXGI_FORMAT dxgiFormat = getDXGIFormat();
237 ASSERT(dxgiFormat != DXGI_FORMAT_D24_UNORM_S8_UINT); // We should never get here for depth textures
238
239 if (mWidth != 0 && mHeight != 0)
240 {
241 ID3D11Device *device = mRenderer->getDevice();
242
243 D3D11_TEXTURE2D_DESC desc;
244 desc.Width = mWidth;
245 desc.Height = mHeight;
246 desc.MipLevels = desc.ArraySize = 1;
247 desc.Format = dxgiFormat;
248 desc.SampleDesc.Count = 1;
249 desc.SampleDesc.Quality = 0;
250 desc.Usage = D3D11_USAGE_STAGING;
251 desc.BindFlags = 0;
252 desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
253 desc.MiscFlags = 0;
254
255 HRESULT result = device->CreateTexture2D(&desc, NULL, &newTexture);
256
257 if (FAILED(result))
258 {
259 ASSERT(result == E_OUTOFMEMORY);
260 ERR("Creating image failed.");
261 return error(GL_OUT_OF_MEMORY);
262 }
263 }
264
265 mStagingTexture = newTexture;
266 mDirty = false;
267}
268
269HRESULT Image11::map(D3D11_MAPPED_SUBRESOURCE *map)
270{
271 createStagingTexture();
272
273 HRESULT result = D3DERR_INVALIDCALL;
274
275 if (mStagingTexture)
276 {
277 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
278 result = deviceContext->Map(mStagingTexture, 0, D3D11_MAP_WRITE, 0, map);
279 ASSERT(SUCCEEDED(result));
280
281 mDirty = true;
282 }
283
284 return result;
285}
286
287void Image11::unmap()
288{
289 if (mStagingTexture)
290 {
291 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
292 deviceContext->Unmap(mStagingTexture, 0);
293 }
294}
295
296}