blob: b41b8e598f5a1c7c270ede7397b1f8750af6eab2 [file] [log] [blame]
daniel@transgaming.comb9d7e6f2012-10-31 19:08:32 +00001//
2// Copyright (c) 2002-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// Image.cpp: Implements the gl::Image class, which acts as the interface to
8// the actual underlying surfaces of a Texture.
9
10#include "libGLESv2/renderer/Image.h"
11
12#include "libEGL/Display.h"
13
14#include "libGLESv2/main.h"
15#include "libGLESv2/mathutil.h"
16#include "libGLESv2/utilities.h"
17#include "libGLESv2/Texture.h"
18
19namespace gl
20{
21Image::Image()
22{
23 mWidth = 0;
24 mHeight = 0;
25 mInternalFormat = GL_NONE;
26
27 mSurface = NULL;
28
29 mDirty = false;
30
31 mD3DPool = D3DPOOL_SYSTEMMEM;
32 mD3DFormat = D3DFMT_UNKNOWN;
daniel@transgaming.com20d36662012-10-31 19:51:43 +000033 mActualFormat = GL_NONE;
daniel@transgaming.comb9d7e6f2012-10-31 19:08:32 +000034}
35
36Image::~Image()
37{
38 if (mSurface)
39 {
40 mSurface->Release();
41 }
42}
43
44void Image::CopyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface9 *source)
45{
46 D3DLOCKED_RECT sourceLock = {0};
47 D3DLOCKED_RECT destLock = {0};
48
49 source->LockRect(&sourceLock, NULL, 0);
50 dest->LockRect(&destLock, NULL, 0);
51
52 if (sourceLock.pBits && destLock.pBits)
53 {
54 D3DSURFACE_DESC desc;
55 source->GetDesc(&desc);
56
57 int rows = dx::IsCompressedFormat(desc.Format) ? desc.Height / 4 : desc.Height;
58 int bytes = dx::ComputeRowSize(desc.Format, desc.Width);
59 ASSERT(bytes <= sourceLock.Pitch && bytes <= destLock.Pitch);
60
61 for(int i = 0; i < rows; i++)
62 {
63 memcpy((char*)destLock.pBits + destLock.Pitch * i, (char*)sourceLock.pBits + sourceLock.Pitch * i, bytes);
64 }
65
66 source->UnlockRect();
67 dest->UnlockRect();
68 }
69 else UNREACHABLE();
70}
71
72bool Image::redefine(GLint internalformat, GLsizei width, GLsizei height, bool forceRelease)
73{
74 if (mWidth != width ||
75 mHeight != height ||
76 mInternalFormat != internalformat ||
77 forceRelease)
78 {
79 mWidth = width;
80 mHeight = height;
81 mInternalFormat = internalformat;
82 // compute the d3d format that will be used
daniel@transgaming.comdf14c762012-10-31 19:51:48 +000083 mD3DFormat = TextureStorage::ConvertTextureInternalFormat(internalformat);
daniel@transgaming.com20d36662012-10-31 19:51:43 +000084 mActualFormat = dx2es::GetEquivalentFormat(mD3DFormat);
daniel@transgaming.comb9d7e6f2012-10-31 19:08:32 +000085
86 if (mSurface)
87 {
88 mSurface->Release();
89 mSurface = NULL;
90 }
91
92 return true;
93 }
94
95 return false;
96}
97
98void Image::createSurface()
99{
100 if(mSurface)
101 {
102 return;
103 }
104
105 IDirect3DTexture9 *newTexture = NULL;
106 IDirect3DSurface9 *newSurface = NULL;
107 const D3DPOOL poolToUse = D3DPOOL_SYSTEMMEM;
108 const D3DFORMAT d3dFormat = getD3DFormat();
109 ASSERT(d3dFormat != D3DFMT_INTZ); // We should never get here for depth textures
110
111 if (mWidth != 0 && mHeight != 0)
112 {
113 int levelToFetch = 0;
114 GLsizei requestWidth = mWidth;
115 GLsizei requestHeight = mHeight;
116 MakeValidSize(true, IsCompressed(mInternalFormat), &requestWidth, &requestHeight, &levelToFetch);
117
118 // D3D9_REPLACE
119 IDirect3DDevice9 *device = getDisplay()->getRenderer()->getDevice();
120 HRESULT result = device->CreateTexture(requestWidth, requestHeight, levelToFetch + 1, NULL, d3dFormat,
121 poolToUse, &newTexture, NULL);
122
123 if (FAILED(result))
124 {
125 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
126 ERR("Creating image surface failed.");
127 return error(GL_OUT_OF_MEMORY);
128 }
129
130 newTexture->GetSurfaceLevel(levelToFetch, &newSurface);
131 newTexture->Release();
132 }
133
134 mSurface = newSurface;
135 mDirty = false;
136 mD3DPool = poolToUse;
137}
138
139HRESULT Image::lock(D3DLOCKED_RECT *lockedRect, const RECT *rect)
140{
141 createSurface();
142
143 HRESULT result = D3DERR_INVALIDCALL;
144
145 if (mSurface)
146 {
147 result = mSurface->LockRect(lockedRect, rect, 0);
148 ASSERT(SUCCEEDED(result));
149
150 mDirty = true;
151 }
152
153 return result;
154}
155
156void Image::unlock()
157{
158 if (mSurface)
159 {
160 HRESULT result = mSurface->UnlockRect();
161 ASSERT(SUCCEEDED(result));
162 }
163}
164
165bool Image::isRenderableFormat() const
166{
daniel@transgaming.comdf14c762012-10-31 19:51:48 +0000167 return TextureStorage::IsTextureFormatRenderable(getD3DFormat());
daniel@transgaming.comb9d7e6f2012-10-31 19:08:32 +0000168}
169
daniel@transgaming.com20d36662012-10-31 19:51:43 +0000170GLenum Image::getActualFormat() const
171{
172 return mActualFormat;
173}
174
daniel@transgaming.comb9d7e6f2012-10-31 19:08:32 +0000175D3DFORMAT Image::getD3DFormat() const
176{
177 // this should only happen if the image hasn't been redefined first
178 // which would be a bug by the caller
179 ASSERT(mD3DFormat != D3DFMT_UNKNOWN);
180
181 return mD3DFormat;
182}
183
184IDirect3DSurface9 *Image::getSurface()
185{
186 createSurface();
187
188 return mSurface;
189}
190
191void Image::setManagedSurface(IDirect3DSurface9 *surface)
192{
193 D3DSURFACE_DESC desc;
194 surface->GetDesc(&desc);
195 ASSERT(desc.Pool == D3DPOOL_MANAGED);
196
197 if ((GLsizei)desc.Width == mWidth && (GLsizei)desc.Height == mHeight)
198 {
199 if (mSurface)
200 {
201 CopyLockableSurfaces(surface, mSurface);
202 mSurface->Release();
203 }
204
205 mSurface = surface;
206 mD3DPool = desc.Pool;
207 }
208}
209
210void Image::updateSurface(IDirect3DSurface9 *destSurface, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
211{
212 IDirect3DSurface9 *sourceSurface = getSurface();
213
214 if (sourceSurface && sourceSurface != destSurface)
215 {
216 RECT rect;
217 rect.left = xoffset;
218 rect.top = yoffset;
219 rect.right = xoffset + width;
220 rect.bottom = yoffset + height;
221
222 POINT point = {rect.left, rect.top};
223 IDirect3DDevice9 *device = getDisplay()->getRenderer()->getDevice(); // D3D9_REPLACE
224
225 if (mD3DPool == D3DPOOL_MANAGED)
226 {
227 D3DSURFACE_DESC desc;
228 sourceSurface->GetDesc(&desc);
229
230 IDirect3DSurface9 *surf = 0;
231 HRESULT result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surf, NULL);
232
233 if (SUCCEEDED(result))
234 {
235 CopyLockableSurfaces(surf, sourceSurface);
236 result = device->UpdateSurface(surf, &rect, destSurface, &point);
237 ASSERT(SUCCEEDED(result));
238 surf->Release();
239 }
240 }
241 else
242 {
243 // UpdateSurface: source must be SYSTEMMEM, dest must be DEFAULT pools
244 HRESULT result = device->UpdateSurface(sourceSurface, &rect, destSurface, &point);
245 ASSERT(SUCCEEDED(result));
246 }
247 }
248}
249
250// Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input
251// into the target pixel rectangle.
252void Image::loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
253 GLint unpackAlignment, const void *input)
254{
255 RECT lockRect =
256 {
257 xoffset, yoffset,
258 xoffset + width, yoffset + height
259 };
260
261 D3DLOCKED_RECT locked;
262 HRESULT result = lock(&locked, &lockRect);
263 if (FAILED(result))
264 {
265 return;
266 }
267
268
269 GLsizei inputPitch = ComputePitch(width, mInternalFormat, unpackAlignment);
270
271 switch (mInternalFormat)
272 {
273 case GL_ALPHA8_EXT:
274 if (supportsSSE2())
275 {
276 loadAlphaDataSSE2(width, height, inputPitch, input, locked.Pitch, locked.pBits);
277 }
278 else
279 {
280 loadAlphaData(width, height, inputPitch, input, locked.Pitch, locked.pBits);
281 }
282 break;
283 case GL_LUMINANCE8_EXT:
284 loadLuminanceData(width, height, inputPitch, input, locked.Pitch, locked.pBits, getD3DFormat() == D3DFMT_L8);
285 break;
286 case GL_ALPHA32F_EXT:
287 loadAlphaFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits);
288 break;
289 case GL_LUMINANCE32F_EXT:
290 loadLuminanceFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits);
291 break;
292 case GL_ALPHA16F_EXT:
293 loadAlphaHalfFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits);
294 break;
295 case GL_LUMINANCE16F_EXT:
296 loadLuminanceHalfFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits);
297 break;
298 case GL_LUMINANCE8_ALPHA8_EXT:
299 loadLuminanceAlphaData(width, height, inputPitch, input, locked.Pitch, locked.pBits, getD3DFormat() == D3DFMT_A8L8);
300 break;
301 case GL_LUMINANCE_ALPHA32F_EXT:
302 loadLuminanceAlphaFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits);
303 break;
304 case GL_LUMINANCE_ALPHA16F_EXT:
305 loadLuminanceAlphaHalfFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits);
306 break;
307 case GL_RGB8_OES:
308 loadRGBUByteData(width, height, inputPitch, input, locked.Pitch, locked.pBits);
309 break;
310 case GL_RGB565:
311 loadRGB565Data(width, height, inputPitch, input, locked.Pitch, locked.pBits);
312 break;
313 case GL_RGBA8_OES:
314 if (supportsSSE2())
315 {
316 loadRGBAUByteDataSSE2(width, height, inputPitch, input, locked.Pitch, locked.pBits);
317 }
318 else
319 {
320 loadRGBAUByteData(width, height, inputPitch, input, locked.Pitch, locked.pBits);
321 }
322 break;
323 case GL_RGBA4:
324 loadRGBA4444Data(width, height, inputPitch, input, locked.Pitch, locked.pBits);
325 break;
326 case GL_RGB5_A1:
327 loadRGBA5551Data(width, height, inputPitch, input, locked.Pitch, locked.pBits);
328 break;
329 case GL_BGRA8_EXT:
330 loadBGRAData(width, height, inputPitch, input, locked.Pitch, locked.pBits);
331 break;
332 // float textures are converted to RGBA, not BGRA, as they're stored that way in D3D
333 case GL_RGB32F_EXT:
334 loadRGBFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits);
335 break;
336 case GL_RGB16F_EXT:
337 loadRGBHalfFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits);
338 break;
339 case GL_RGBA32F_EXT:
340 loadRGBAFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits);
341 break;
342 case GL_RGBA16F_EXT:
343 loadRGBAHalfFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits);
344 break;
345 default: UNREACHABLE();
346 }
347
348 unlock();
349}
350
351void Image::loadAlphaData(GLsizei width, GLsizei height,
352 int inputPitch, const void *input, size_t outputPitch, void *output) const
353{
354 const unsigned char *source = NULL;
355 unsigned char *dest = NULL;
356
357 for (int y = 0; y < height; y++)
358 {
359 source = static_cast<const unsigned char*>(input) + y * inputPitch;
360 dest = static_cast<unsigned char*>(output) + y * outputPitch;
361 for (int x = 0; x < width; x++)
362 {
363 dest[4 * x + 0] = 0;
364 dest[4 * x + 1] = 0;
365 dest[4 * x + 2] = 0;
366 dest[4 * x + 3] = source[x];
367 }
368 }
369}
370
371void Image::loadAlphaFloatData(GLsizei width, GLsizei height,
372 int inputPitch, const void *input, size_t outputPitch, void *output) const
373{
374 const float *source = NULL;
375 float *dest = NULL;
376
377 for (int y = 0; y < height; y++)
378 {
379 source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
380 dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + y * outputPitch);
381 for (int x = 0; x < width; x++)
382 {
383 dest[4 * x + 0] = 0;
384 dest[4 * x + 1] = 0;
385 dest[4 * x + 2] = 0;
386 dest[4 * x + 3] = source[x];
387 }
388 }
389}
390
391void Image::loadAlphaHalfFloatData(GLsizei width, GLsizei height,
392 int inputPitch, const void *input, size_t outputPitch, void *output) const
393{
394 const unsigned short *source = NULL;
395 unsigned short *dest = NULL;
396
397 for (int y = 0; y < height; y++)
398 {
399 source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
400 dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + y * outputPitch);
401 for (int x = 0; x < width; x++)
402 {
403 dest[4 * x + 0] = 0;
404 dest[4 * x + 1] = 0;
405 dest[4 * x + 2] = 0;
406 dest[4 * x + 3] = source[x];
407 }
408 }
409}
410
411void Image::loadLuminanceData(GLsizei width, GLsizei height,
412 int inputPitch, const void *input, size_t outputPitch, void *output, bool native) const
413{
414 const unsigned char *source = NULL;
415 unsigned char *dest = NULL;
416
417 for (int y = 0; y < height; y++)
418 {
419 source = static_cast<const unsigned char*>(input) + y * inputPitch;
420 dest = static_cast<unsigned char*>(output) + y * outputPitch;
421
422 if (!native) // BGRA8 destination format
423 {
424 for (int x = 0; x < width; x++)
425 {
426 dest[4 * x + 0] = source[x];
427 dest[4 * x + 1] = source[x];
428 dest[4 * x + 2] = source[x];
429 dest[4 * x + 3] = 0xFF;
430 }
431 }
432 else // L8 destination format
433 {
434 memcpy(dest, source, width);
435 }
436 }
437}
438
439void Image::loadLuminanceFloatData(GLsizei width, GLsizei height,
440 int inputPitch, const void *input, size_t outputPitch, void *output) const
441{
442 const float *source = NULL;
443 float *dest = NULL;
444
445 for (int y = 0; y < height; y++)
446 {
447 source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
448 dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + y * outputPitch);
449 for (int x = 0; x < width; x++)
450 {
451 dest[4 * x + 0] = source[x];
452 dest[4 * x + 1] = source[x];
453 dest[4 * x + 2] = source[x];
454 dest[4 * x + 3] = 1.0f;
455 }
456 }
457}
458
459void Image::loadLuminanceHalfFloatData(GLsizei width, GLsizei height,
460 int inputPitch, const void *input, size_t outputPitch, void *output) const
461{
462 const unsigned short *source = NULL;
463 unsigned short *dest = NULL;
464
465 for (int y = 0; y < height; y++)
466 {
467 source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
468 dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + y * outputPitch);
469 for (int x = 0; x < width; x++)
470 {
471 dest[4 * x + 0] = source[x];
472 dest[4 * x + 1] = source[x];
473 dest[4 * x + 2] = source[x];
474 dest[4 * x + 3] = 0x3C00; // SEEEEEMMMMMMMMMM, S = 0, E = 15, M = 0: 16bit flpt representation of 1
475 }
476 }
477}
478
479void Image::loadLuminanceAlphaData(GLsizei width, GLsizei height,
480 int inputPitch, const void *input, size_t outputPitch, void *output, bool native) const
481{
482 const unsigned char *source = NULL;
483 unsigned char *dest = NULL;
484
485 for (int y = 0; y < height; y++)
486 {
487 source = static_cast<const unsigned char*>(input) + y * inputPitch;
488 dest = static_cast<unsigned char*>(output) + y * outputPitch;
489
490 if (!native) // BGRA8 destination format
491 {
492 for (int x = 0; x < width; x++)
493 {
494 dest[4 * x + 0] = source[2*x+0];
495 dest[4 * x + 1] = source[2*x+0];
496 dest[4 * x + 2] = source[2*x+0];
497 dest[4 * x + 3] = source[2*x+1];
498 }
499 }
500 else
501 {
502 memcpy(dest, source, width * 2);
503 }
504 }
505}
506
507void Image::loadLuminanceAlphaFloatData(GLsizei width, GLsizei height,
508 int inputPitch, const void *input, size_t outputPitch, void *output) const
509{
510 const float *source = NULL;
511 float *dest = NULL;
512
513 for (int y = 0; y < height; y++)
514 {
515 source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
516 dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + y * outputPitch);
517 for (int x = 0; x < width; x++)
518 {
519 dest[4 * x + 0] = source[2*x+0];
520 dest[4 * x + 1] = source[2*x+0];
521 dest[4 * x + 2] = source[2*x+0];
522 dest[4 * x + 3] = source[2*x+1];
523 }
524 }
525}
526
527void Image::loadLuminanceAlphaHalfFloatData(GLsizei width, GLsizei height,
528 int inputPitch, const void *input, size_t outputPitch, void *output) const
529{
530 const unsigned short *source = NULL;
531 unsigned short *dest = NULL;
532
533 for (int y = 0; y < height; y++)
534 {
535 source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
536 dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + y * outputPitch);
537 for (int x = 0; x < width; x++)
538 {
539 dest[4 * x + 0] = source[2*x+0];
540 dest[4 * x + 1] = source[2*x+0];
541 dest[4 * x + 2] = source[2*x+0];
542 dest[4 * x + 3] = source[2*x+1];
543 }
544 }
545}
546
547void Image::loadRGBUByteData(GLsizei width, GLsizei height,
548 int inputPitch, const void *input, size_t outputPitch, void *output) const
549{
550 const unsigned char *source = NULL;
551 unsigned char *dest = NULL;
552
553 for (int y = 0; y < height; y++)
554 {
555 source = static_cast<const unsigned char*>(input) + y * inputPitch;
556 dest = static_cast<unsigned char*>(output) + y * outputPitch;
557 for (int x = 0; x < width; x++)
558 {
559 dest[4 * x + 0] = source[x * 3 + 2];
560 dest[4 * x + 1] = source[x * 3 + 1];
561 dest[4 * x + 2] = source[x * 3 + 0];
562 dest[4 * x + 3] = 0xFF;
563 }
564 }
565}
566
567void Image::loadRGB565Data(GLsizei width, GLsizei height,
568 int inputPitch, const void *input, size_t outputPitch, void *output) const
569{
570 const unsigned short *source = NULL;
571 unsigned char *dest = NULL;
572
573 for (int y = 0; y < height; y++)
574 {
575 source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
576 dest = static_cast<unsigned char*>(output) + y * outputPitch;
577 for (int x = 0; x < width; x++)
578 {
579 unsigned short rgba = source[x];
580 dest[4 * x + 0] = ((rgba & 0x001F) << 3) | ((rgba & 0x001F) >> 2);
581 dest[4 * x + 1] = ((rgba & 0x07E0) >> 3) | ((rgba & 0x07E0) >> 9);
582 dest[4 * x + 2] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13);
583 dest[4 * x + 3] = 0xFF;
584 }
585 }
586}
587
588void Image::loadRGBFloatData(GLsizei width, GLsizei height,
589 int inputPitch, const void *input, size_t outputPitch, void *output) const
590{
591 const float *source = NULL;
592 float *dest = NULL;
593
594 for (int y = 0; y < height; y++)
595 {
596 source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
597 dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + y * outputPitch);
598 for (int x = 0; x < width; x++)
599 {
600 dest[4 * x + 0] = source[x * 3 + 0];
601 dest[4 * x + 1] = source[x * 3 + 1];
602 dest[4 * x + 2] = source[x * 3 + 2];
603 dest[4 * x + 3] = 1.0f;
604 }
605 }
606}
607
608void Image::loadRGBHalfFloatData(GLsizei width, GLsizei height,
609 int inputPitch, const void *input, size_t outputPitch, void *output) const
610{
611 const unsigned short *source = NULL;
612 unsigned short *dest = NULL;
613
614 for (int y = 0; y < height; y++)
615 {
616 source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
617 dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + y * outputPitch);
618 for (int x = 0; x < width; x++)
619 {
620 dest[4 * x + 0] = source[x * 3 + 0];
621 dest[4 * x + 1] = source[x * 3 + 1];
622 dest[4 * x + 2] = source[x * 3 + 2];
623 dest[4 * x + 3] = 0x3C00; // SEEEEEMMMMMMMMMM, S = 0, E = 15, M = 0: 16bit flpt representation of 1
624 }
625 }
626}
627
628void Image::loadRGBAUByteData(GLsizei width, GLsizei height,
629 int inputPitch, const void *input, size_t outputPitch, void *output) const
630{
631 const unsigned int *source = NULL;
632 unsigned int *dest = NULL;
633 for (int y = 0; y < height; y++)
634 {
635 source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch);
636 dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + y * outputPitch);
637
638 for (int x = 0; x < width; x++)
639 {
640 unsigned int rgba = source[x];
641 dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00);
642 }
643 }
644}
645
646void Image::loadRGBA4444Data(GLsizei width, GLsizei height,
647 int inputPitch, const void *input, size_t outputPitch, void *output) const
648{
649 const unsigned short *source = NULL;
650 unsigned char *dest = NULL;
651
652 for (int y = 0; y < height; y++)
653 {
654 source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
655 dest = static_cast<unsigned char*>(output) + y * outputPitch;
656 for (int x = 0; x < width; x++)
657 {
658 unsigned short rgba = source[x];
659 dest[4 * x + 0] = ((rgba & 0x00F0) << 0) | ((rgba & 0x00F0) >> 4);
660 dest[4 * x + 1] = ((rgba & 0x0F00) >> 4) | ((rgba & 0x0F00) >> 8);
661 dest[4 * x + 2] = ((rgba & 0xF000) >> 8) | ((rgba & 0xF000) >> 12);
662 dest[4 * x + 3] = ((rgba & 0x000F) << 4) | ((rgba & 0x000F) >> 0);
663 }
664 }
665}
666
667void Image::loadRGBA5551Data(GLsizei width, GLsizei height,
668 int inputPitch, const void *input, size_t outputPitch, void *output) const
669{
670 const unsigned short *source = NULL;
671 unsigned char *dest = NULL;
672
673 for (int y = 0; y < height; y++)
674 {
675 source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
676 dest = static_cast<unsigned char*>(output) + y * outputPitch;
677 for (int x = 0; x < width; x++)
678 {
679 unsigned short rgba = source[x];
680 dest[4 * x + 0] = ((rgba & 0x003E) << 2) | ((rgba & 0x003E) >> 3);
681 dest[4 * x + 1] = ((rgba & 0x07C0) >> 3) | ((rgba & 0x07C0) >> 8);
682 dest[4 * x + 2] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13);
683 dest[4 * x + 3] = (rgba & 0x0001) ? 0xFF : 0;
684 }
685 }
686}
687
688void Image::loadRGBAFloatData(GLsizei width, GLsizei height,
689 int inputPitch, const void *input, size_t outputPitch, void *output) const
690{
691 const float *source = NULL;
692 float *dest = NULL;
693
694 for (int y = 0; y < height; y++)
695 {
696 source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
697 dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + y * outputPitch);
698 memcpy(dest, source, width * 16);
699 }
700}
701
702void Image::loadRGBAHalfFloatData(GLsizei width, GLsizei height,
703 int inputPitch, const void *input, size_t outputPitch, void *output) const
704{
705 const unsigned char *source = NULL;
706 unsigned char *dest = NULL;
707
708 for (int y = 0; y < height; y++)
709 {
710 source = static_cast<const unsigned char*>(input) + y * inputPitch;
711 dest = static_cast<unsigned char*>(output) + y * outputPitch;
712 memcpy(dest, source, width * 8);
713 }
714}
715
716void Image::loadBGRAData(GLsizei width, GLsizei height,
717 int inputPitch, const void *input, size_t outputPitch, void *output) const
718{
719 const unsigned char *source = NULL;
720 unsigned char *dest = NULL;
721
722 for (int y = 0; y < height; y++)
723 {
724 source = static_cast<const unsigned char*>(input) + y * inputPitch;
725 dest = static_cast<unsigned char*>(output) + y * outputPitch;
726 memcpy(dest, source, width*4);
727 }
728}
729
730void Image::loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
731 const void *input) {
732 ASSERT(xoffset % 4 == 0);
733 ASSERT(yoffset % 4 == 0);
734
735 RECT lockRect = {
736 xoffset, yoffset,
737 xoffset + width, yoffset + height
738 };
739
740 D3DLOCKED_RECT locked;
741 HRESULT result = lock(&locked, &lockRect);
742 if (FAILED(result))
743 {
744 return;
745 }
746
747 GLsizei inputSize = ComputeCompressedSize(width, height, mInternalFormat);
748 GLsizei inputPitch = ComputeCompressedPitch(width, mInternalFormat);
749 int rows = inputSize / inputPitch;
750 for (int i = 0; i < rows; ++i)
751 {
752 memcpy((void*)((BYTE*)locked.pBits + i * locked.Pitch), (void*)((BYTE*)input + i * inputPitch), inputPitch);
753 }
754
755 unlock();
756}
757
758// This implements glCopyTex[Sub]Image2D for non-renderable internal texture formats and incomplete textures
759void Image::copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, IDirect3DSurface9 *renderTarget)
760{
761 IDirect3DDevice9 *device = getDisplay()->getRenderer()->getDevice(); // D3D9_REPLACE
762 IDirect3DSurface9 *renderTargetData = NULL;
763 D3DSURFACE_DESC description;
764 renderTarget->GetDesc(&description);
765
766 HRESULT result = device->CreateOffscreenPlainSurface(description.Width, description.Height, description.Format, D3DPOOL_SYSTEMMEM, &renderTargetData, NULL);
767
768 if (FAILED(result))
769 {
770 ERR("Could not create matching destination surface.");
771 return error(GL_OUT_OF_MEMORY);
772 }
773
774 result = device->GetRenderTargetData(renderTarget, renderTargetData);
775
776 if (FAILED(result))
777 {
778 ERR("GetRenderTargetData unexpectedly failed.");
779 renderTargetData->Release();
780 return error(GL_OUT_OF_MEMORY);
781 }
782
783 RECT sourceRect = {x, y, x + width, y + height};
784 RECT destRect = {xoffset, yoffset, xoffset + width, yoffset + height};
785
786 D3DLOCKED_RECT sourceLock = {0};
787 result = renderTargetData->LockRect(&sourceLock, &sourceRect, 0);
788
789 if (FAILED(result))
790 {
791 ERR("Failed to lock the source surface (rectangle might be invalid).");
792 renderTargetData->Release();
793 return error(GL_OUT_OF_MEMORY);
794 }
795
796 D3DLOCKED_RECT destLock = {0};
797 result = lock(&destLock, &destRect);
798
799 if (FAILED(result))
800 {
801 ERR("Failed to lock the destination surface (rectangle might be invalid).");
802 renderTargetData->UnlockRect();
803 renderTargetData->Release();
804 return error(GL_OUT_OF_MEMORY);
805 }
806
807 if (destLock.pBits && sourceLock.pBits)
808 {
809 unsigned char *source = (unsigned char*)sourceLock.pBits;
810 unsigned char *dest = (unsigned char*)destLock.pBits;
811
812 switch (description.Format)
813 {
814 case D3DFMT_X8R8G8B8:
815 case D3DFMT_A8R8G8B8:
816 switch(getD3DFormat())
817 {
818 case D3DFMT_X8R8G8B8:
819 case D3DFMT_A8R8G8B8:
820 for(int y = 0; y < height; y++)
821 {
822 memcpy(dest, source, 4 * width);
823
824 source += sourceLock.Pitch;
825 dest += destLock.Pitch;
826 }
827 break;
828 case D3DFMT_L8:
829 for(int y = 0; y < height; y++)
830 {
831 for(int x = 0; x < width; x++)
832 {
833 dest[x] = source[x * 4 + 2];
834 }
835
836 source += sourceLock.Pitch;
837 dest += destLock.Pitch;
838 }
839 break;
840 case D3DFMT_A8L8:
841 for(int y = 0; y < height; y++)
842 {
843 for(int x = 0; x < width; x++)
844 {
845 dest[x * 2 + 0] = source[x * 4 + 2];
846 dest[x * 2 + 1] = source[x * 4 + 3];
847 }
848
849 source += sourceLock.Pitch;
850 dest += destLock.Pitch;
851 }
852 break;
853 default:
854 UNREACHABLE();
855 }
856 break;
857 case D3DFMT_R5G6B5:
858 switch(getD3DFormat())
859 {
860 case D3DFMT_X8R8G8B8:
861 for(int y = 0; y < height; y++)
862 {
863 for(int x = 0; x < width; x++)
864 {
865 unsigned short rgb = ((unsigned short*)source)[x];
866 unsigned char red = (rgb & 0xF800) >> 8;
867 unsigned char green = (rgb & 0x07E0) >> 3;
868 unsigned char blue = (rgb & 0x001F) << 3;
869 dest[x + 0] = blue | (blue >> 5);
870 dest[x + 1] = green | (green >> 6);
871 dest[x + 2] = red | (red >> 5);
872 dest[x + 3] = 0xFF;
873 }
874
875 source += sourceLock.Pitch;
876 dest += destLock.Pitch;
877 }
878 break;
879 case D3DFMT_L8:
880 for(int y = 0; y < height; y++)
881 {
882 for(int x = 0; x < width; x++)
883 {
884 unsigned char red = source[x * 2 + 1] & 0xF8;
885 dest[x] = red | (red >> 5);
886 }
887
888 source += sourceLock.Pitch;
889 dest += destLock.Pitch;
890 }
891 break;
892 default:
893 UNREACHABLE();
894 }
895 break;
896 case D3DFMT_A1R5G5B5:
897 switch(getD3DFormat())
898 {
899 case D3DFMT_X8R8G8B8:
900 for(int y = 0; y < height; y++)
901 {
902 for(int x = 0; x < width; x++)
903 {
904 unsigned short argb = ((unsigned short*)source)[x];
905 unsigned char red = (argb & 0x7C00) >> 7;
906 unsigned char green = (argb & 0x03E0) >> 2;
907 unsigned char blue = (argb & 0x001F) << 3;
908 dest[x + 0] = blue | (blue >> 5);
909 dest[x + 1] = green | (green >> 5);
910 dest[x + 2] = red | (red >> 5);
911 dest[x + 3] = 0xFF;
912 }
913
914 source += sourceLock.Pitch;
915 dest += destLock.Pitch;
916 }
917 break;
918 case D3DFMT_A8R8G8B8:
919 for(int y = 0; y < height; y++)
920 {
921 for(int x = 0; x < width; x++)
922 {
923 unsigned short argb = ((unsigned short*)source)[x];
924 unsigned char red = (argb & 0x7C00) >> 7;
925 unsigned char green = (argb & 0x03E0) >> 2;
926 unsigned char blue = (argb & 0x001F) << 3;
927 unsigned char alpha = (signed short)argb >> 15;
928 dest[x + 0] = blue | (blue >> 5);
929 dest[x + 1] = green | (green >> 5);
930 dest[x + 2] = red | (red >> 5);
931 dest[x + 3] = alpha;
932 }
933
934 source += sourceLock.Pitch;
935 dest += destLock.Pitch;
936 }
937 break;
938 case D3DFMT_L8:
939 for(int y = 0; y < height; y++)
940 {
941 for(int x = 0; x < width; x++)
942 {
943 unsigned char red = source[x * 2 + 1] & 0x7C;
944 dest[x] = (red << 1) | (red >> 4);
945 }
946
947 source += sourceLock.Pitch;
948 dest += destLock.Pitch;
949 }
950 break;
951 case D3DFMT_A8L8:
952 for(int y = 0; y < height; y++)
953 {
954 for(int x = 0; x < width; x++)
955 {
956 unsigned char red = source[x * 2 + 1] & 0x7C;
957 dest[x * 2 + 0] = (red << 1) | (red >> 4);
958 dest[x * 2 + 1] = (signed char)source[x * 2 + 1] >> 7;
959 }
960
961 source += sourceLock.Pitch;
962 dest += destLock.Pitch;
963 }
964 break;
965 default:
966 UNREACHABLE();
967 }
968 break;
969 default:
970 UNREACHABLE();
971 }
972 }
973
974 unlock();
975 renderTargetData->UnlockRect();
976
977 renderTargetData->Release();
978
979 mDirty = true;
980}
981
982}