blob: b106659ae666d458d613b8fc07b12b32199373da [file] [log] [blame]
daniel@transgaming.com4ba24062012-12-20 20:54:24 +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// Image9.cpp: Implements the rx::Image9 class, which acts as the interface to
8// the actual underlying surfaces of a Texture.
9
10#include "libGLESv2/renderer/Image9.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#include "libGLESv2/Framebuffer.h"
19#include "libGLESv2/renderer/RenderTarget9.h"
20
21#include "libGLESv2/renderer/renderer9_utils.h"
daniel@transgaming.com12e02212012-12-20 20:55:15 +000022#include "libGLESv2/renderer/generatemip.h"
daniel@transgaming.com4ba24062012-12-20 20:54:24 +000023
24namespace rx
25{
26
daniel@transgaming.com12e02212012-12-20 20:55:15 +000027Image9::Image9()
daniel@transgaming.com4ba24062012-12-20 20:54:24 +000028{
daniel@transgaming.com12e02212012-12-20 20:55:15 +000029 mSurface = NULL;
30 mRenderer = NULL;
31
32 mD3DPool = D3DPOOL_SYSTEMMEM;
33 mD3DFormat = D3DFMT_UNKNOWN;
34}
35
36Image9::~Image9()
daniel@transgaming.com4ba24062012-12-20 20:54:24 +000037{
daniel@transgaming.com12e02212012-12-20 20:55:15 +000038 if (mSurface)
daniel@transgaming.com4ba24062012-12-20 20:54:24 +000039 {
daniel@transgaming.com12e02212012-12-20 20:55:15 +000040 mSurface->Release();
daniel@transgaming.com4ba24062012-12-20 20:54:24 +000041 }
42}
43
daniel@transgaming.com12e02212012-12-20 20:55:15 +000044void Image9::generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 *sourceSurface)
daniel@transgaming.com4ba24062012-12-20 20:54:24 +000045{
46 D3DSURFACE_DESC destDesc;
47 HRESULT result = destSurface->GetDesc(&destDesc);
48 ASSERT(SUCCEEDED(result));
49
50 D3DSURFACE_DESC sourceDesc;
51 result = sourceSurface->GetDesc(&sourceDesc);
52 ASSERT(SUCCEEDED(result));
53
54 ASSERT(sourceDesc.Format == destDesc.Format);
55 ASSERT(sourceDesc.Width == 1 || sourceDesc.Width / 2 == destDesc.Width);
56 ASSERT(sourceDesc.Height == 1 || sourceDesc.Height / 2 == destDesc.Height);
57
58 D3DLOCKED_RECT sourceLocked = {0};
59 result = sourceSurface->LockRect(&sourceLocked, NULL, D3DLOCK_READONLY);
60 ASSERT(SUCCEEDED(result));
61
62 D3DLOCKED_RECT destLocked = {0};
63 result = destSurface->LockRect(&destLocked, NULL, 0);
64 ASSERT(SUCCEEDED(result));
65
66 const unsigned char *sourceData = reinterpret_cast<const unsigned char*>(sourceLocked.pBits);
67 unsigned char *destData = reinterpret_cast<unsigned char*>(destLocked.pBits);
68
69 if (sourceData && destData)
70 {
71 switch (sourceDesc.Format)
72 {
73 case D3DFMT_L8:
74 GenerateMip<L8>(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch);
75 break;
76 case D3DFMT_A8L8:
77 GenerateMip<A8L8>(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch);
78 break;
79 case D3DFMT_A8R8G8B8:
80 case D3DFMT_X8R8G8B8:
81 GenerateMip<A8R8G8B8>(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch);
82 break;
83 case D3DFMT_A16B16G16R16F:
84 GenerateMip<A16B16G16R16F>(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch);
85 break;
86 case D3DFMT_A32B32G32R32F:
87 GenerateMip<A32B32G32R32F>(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch);
88 break;
89 default:
90 UNREACHABLE();
91 break;
92 }
93
94 destSurface->UnlockRect();
95 sourceSurface->UnlockRect();
96 }
97}
daniel@transgaming.com4ba24062012-12-20 20:54:24 +000098
99Image9 *Image9::makeImage9(Image *img)
100{
101 ASSERT(dynamic_cast<rx::Image9*>(img) != NULL);
102 return static_cast<rx::Image9*>(img);
103}
104
105void Image9::generateMipmap(Image9 *dest, Image9 *source)
106{
107 IDirect3DSurface9 *sourceSurface = source->getSurface();
108 if (sourceSurface == NULL)
109 return error(GL_OUT_OF_MEMORY);
110
111 IDirect3DSurface9 *destSurface = dest->getSurface();
daniel@transgaming.com12e02212012-12-20 20:55:15 +0000112 generateMip(destSurface, sourceSurface);
daniel@transgaming.com4ba24062012-12-20 20:54:24 +0000113
114 source->markDirty();
115}
116
117void Image9::copyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface9 *source)
118{
119 D3DLOCKED_RECT sourceLock = {0};
120 D3DLOCKED_RECT destLock = {0};
121
122 source->LockRect(&sourceLock, NULL, 0);
123 dest->LockRect(&destLock, NULL, 0);
124
125 if (sourceLock.pBits && destLock.pBits)
126 {
127 D3DSURFACE_DESC desc;
128 source->GetDesc(&desc);
129
daniel@transgaming.com9a583652012-12-20 21:07:54 +0000130 int rows = d3d9::IsCompressedFormat(desc.Format) ? desc.Height / 4 : desc.Height;
131 int bytes = d3d9::ComputeRowSize(desc.Format, desc.Width);
daniel@transgaming.com4ba24062012-12-20 20:54:24 +0000132 ASSERT(bytes <= sourceLock.Pitch && bytes <= destLock.Pitch);
133
134 for(int i = 0; i < rows; i++)
135 {
136 memcpy((char*)destLock.pBits + destLock.Pitch * i, (char*)sourceLock.pBits + sourceLock.Pitch * i, bytes);
137 }
138
139 source->UnlockRect();
140 dest->UnlockRect();
141 }
142 else UNREACHABLE();
143}
144
145bool Image9::redefine(rx::Renderer *renderer, GLint internalformat, GLsizei width, GLsizei height, bool forceRelease)
146{
147 if (mWidth != width ||
148 mHeight != height ||
149 mInternalFormat != internalformat ||
150 forceRelease)
151 {
152 mRenderer = Renderer9::makeRenderer9(renderer);
153
154 mWidth = width;
155 mHeight = height;
156 mInternalFormat = internalformat;
157 // compute the d3d format that will be used
158 mD3DFormat = mRenderer->ConvertTextureInternalFormat(internalformat);
159 mActualFormat = d3d9_gl::GetEquivalentFormat(mD3DFormat);
160
161 if (mSurface)
162 {
163 mSurface->Release();
164 mSurface = NULL;
165 }
166
167 return true;
168 }
169
170 return false;
171}
172
173void Image9::createSurface()
174{
175 if(mSurface)
176 {
177 return;
178 }
179
180 IDirect3DTexture9 *newTexture = NULL;
181 IDirect3DSurface9 *newSurface = NULL;
182 const D3DPOOL poolToUse = D3DPOOL_SYSTEMMEM;
183 const D3DFORMAT d3dFormat = getD3DFormat();
184 ASSERT(d3dFormat != D3DFMT_INTZ); // We should never get here for depth textures
185
186 if (mWidth != 0 && mHeight != 0)
187 {
188 int levelToFetch = 0;
189 GLsizei requestWidth = mWidth;
190 GLsizei requestHeight = mHeight;
191 gl::MakeValidSize(true, gl::IsCompressed(mInternalFormat), &requestWidth, &requestHeight, &levelToFetch);
192
193 IDirect3DDevice9 *device = mRenderer->getDevice(); // D3D9_REPLACE
194
195 HRESULT result = device->CreateTexture(requestWidth, requestHeight, levelToFetch + 1, 0, d3dFormat,
196 poolToUse, &newTexture, NULL);
197
198 if (FAILED(result))
199 {
200 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
201 ERR("Creating image surface failed.");
202 return error(GL_OUT_OF_MEMORY);
203 }
204
205 newTexture->GetSurfaceLevel(levelToFetch, &newSurface);
206 newTexture->Release();
207 }
208
209 mSurface = newSurface;
210 mDirty = false;
211 mD3DPool = poolToUse;
212}
213
214HRESULT Image9::lock(D3DLOCKED_RECT *lockedRect, const RECT *rect)
215{
216 createSurface();
217
218 HRESULT result = D3DERR_INVALIDCALL;
219
220 if (mSurface)
221 {
222 result = mSurface->LockRect(lockedRect, rect, 0);
223 ASSERT(SUCCEEDED(result));
224
225 mDirty = true;
226 }
227
228 return result;
229}
230
231void Image9::unlock()
232{
233 if (mSurface)
234 {
235 HRESULT result = mSurface->UnlockRect();
236 ASSERT(SUCCEEDED(result));
237 }
238}
239
240bool Image9::isRenderableFormat() const
241{
242 return TextureStorage::IsTextureFormatRenderable(getD3DFormat());
243}
244
245D3DFORMAT Image9::getD3DFormat() const
246{
247 // this should only happen if the image hasn't been redefined first
248 // which would be a bug by the caller
249 ASSERT(mD3DFormat != D3DFMT_UNKNOWN);
250
251 return mD3DFormat;
252}
253
254IDirect3DSurface9 *Image9::getSurface()
255{
256 createSurface();
257
258 return mSurface;
259}
260
261void Image9::setManagedSurface(TextureStorage2D *storage, int level)
262{
263 setManagedSurface(storage->getSurfaceLevel(level, false));
264}
265
266void Image9::setManagedSurface(TextureStorageCubeMap *storage, int face, int level)
267{
268 setManagedSurface(storage->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, false));
269}
270
271void Image9::setManagedSurface(IDirect3DSurface9 *surface)
272{
273 D3DSURFACE_DESC desc;
274 surface->GetDesc(&desc);
275 ASSERT(desc.Pool == D3DPOOL_MANAGED);
276
277 if ((GLsizei)desc.Width == mWidth && (GLsizei)desc.Height == mHeight)
278 {
279 if (mSurface)
280 {
281 copyLockableSurfaces(surface, mSurface);
282 mSurface->Release();
283 }
284
285 mSurface = surface;
286 mD3DPool = desc.Pool;
287 }
288}
289
290bool Image9::updateSurface(TextureStorage2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
291{
292 ASSERT(getSurface() != NULL);
293 return updateSurface(storage->getSurfaceLevel(level, true), xoffset, yoffset, width, height);
294}
295
296bool Image9::updateSurface(TextureStorageCubeMap *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
297{
298 ASSERT(getSurface() != NULL);
299 return updateSurface(storage->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, true), xoffset, yoffset, width, height);
300}
301
302bool Image9::updateSurface(IDirect3DSurface9 *destSurface, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
303{
304 if (!destSurface)
305 return false;
306
307 IDirect3DSurface9 *sourceSurface = getSurface();
308
309 if (sourceSurface && sourceSurface != destSurface)
310 {
311 RECT rect;
312 rect.left = xoffset;
313 rect.top = yoffset;
314 rect.right = xoffset + width;
315 rect.bottom = yoffset + height;
316
317 POINT point = {rect.left, rect.top};
318
319 IDirect3DDevice9 *device = mRenderer->getDevice(); // D3D9_REPLACE
320
321 if (mD3DPool == D3DPOOL_MANAGED)
322 {
323 D3DSURFACE_DESC desc;
324 sourceSurface->GetDesc(&desc);
325
326 IDirect3DSurface9 *surf = 0;
327 HRESULT result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surf, NULL);
328
329 if (SUCCEEDED(result))
330 {
331 copyLockableSurfaces(surf, sourceSurface);
332 result = device->UpdateSurface(surf, &rect, destSurface, &point);
333 ASSERT(SUCCEEDED(result));
334 surf->Release();
335 }
336 }
337 else
338 {
339 // UpdateSurface: source must be SYSTEMMEM, dest must be DEFAULT pools
340 HRESULT result = device->UpdateSurface(sourceSurface, &rect, destSurface, &point);
341 ASSERT(SUCCEEDED(result));
342 }
343 }
344
345 destSurface->Release();
346 return true;
347}
348
349// Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input
350// into the target pixel rectangle.
351void Image9::loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
352 GLint unpackAlignment, const void *input)
353{
354 RECT lockRect =
355 {
356 xoffset, yoffset,
357 xoffset + width, yoffset + height
358 };
359
360 D3DLOCKED_RECT locked;
361 HRESULT result = lock(&locked, &lockRect);
362 if (FAILED(result))
363 {
364 return;
365 }
366
367
368 GLsizei inputPitch = gl::ComputePitch(width, mInternalFormat, unpackAlignment);
369
370 switch (mInternalFormat)
371 {
372 case GL_ALPHA8_EXT:
373 if (gl::supportsSSE2())
374 {
375 loadAlphaDataSSE2(width, height, inputPitch, input, locked.Pitch, locked.pBits);
376 }
377 else
378 {
379 loadAlphaData(width, height, inputPitch, input, locked.Pitch, locked.pBits);
380 }
381 break;
382 case GL_LUMINANCE8_EXT:
383 loadLuminanceData(width, height, inputPitch, input, locked.Pitch, locked.pBits, getD3DFormat() == D3DFMT_L8);
384 break;
385 case GL_ALPHA32F_EXT:
386 loadAlphaFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits);
387 break;
388 case GL_LUMINANCE32F_EXT:
389 loadLuminanceFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits);
390 break;
391 case GL_ALPHA16F_EXT:
392 loadAlphaHalfFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits);
393 break;
394 case GL_LUMINANCE16F_EXT:
395 loadLuminanceHalfFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits);
396 break;
397 case GL_LUMINANCE8_ALPHA8_EXT:
398 loadLuminanceAlphaData(width, height, inputPitch, input, locked.Pitch, locked.pBits, getD3DFormat() == D3DFMT_A8L8);
399 break;
400 case GL_LUMINANCE_ALPHA32F_EXT:
401 loadLuminanceAlphaFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits);
402 break;
403 case GL_LUMINANCE_ALPHA16F_EXT:
404 loadLuminanceAlphaHalfFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits);
405 break;
406 case GL_RGB8_OES:
407 loadRGBUByteData(width, height, inputPitch, input, locked.Pitch, locked.pBits);
408 break;
409 case GL_RGB565:
410 loadRGB565Data(width, height, inputPitch, input, locked.Pitch, locked.pBits);
411 break;
412 case GL_RGBA8_OES:
413 if (gl::supportsSSE2())
414 {
415 loadRGBAUByteDataSSE2(width, height, inputPitch, input, locked.Pitch, locked.pBits);
416 }
417 else
418 {
419 loadRGBAUByteData(width, height, inputPitch, input, locked.Pitch, locked.pBits);
420 }
421 break;
422 case GL_RGBA4:
423 loadRGBA4444Data(width, height, inputPitch, input, locked.Pitch, locked.pBits);
424 break;
425 case GL_RGB5_A1:
426 loadRGBA5551Data(width, height, inputPitch, input, locked.Pitch, locked.pBits);
427 break;
428 case GL_BGRA8_EXT:
429 loadBGRAData(width, height, inputPitch, input, locked.Pitch, locked.pBits);
430 break;
431 // float textures are converted to RGBA, not BGRA, as they're stored that way in D3D
432 case GL_RGB32F_EXT:
433 loadRGBFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits);
434 break;
435 case GL_RGB16F_EXT:
436 loadRGBHalfFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits);
437 break;
438 case GL_RGBA32F_EXT:
439 loadRGBAFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits);
440 break;
441 case GL_RGBA16F_EXT:
442 loadRGBAHalfFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits);
443 break;
444 default: UNREACHABLE();
445 }
446
447 unlock();
448}
449
450void Image9::loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
451 const void *input)
452{
453 ASSERT(xoffset % 4 == 0);
454 ASSERT(yoffset % 4 == 0);
455
456 RECT lockRect = {
457 xoffset, yoffset,
458 xoffset + width, yoffset + height
459 };
460
461 D3DLOCKED_RECT locked;
462 HRESULT result = lock(&locked, &lockRect);
463 if (FAILED(result))
464 {
465 return;
466 }
467
468 GLsizei inputSize = gl::ComputeCompressedSize(width, height, mInternalFormat);
469 GLsizei inputPitch = gl::ComputeCompressedPitch(width, mInternalFormat);
470 int rows = inputSize / inputPitch;
471 for (int i = 0; i < rows; ++i)
472 {
473 memcpy((void*)((BYTE*)locked.pBits + i * locked.Pitch), (void*)((BYTE*)input + i * inputPitch), inputPitch);
474 }
475
476 unlock();
477}
478
479// This implements glCopyTex[Sub]Image2D for non-renderable internal texture formats and incomplete textures
480void Image9::copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source)
481{
482 RenderTarget9 *renderTarget = NULL;
483 IDirect3DSurface9 *surface = NULL;
484 gl::Renderbuffer *colorbuffer = source->getColorbuffer();
485
486 if (colorbuffer)
487 {
488 renderTarget = RenderTarget9::makeRenderTarget9(colorbuffer->getRenderTarget());
489 }
490
491 if (renderTarget)
492 {
493 surface = renderTarget->getSurface();
494 }
495
496 if (!surface)
497 {
498 ERR("Failed to retrieve the render target.");
499 return error(GL_OUT_OF_MEMORY);
500 }
501
502 IDirect3DDevice9 *device = mRenderer->getDevice(); // D3D9_REPLACE
503
504 IDirect3DSurface9 *renderTargetData = NULL;
505 D3DSURFACE_DESC description;
506 surface->GetDesc(&description);
507
508 HRESULT result = device->CreateOffscreenPlainSurface(description.Width, description.Height, description.Format, D3DPOOL_SYSTEMMEM, &renderTargetData, NULL);
509
510 if (FAILED(result))
511 {
512 ERR("Could not create matching destination surface.");
513 surface->Release();
514 return error(GL_OUT_OF_MEMORY);
515 }
516
517 result = device->GetRenderTargetData(surface, renderTargetData);
518
519 if (FAILED(result))
520 {
521 ERR("GetRenderTargetData unexpectedly failed.");
522 renderTargetData->Release();
523 surface->Release();
524 return error(GL_OUT_OF_MEMORY);
525 }
526
527 RECT sourceRect = {x, y, x + width, y + height};
528 RECT destRect = {xoffset, yoffset, xoffset + width, yoffset + height};
529
530 D3DLOCKED_RECT sourceLock = {0};
531 result = renderTargetData->LockRect(&sourceLock, &sourceRect, 0);
532
533 if (FAILED(result))
534 {
535 ERR("Failed to lock the source surface (rectangle might be invalid).");
536 renderTargetData->Release();
537 surface->Release();
538 return error(GL_OUT_OF_MEMORY);
539 }
540
541 D3DLOCKED_RECT destLock = {0};
542 result = lock(&destLock, &destRect);
543
544 if (FAILED(result))
545 {
546 ERR("Failed to lock the destination surface (rectangle might be invalid).");
547 renderTargetData->UnlockRect();
548 renderTargetData->Release();
549 surface->Release();
550 return error(GL_OUT_OF_MEMORY);
551 }
552
553 if (destLock.pBits && sourceLock.pBits)
554 {
555 unsigned char *source = (unsigned char*)sourceLock.pBits;
556 unsigned char *dest = (unsigned char*)destLock.pBits;
557
558 switch (description.Format)
559 {
560 case D3DFMT_X8R8G8B8:
561 case D3DFMT_A8R8G8B8:
562 switch(getD3DFormat())
563 {
564 case D3DFMT_X8R8G8B8:
565 case D3DFMT_A8R8G8B8:
566 for(int y = 0; y < height; y++)
567 {
568 memcpy(dest, source, 4 * width);
569
570 source += sourceLock.Pitch;
571 dest += destLock.Pitch;
572 }
573 break;
574 case D3DFMT_L8:
575 for(int y = 0; y < height; y++)
576 {
577 for(int x = 0; x < width; x++)
578 {
579 dest[x] = source[x * 4 + 2];
580 }
581
582 source += sourceLock.Pitch;
583 dest += destLock.Pitch;
584 }
585 break;
586 case D3DFMT_A8L8:
587 for(int y = 0; y < height; y++)
588 {
589 for(int x = 0; x < width; x++)
590 {
591 dest[x * 2 + 0] = source[x * 4 + 2];
592 dest[x * 2 + 1] = source[x * 4 + 3];
593 }
594
595 source += sourceLock.Pitch;
596 dest += destLock.Pitch;
597 }
598 break;
599 default:
600 UNREACHABLE();
601 }
602 break;
603 case D3DFMT_R5G6B5:
604 switch(getD3DFormat())
605 {
606 case D3DFMT_X8R8G8B8:
607 for(int y = 0; y < height; y++)
608 {
609 for(int x = 0; x < width; x++)
610 {
611 unsigned short rgb = ((unsigned short*)source)[x];
612 unsigned char red = (rgb & 0xF800) >> 8;
613 unsigned char green = (rgb & 0x07E0) >> 3;
614 unsigned char blue = (rgb & 0x001F) << 3;
615 dest[x + 0] = blue | (blue >> 5);
616 dest[x + 1] = green | (green >> 6);
617 dest[x + 2] = red | (red >> 5);
618 dest[x + 3] = 0xFF;
619 }
620
621 source += sourceLock.Pitch;
622 dest += destLock.Pitch;
623 }
624 break;
625 case D3DFMT_L8:
626 for(int y = 0; y < height; y++)
627 {
628 for(int x = 0; x < width; x++)
629 {
630 unsigned char red = source[x * 2 + 1] & 0xF8;
631 dest[x] = red | (red >> 5);
632 }
633
634 source += sourceLock.Pitch;
635 dest += destLock.Pitch;
636 }
637 break;
638 default:
639 UNREACHABLE();
640 }
641 break;
642 case D3DFMT_A1R5G5B5:
643 switch(getD3DFormat())
644 {
645 case D3DFMT_X8R8G8B8:
646 for(int y = 0; y < height; y++)
647 {
648 for(int x = 0; x < width; x++)
649 {
650 unsigned short argb = ((unsigned short*)source)[x];
651 unsigned char red = (argb & 0x7C00) >> 7;
652 unsigned char green = (argb & 0x03E0) >> 2;
653 unsigned char blue = (argb & 0x001F) << 3;
654 dest[x + 0] = blue | (blue >> 5);
655 dest[x + 1] = green | (green >> 5);
656 dest[x + 2] = red | (red >> 5);
657 dest[x + 3] = 0xFF;
658 }
659
660 source += sourceLock.Pitch;
661 dest += destLock.Pitch;
662 }
663 break;
664 case D3DFMT_A8R8G8B8:
665 for(int y = 0; y < height; y++)
666 {
667 for(int x = 0; x < width; x++)
668 {
669 unsigned short argb = ((unsigned short*)source)[x];
670 unsigned char red = (argb & 0x7C00) >> 7;
671 unsigned char green = (argb & 0x03E0) >> 2;
672 unsigned char blue = (argb & 0x001F) << 3;
673 unsigned char alpha = (signed short)argb >> 15;
674 dest[x + 0] = blue | (blue >> 5);
675 dest[x + 1] = green | (green >> 5);
676 dest[x + 2] = red | (red >> 5);
677 dest[x + 3] = alpha;
678 }
679
680 source += sourceLock.Pitch;
681 dest += destLock.Pitch;
682 }
683 break;
684 case D3DFMT_L8:
685 for(int y = 0; y < height; y++)
686 {
687 for(int x = 0; x < width; x++)
688 {
689 unsigned char red = source[x * 2 + 1] & 0x7C;
690 dest[x] = (red << 1) | (red >> 4);
691 }
692
693 source += sourceLock.Pitch;
694 dest += destLock.Pitch;
695 }
696 break;
697 case D3DFMT_A8L8:
698 for(int y = 0; y < height; y++)
699 {
700 for(int x = 0; x < width; x++)
701 {
702 unsigned char red = source[x * 2 + 1] & 0x7C;
703 dest[x * 2 + 0] = (red << 1) | (red >> 4);
704 dest[x * 2 + 1] = (signed char)source[x * 2 + 1] >> 7;
705 }
706
707 source += sourceLock.Pitch;
708 dest += destLock.Pitch;
709 }
710 break;
711 default:
712 UNREACHABLE();
713 }
714 break;
715 default:
716 UNREACHABLE();
717 }
718 }
719
720 unlock();
721 renderTargetData->UnlockRect();
722
723 renderTargetData->Release();
724 surface->Release();
725
726 mDirty = true;
727}
728
729}