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