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