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