ReactOS 0.4.17-dev-966-gf06eace
surface.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2009-2010 Tony Wasserka
3 * Copyright (C) 2012 Józef Kucia
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 *
19 */
20
21
22#include "d3dx9_private.h"
23
24#include "initguid.h"
25#include "ole2.h"
26#include "wincodec.h"
27
28#include "txc_dxtn.h"
29#include <assert.h>
30
32
34
35static const struct
36{
37 const GUID *wic_guid;
40{
41 { &GUID_WICPixelFormat8bppIndexed, D3DX_PIXEL_FORMAT_P8_UINT },
42 { &GUID_WICPixelFormat1bppIndexed, D3DX_PIXEL_FORMAT_P8_UINT },
43 { &GUID_WICPixelFormat4bppIndexed, D3DX_PIXEL_FORMAT_P8_UINT },
44 { &GUID_WICPixelFormat8bppGray, D3DX_PIXEL_FORMAT_L8_UNORM },
45 { &GUID_WICPixelFormat16bppBGR555, D3DX_PIXEL_FORMAT_B5G5R5X1_UNORM },
46 { &GUID_WICPixelFormat16bppBGR565, D3DX_PIXEL_FORMAT_B5G6R5_UNORM },
47 { &GUID_WICPixelFormat24bppBGR, D3DX_PIXEL_FORMAT_B8G8R8_UNORM },
48 { &GUID_WICPixelFormat32bppBGR, D3DX_PIXEL_FORMAT_B8G8R8X8_UNORM },
49 { &GUID_WICPixelFormat32bppBGRA, D3DX_PIXEL_FORMAT_B8G8R8A8_UNORM },
50 { &GUID_WICPixelFormat48bppRGB, D3DX_PIXEL_FORMAT_R16G16B16_UNORM },
51 { &GUID_WICPixelFormat64bppRGBA, D3DX_PIXEL_FORMAT_R16G16B16A16_UNORM },
52};
53
55{
56 unsigned int i;
57
58 for (i = 0; i < ARRAY_SIZE(wic_pixel_formats); i++)
59 {
62 }
63
65
66}
67
69{
71 unsigned int i;
72
73 for (i = 0; i < ARRAY_SIZE(wic_pixel_formats); i++)
74 {
76 return wic_pixel_formats[i].wic_guid;
77 }
78
79 return NULL;
80}
81
82#define DDS_PALETTE_SIZE (sizeof(PALETTEENTRY) * 256)
83
84/* dds_header.flags */
85#define DDS_CAPS 0x1
86#define DDS_HEIGHT 0x2
87#define DDS_WIDTH 0x4
88#define DDS_PITCH 0x8
89#define DDS_PIXELFORMAT 0x1000
90#define DDS_MIPMAPCOUNT 0x20000
91#define DDS_LINEARSIZE 0x80000
92#define DDS_DEPTH 0x800000
93
94/* dds_header.caps */
95#define DDSCAPS_ALPHA 0x2
96#define DDS_CAPS_COMPLEX 0x8
97#define DDSCAPS_PALETTE 0x100
98#define DDS_CAPS_TEXTURE 0x1000
99#define DDS_CAPS_MIPMAP 0x400000
100
101/* dds_header.caps2 */
102#define DDS_CAPS2_CUBEMAP 0x200
103#define DDS_CAPS2_CUBEMAP_POSITIVEX 0x400
104#define DDS_CAPS2_CUBEMAP_NEGATIVEX 0x800
105#define DDS_CAPS2_CUBEMAP_POSITIVEY 0x1000
106#define DDS_CAPS2_CUBEMAP_NEGATIVEY 0x2000
107#define DDS_CAPS2_CUBEMAP_POSITIVEZ 0x4000
108#define DDS_CAPS2_CUBEMAP_NEGATIVEZ 0x8000
109#define DDS_CAPS2_CUBEMAP_ALL_FACES ( DDS_CAPS2_CUBEMAP_POSITIVEX | DDS_CAPS2_CUBEMAP_NEGATIVEX \
110 | DDS_CAPS2_CUBEMAP_POSITIVEY | DDS_CAPS2_CUBEMAP_NEGATIVEY \
111 | DDS_CAPS2_CUBEMAP_POSITIVEZ | DDS_CAPS2_CUBEMAP_NEGATIVEZ )
112#define DDS_CAPS2_VOLUME 0x200000
113
114/* dds_pixel_format.flags */
115#define DDS_PF_ALPHA 0x1
116#define DDS_PF_ALPHA_ONLY 0x2
117#define DDS_PF_FOURCC 0x4
118#define DDS_PF_INDEXED 0x20
119#define DDS_PF_RGB 0x40
120#define DDS_PF_YUV 0x200
121#define DDS_PF_LUMINANCE 0x20000
122#define DDS_PF_BUMPLUMINANCE 0x40000
123#define DDS_PF_BUMPDUDV 0x80000
124
126{
135};
136
138{
154};
155
157 IDirect3DSurface9 **temp_surface, BOOL write)
158{
159 unsigned int width, height;
162 DWORD lock_flag;
163 HRESULT hr;
164
165 lock_flag = write ? 0 : D3DLOCK_READONLY;
166 *temp_surface = NULL;
167 if (FAILED(hr = IDirect3DSurface9_LockRect(surface, lock, surface_rect, lock_flag)))
168 {
171
172 if (surface_rect)
173 {
174 width = surface_rect->right - surface_rect->left;
175 height = surface_rect->bottom - surface_rect->top;
176 }
177 else
178 {
179 width = desc.Width;
180 height = desc.Height;
181 }
182
184 desc.Format, D3DPOOL_SYSTEMMEM, temp_surface, NULL)
186 desc.Format, D3DMULTISAMPLE_NONE, 0, TRUE, temp_surface, NULL);
187 if (FAILED(hr))
188 {
189 WARN("Failed to create temporary surface, surface %p, format %#x, "
190 "usage %#lx, pool %#x, write %#x, width %u, height %u.\n",
191 surface, desc.Format, desc.Usage, desc.Pool, write, width, height);
193 return hr;
194 }
195
196 if (write || SUCCEEDED(hr = IDirect3DDevice9_StretchRect(device, surface, surface_rect,
197 *temp_surface, NULL, D3DTEXF_NONE)))
198 hr = IDirect3DSurface9_LockRect(*temp_surface, lock, NULL, lock_flag);
199
201 if (FAILED(hr))
202 {
203 WARN("Failed to lock surface %p, write %#x, usage %#lx, pool %#x.\n",
204 surface, write, desc.Usage, desc.Pool);
205 IDirect3DSurface9_Release(*temp_surface);
206 *temp_surface = NULL;
207 return hr;
208 }
209 TRACE("Created temporary surface %p.\n", surface);
210 }
211 return hr;
212}
213
214HRESULT unlock_surface(IDirect3DSurface9 *surface, const RECT *surface_rect,
215 IDirect3DSurface9 *temp_surface, BOOL update)
216{
218 POINT surface_point;
219 HRESULT hr;
220
221 if (!temp_surface)
222 {
224 return hr;
225 }
226
227 hr = IDirect3DSurface9_UnlockRect(temp_surface);
228 if (update)
229 {
230 if (surface_rect)
231 {
232 surface_point.x = surface_rect->left;
233 surface_point.y = surface_rect->top;
234 }
235 else
236 {
237 surface_point.x = 0;
238 surface_point.y = 0;
239 }
241 if (FAILED(hr = IDirect3DDevice9_UpdateSurface(device, temp_surface, NULL, surface, &surface_point)))
242 WARN("Updating surface failed, hr %#lx, surface %p, temp_surface %p.\n",
243 hr, surface, temp_surface);
245 }
246 IDirect3DSurface9_Release(temp_surface);
247 return hr;
248}
249
250static const struct
251{
255{
256 /* DDS_PF_FOURCC. */
257 { { 32, DDS_PF_FOURCC, MAKEFOURCC('U','Y','V','Y') }, D3DX_PIXEL_FORMAT_UYVY },
258 { { 32, DDS_PF_FOURCC, MAKEFOURCC('Y','U','Y','2') }, D3DX_PIXEL_FORMAT_YUY2 },
259 { { 32, DDS_PF_FOURCC, MAKEFOURCC('R','G','B','G') }, D3DX_PIXEL_FORMAT_R8G8_B8G8_UNORM },
260 { { 32, DDS_PF_FOURCC, MAKEFOURCC('G','R','G','B') }, D3DX_PIXEL_FORMAT_G8R8_G8B8_UNORM },
261 { { 32, DDS_PF_FOURCC, MAKEFOURCC('D','X','T','1') }, D3DX_PIXEL_FORMAT_DXT1_UNORM },
262 { { 32, DDS_PF_FOURCC, MAKEFOURCC('D','X','T','2') }, D3DX_PIXEL_FORMAT_DXT2_UNORM },
263 { { 32, DDS_PF_FOURCC, MAKEFOURCC('D','X','T','3') }, D3DX_PIXEL_FORMAT_DXT3_UNORM },
264 { { 32, DDS_PF_FOURCC, MAKEFOURCC('D','X','T','4') }, D3DX_PIXEL_FORMAT_DXT4_UNORM },
265 { { 32, DDS_PF_FOURCC, MAKEFOURCC('D','X','T','5') }, D3DX_PIXEL_FORMAT_DXT5_UNORM },
266 /* These aren't actually fourcc values, they're just D3DFMT values. */
275 /* DDS_PF_RGB. */
276 { { 32, DDS_PF_RGB, 0, 8, 0xe0, 0x1c, 0x03, 0x00 }, D3DX_PIXEL_FORMAT_B2G3R3_UNORM },
277 { { 32, DDS_PF_RGB, 0, 16, 0xf800, 0x07e0, 0x001f, 0x0000 }, D3DX_PIXEL_FORMAT_B5G6R5_UNORM },
278 { { 32, DDS_PF_RGB, 0, 16, 0x7c00, 0x03e0, 0x001f, 0x0000 }, D3DX_PIXEL_FORMAT_B5G5R5X1_UNORM },
279 { { 32, DDS_PF_RGB, 0, 16, 0x0f00, 0x00f0, 0x000f, 0x0000 }, D3DX_PIXEL_FORMAT_B4G4R4X4_UNORM },
280 { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, D3DX_PIXEL_FORMAT_B8G8R8_UNORM },
281 { { 32, DDS_PF_RGB, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000 }, D3DX_PIXEL_FORMAT_B8G8R8X8_UNORM },
282 { { 32, DDS_PF_RGB, 0, 32, 0x0000ffff, 0xffff0000, 0x00000000, 0x00000000 }, D3DX_PIXEL_FORMAT_R16G16_UNORM },
283 { { 32, DDS_PF_RGB, 0, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000 }, D3DX_PIXEL_FORMAT_R8G8B8X8_UNORM },
284 { { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 16, 0x00e0, 0x001c, 0x0003, 0xff00 }, D3DX_PIXEL_FORMAT_B2G3R3A8_UNORM },
285 { { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 16, 0x7c00, 0x03e0, 0x001f, 0x8000 }, D3DX_PIXEL_FORMAT_B5G5R5A1_UNORM },
286 { { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 16, 0x0f00, 0x00f0, 0x000f, 0xf000 }, D3DX_PIXEL_FORMAT_B4G4R4A4_UNORM },
287 { { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }, D3DX_PIXEL_FORMAT_B8G8R8A8_UNORM },
288 { { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 }, D3DX_PIXEL_FORMAT_R8G8B8A8_UNORM },
289 { { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 32, 0x3ff00000, 0x000ffc00, 0x000003ff, 0xc0000000 }, D3DX_PIXEL_FORMAT_R10G10B10A2_UNORM },
290 { { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 32, 0x000003ff, 0x000ffc00, 0x3ff00000, 0xc0000000 }, D3DX_PIXEL_FORMAT_B10G10R10A2_UNORM },
291 /* DDS_PF_INDEXED. */
292 { { 32, DDS_PF_INDEXED, 0, 8 }, D3DX_PIXEL_FORMAT_P8_UINT },
293 { { 32, DDS_PF_INDEXED | DDS_PF_ALPHA, 0, 16, 0, 0, 0, 0xff00, }, D3DX_PIXEL_FORMAT_P8_UINT_A8_UNORM },
294 /* DDS_PF_LUMINANCE. */
295 { { 32, DDS_PF_LUMINANCE, 0, 8, 0x00ff }, D3DX_PIXEL_FORMAT_L8_UNORM },
296 { { 32, DDS_PF_LUMINANCE, 0, 16, 0xffff }, D3DX_PIXEL_FORMAT_L16_UNORM },
297 { { 32, DDS_PF_LUMINANCE | DDS_PF_ALPHA, 0, 8, 0x000f, 0, 0, 0x00f0 }, D3DX_PIXEL_FORMAT_L4A4_UNORM },
298 { { 32, DDS_PF_LUMINANCE | DDS_PF_ALPHA, 0, 16, 0x00ff, 0, 0, 0xff00 }, D3DX_PIXEL_FORMAT_L8A8_UNORM },
299 /* Exceptional case, A8L8 can also have 8bpp. */
300 { { 32, DDS_PF_LUMINANCE | DDS_PF_ALPHA, 0, 8, 0x00ff, 0, 0, 0xff00 }, D3DX_PIXEL_FORMAT_L8A8_UNORM },
301 /* DDS_PF_ALPHA_ONLY. */
302 { { 32, DDS_PF_ALPHA_ONLY, 0, 8, 0, 0, 0, 0xff }, D3DX_PIXEL_FORMAT_A8_UNORM },
303 /* DDS_PF_BUMPDUDV. */
304 { { 32, DDS_PF_BUMPDUDV, 0, 16, 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000 }, D3DX_PIXEL_FORMAT_U8V8_SNORM },
305 { { 32, DDS_PF_BUMPDUDV, 0, 32, 0x0000ffff, 0xffff0000, 0x00000000, 0x00000000 }, D3DX_PIXEL_FORMAT_U16V16_SNORM },
306 { { 32, DDS_PF_BUMPDUDV, 0, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 }, D3DX_PIXEL_FORMAT_U8V8W8Q8_SNORM },
307 { { 32, DDS_PF_BUMPDUDV | DDS_PF_ALPHA, 0, 32, 0x3ff00000, 0x000ffc00, 0x000003ff, 0xc0000000 }, D3DX_PIXEL_FORMAT_U10V10W10_SNORM_A2_UNORM },
308 /* DDS_PF_BUMPLUMINANCE. */
309 { { 32, DDS_PF_BUMPLUMINANCE, 0, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000 }, D3DX_PIXEL_FORMAT_U8V8_SNORM_L8X8_UNORM },
311
312static BOOL dds_pixel_format_compare(const struct dds_pixel_format *pf_a, const struct dds_pixel_format *pf_b,
313 BOOL check_rmask, BOOL check_gmask, BOOL check_bmask, BOOL check_amask)
314{
315 return pf_a->bpp == pf_b->bpp && !((check_rmask && pf_a->rmask != pf_b->rmask)
316 || (check_gmask && pf_a->gmask != pf_b->gmask) || (check_bmask && pf_a->bmask != pf_b->bmask)
317 || (check_amask && pf_a->amask != pf_b->amask));
318}
319
321{
322 uint32_t i;
323
324 TRACE("pixel_format: size %lu, flags %#lx, fourcc %#lx, bpp %lu.\n", pixel_format->size,
325 pixel_format->flags, pixel_format->fourcc, pixel_format->bpp);
326 TRACE("rmask %#lx, gmask %#lx, bmask %#lx, amask %#lx.\n", pixel_format->rmask, pixel_format->gmask,
327 pixel_format->bmask, pixel_format->amask);
328
329 for (i = 0; i < ARRAY_SIZE(dds_pixel_formats); ++i)
330 {
331 const struct dds_pixel_format *dds_pf = &dds_pixel_formats[i].dds_pixel_format;
332
333 if (pixel_format->flags != dds_pf->flags)
334 continue;
335
336 switch (pixel_format->flags & ~DDS_PF_ALPHA)
337 {
341 break;
342
343 case DDS_PF_FOURCC:
344 if (pixel_format->fourcc == dds_pf->fourcc)
345 return dds_pixel_formats[i].d3dx_pixel_format;
346 break;
347
348 case DDS_PF_INDEXED:
351 break;
352
353 case DDS_PF_RGB:
356 break;
357
358 case DDS_PF_LUMINANCE:
361 break;
362
366 break;
367
368 case DDS_PF_BUMPDUDV:
371 break;
372
373 default:
374 assert(0); /* Should not happen. */
375 break;
376 }
377 }
378
379 WARN("Unknown pixel format (flags %#lx, fourcc %#lx, bpp %lu, r %#lx, g %#lx, b %#lx, a %#lx).\n",
380 pixel_format->flags, pixel_format->fourcc, pixel_format->bpp,
381 pixel_format->rmask, pixel_format->gmask, pixel_format->bmask, pixel_format->amask);
383}
384
387{
388 const struct dds_pixel_format *pf = NULL;
389 uint32_t i;
390
391 for (i = 0; i < ARRAY_SIZE(dds_pixel_formats); ++i)
392 {
394 {
395 pf = &dds_pixel_formats[i].dds_pixel_format;
396 break;
397 }
398 }
399
400 if (!pf)
401 {
402 WARN("Unhandled format %#x.\n", d3dx_pixel_format);
403 return E_NOTIMPL;
404 }
405
406 if (pixel_format)
407 *pixel_format = *pf;
408
409 return D3D_OK;
410}
411
413{
414 size->width = max(size->width / 2, 1);
415 size->height = max(size->height / 2, 1);
416 size->depth = max(size->depth / 2, 1);
417}
418
419static const char *debug_volume(const struct volume *volume)
420{
421 if (!volume)
422 return "(null)";
423 return wine_dbg_sprintf("(%ux%ux%u)", volume->width, volume->height, volume->depth);
424}
425
427 uint32_t *pitch, uint32_t *size)
428{
429 const struct pixel_format_desc *format_desc = get_d3dx_pixel_format_info(format);
430
431 if (is_unknown_format(format_desc))
432 return E_NOTIMPL;
433
434 if (format_desc->block_width != 1 || format_desc->block_height != 1)
435 {
436 *pitch = format_desc->block_byte_count
437 * max(1, (width + format_desc->block_width - 1) / format_desc->block_width);
438 *size = *pitch
439 * max(1, (height + format_desc->block_height - 1) / format_desc->block_height);
440 }
441 else
442 {
443 *pitch = width * format_desc->bytes_per_pixel;
444 *size = *pitch * height;
445 }
446
447 return D3D_OK;
448}
449
451 uint32_t mip_levels)
452{
453 uint32_t layer_size, row_pitch, slice_pitch, i;
454 struct volume dims = { width, height, depth };
455
456 layer_size = 0;
457 for (i = 0; i < mip_levels; ++i)
458 {
459 if (FAILED(d3dx_calculate_pixels_size(format, dims.width, dims.height, &row_pitch, &slice_pitch)))
460 return 0;
461 layer_size += slice_pitch * dims.depth;
463 }
464
465 return layer_size;
466}
467
469 enum d3dx_pixel_format_id format, const struct volume *size, uint32_t mip_levels)
470{
471 HRESULT hr;
472
473 memset(header, 0, sizeof(*header));
474 header->signature = MAKEFOURCC('D','D','S',' ');
475 /* The signature is not really part of the DDS header. */
476 header->size = sizeof(*header) - FIELD_OFFSET(struct dds_header, size);
478 if (FAILED(hr))
479 return hr;
480
482 header->height = size->height;
483 header->width = size->width;
484 header->caps = DDS_CAPS_TEXTURE;
485 if (header->pixel_format.flags & DDS_PF_ALPHA || header->pixel_format.flags & DDS_PF_ALPHA_ONLY)
486 header->caps |= DDSCAPS_ALPHA;
487 if (header->pixel_format.flags & DDS_PF_INDEXED)
488 header->caps |= DDSCAPS_PALETTE;
489
490 return D3D_OK;
491}
492
493static HRESULT d3dx_save_pixels_to_memory(struct d3dx_pixels *src_pixels, const struct pixel_format_desc *src_fmt_desc,
494 D3DXIMAGE_FILEFORMAT file_format, ID3DXBuffer **dst_buffer)
495{
496 enum d3dx_pixel_format_id dst_format = src_fmt_desc->format;
497 const struct pixel_format_desc *dst_fmt_desc;
498 uint32_t dst_row_pitch, dst_slice_pitch;
499 struct d3dx_pixels dst_pixels;
502 HRESULT hr;
503
504 *dst_buffer = NULL;
505 switch (file_format)
506 {
507 case D3DXIFF_DDS:
508 {
509 struct dds_header *header;
510 uint32_t header_size;
511
513 if (FAILED(hr))
514 return hr;
515
517 hr = d3dx_calculate_pixels_size(dst_format, src_pixels->size.width, src_pixels->size.height, &dst_row_pitch,
518 &dst_slice_pitch);
519 if (FAILED(hr))
520 return hr;
521
522 header_size = is_index_format(dst_fmt_desc) ? sizeof(*header) + DDS_PALETTE_SIZE : sizeof(*header);
523 hr = D3DXCreateBuffer(dst_slice_pitch + header_size, &buffer);
524 if (FAILED(hr))
525 return hr;
526
530 if (FAILED(hr))
531 goto exit;
532 if (is_index_format(dst_fmt_desc))
535 break;
536 }
537
538 default:
539 assert(0 && "Unexpected file format.");
540 return E_FAIL;
541 }
542
543 if (src_pixels->size.width != 0 && src_pixels->size.height != 0)
544 {
545 const RECT dst_rect = { 0, 0, src_pixels->size.width, src_pixels->size.height };
546
547 set_d3dx_pixels(&dst_pixels, pixels, dst_row_pitch, dst_slice_pitch, src_pixels->palette, src_pixels->size.width,
548 src_pixels->size.height, src_pixels->size.depth, &dst_rect);
549
550 hr = d3dx_load_pixels_from_pixels(&dst_pixels, dst_fmt_desc, src_pixels, src_fmt_desc, D3DX_FILTER_NONE, 0);
551 if (FAILED(hr))
552 goto exit;
553 }
554
555 *dst_buffer = buffer;
556exit:
557 if (*dst_buffer != buffer)
559 return hr;
560}
561
563 const PALETTEENTRY *src_palette, const RECT *src_rect)
564{
565 const struct pixel_format_desc *src_fmt_desc;
566 D3DSURFACE_DESC src_surface_desc;
567 IDirect3DSurface9 *temp_surface;
568 struct d3dx_pixels src_pixels;
569 D3DLOCKED_RECT locked_rect;
571 RECT src_rect_temp;
572 HRESULT hr;
573
574 IDirect3DSurface9_GetDesc(src_surface, &src_surface_desc);
575 src_fmt_desc = get_format_info(src_surface_desc.Format);
576 if (is_unknown_format(src_fmt_desc))
577 return E_NOTIMPL;
578
579 if (!src_palette && is_index_format(src_fmt_desc))
580 {
581 FIXME("Default palette unimplemented.\n");
582 return E_NOTIMPL;
583 }
584
585 if (src_rect)
586 {
587 if (src_rect->left > src_rect->right || src_rect->right > src_surface_desc.Width
588 || src_rect->top > src_rect->bottom || src_rect->bottom > src_surface_desc.Height
589 || src_rect->left < 0 || src_rect->top < 0)
590 {
591 WARN("Invalid src_rect specified.\n");
592 return D3DERR_INVALIDCALL;
593 }
594 }
595 else
596 {
597 SetRect(&src_rect_temp, 0, 0, src_surface_desc.Width, src_surface_desc.Height);
598 src_rect = &src_rect_temp;
599 }
600
601 hr = lock_surface(src_surface, NULL, &locked_rect, &temp_surface, FALSE);
602 if (FAILED(hr))
603 return hr;
604
605 hr = d3dx_pixels_init(locked_rect.pBits, locked_rect.Pitch, 0, src_palette, src_fmt_desc->format,
606 src_rect->left, src_rect->top, src_rect->right, src_rect->bottom, 0, 1, &src_pixels);
607 if (FAILED(hr))
608 {
609 unlock_surface(src_surface, NULL, temp_surface, FALSE);
610 return hr;
611 }
612
613 hr = d3dx_save_pixels_to_memory(&src_pixels, src_fmt_desc, D3DXIFF_DDS, &buffer);
614 if (FAILED(hr))
615 {
616 unlock_surface(src_surface, NULL, temp_surface, FALSE);
617 return hr;
618 }
619
620 hr = unlock_surface(src_surface, NULL, temp_surface, FALSE);
621 if (FAILED(hr))
622 {
624 return hr;
625 }
626
627 *dst_buffer = buffer;
628 return D3D_OK;
629}
630
631static const uint8_t bmp_file_signature[] = { 'B', 'M' };
632static const uint8_t jpg_file_signature[] = { 0xff, 0xd8 };
633static const uint8_t png_file_signature[] = { 0x89, 'P', 'N', 'G', 0x0d, 0x0a, 0x1a, 0x0a };
634static const uint8_t dds_file_signature[] = { 'D', 'D', 'S', ' ' };
635static const uint8_t ppm_plain_file_signature[] = { 'P', '3' };
636static const uint8_t ppm_raw_file_signature[] = { 'P', '6' };
637static const uint8_t hdr_file_signature[] = { '#', '?', 'R', 'A', 'D', 'I', 'A', 'N', 'C', 'E', '\n' };
638static const uint8_t pfm_color_file_signature[] = { 'P', 'F' };
639static const uint8_t pfm_gray_file_signature[] = { 'P', 'f' };
640
641/*
642 * If none of these match, the file is either DIB, TGA, or something we don't
643 * support.
644 */
646{
650};
651
653{
663};
664
665static BOOL d3dx_get_image_file_format_from_file_signature(const void *src_data, uint32_t src_data_size,
666 D3DXIMAGE_FILEFORMAT *out_iff)
667{
668 unsigned int i;
669
670 for (i = 0; i < ARRAY_SIZE(file_format_signatures); ++i)
671 {
673
674 if ((src_data_size >= signature->file_signature_len)
675 && !memcmp(src_data, signature->file_signature, signature->file_signature_len))
676 {
677 *out_iff = signature->image_file_format;
678 return TRUE;
679 }
680 }
681
682 return FALSE;
683}
684
685static HRESULT d3dx_initialize_image_from_dds(const void *src_data, uint32_t src_data_size,
686 struct d3dx_image *image, uint32_t starting_mip_level)
687{
688 uint32_t expected_src_data_size, header_size;
689 const struct dds_header *header = src_data;
690 BOOL is_indexed_fmt;
691 HRESULT hr;
692
693 if (src_data_size < sizeof(*header) || header->pixel_format.size != sizeof(header->pixel_format))
694 return D3DXERR_INVALIDDATA;
695
696 TRACE("File type is DDS.\n");
697 is_indexed_fmt = !!(header->pixel_format.flags & DDS_PF_INDEXED);
698 header_size = is_indexed_fmt ? sizeof(*header) + DDS_PALETTE_SIZE : sizeof(*header);
699
700 set_volume_struct(&image->size, header->width, header->height, 1);
701 image->mip_levels = header->miplevels ? header->miplevels : 1;
703 image->layer_count = 1;
704
705 if (image->format == D3DX_PIXEL_FORMAT_COUNT)
706 return D3DXERR_INVALIDDATA;
707
708 TRACE("Pixel format is %#x.\n", image->format);
709 if (header->flags & DDS_DEPTH)
710 {
711 image->size.depth = max(header->depth, 1);
712 image->resource_type = D3DRTYPE_VOLUMETEXTURE;
713 }
714 else if (header->caps2 & DDS_CAPS2_CUBEMAP)
715 {
717 {
718 WARN("Tried to load a partial cubemap DDS file.\n");
719 return D3DXERR_INVALIDDATA;
720 }
721
722 image->layer_count = 6;
723 image->resource_type = D3DRTYPE_CUBETEXTURE;
724 }
725 else
726 image->resource_type = D3DRTYPE_TEXTURE;
727
728 image->layer_pitch = d3dx_calculate_layer_pixels_size(image->format, image->size.width, image->size.height,
729 image->size.depth, image->mip_levels);
730 if (!image->layer_pitch)
731 return D3DXERR_INVALIDDATA;
732 expected_src_data_size = (image->layer_pitch * image->layer_count) + header_size;
733 if (src_data_size < expected_src_data_size)
734 {
735 WARN("File is too short %u, expected at least %u bytes.\n", src_data_size, expected_src_data_size);
736 return D3DXERR_INVALIDDATA;
737 }
738
739 image->palette = (is_indexed_fmt) ? (PALETTEENTRY *)(((uint8_t *)src_data) + sizeof(*header)) : NULL;
740 image->pixels = ((BYTE *)src_data) + header_size;
741 image->image_file_format = D3DXIFF_DDS;
742 if (starting_mip_level && (image->mip_levels > 1))
743 {
744 uint32_t i, row_pitch, slice_pitch, initial_mip_levels;
745 const struct volume initial_size = image->size;
746
747 initial_mip_levels = image->mip_levels;
748 for (i = 0; i < starting_mip_level; i++)
749 {
750 hr = d3dx_calculate_pixels_size(image->format, image->size.width, image->size.height, &row_pitch, &slice_pitch);
751 if (FAILED(hr))
752 return hr;
753
754 image->pixels += slice_pitch * image->size.depth;
756 if (--image->mip_levels == 1)
757 break;
758 }
759
760 TRACE("Requested starting mip level %u, actual starting mip level is %u (of %u total in image).\n",
761 starting_mip_level, (initial_mip_levels - image->mip_levels), initial_mip_levels);
762 TRACE("Original dimensions %s, new dimensions %s.\n", debug_volume(&initial_size), debug_volume(&image->size));
763 }
764
765 return D3D_OK;
766}
767
768static BOOL convert_dib_to_bmp(const void **data, unsigned int *size)
769{
770 ULONG header_size;
771 ULONG count = 0;
774 BYTE *new_data;
776
777 if ((*size < 4) || (*size < (header_size = *(ULONG*)*data)))
778 return FALSE;
779
780 if ((header_size == sizeof(BITMAPINFOHEADER)) ||
781 (header_size == sizeof(BITMAPV4HEADER)) ||
782 (header_size == sizeof(BITMAPV5HEADER)) ||
783 (header_size == 64 /* sizeof(BITMAPCOREHEADER2) */))
784 {
785 /* All structures begin with the same memory layout as BITMAPINFOHEADER */
786 BITMAPINFOHEADER *info_header = (BITMAPINFOHEADER*)*data;
787 count = info_header->biClrUsed;
788
789 if (!count && info_header->biBitCount <= 8)
790 count = 1 << info_header->biBitCount;
791
792 offset = sizeof(BITMAPFILEHEADER) + header_size + sizeof(RGBQUAD) * count;
793
794 /* For BITMAPINFOHEADER with BI_BITFIELDS compression, there are 3 additional color masks after header */
795 if ((info_header->biSize == sizeof(BITMAPINFOHEADER)) && (info_header->biCompression == BI_BITFIELDS))
796 offset += 3 * sizeof(DWORD);
797 }
798 else if (header_size == sizeof(BITMAPCOREHEADER))
799 {
800 BITMAPCOREHEADER *core_header = (BITMAPCOREHEADER*)*data;
801
802 if (core_header->bcBitCount <= 8)
803 count = 1 << core_header->bcBitCount;
804
805 offset = sizeof(BITMAPFILEHEADER) + header_size + sizeof(RGBTRIPLE) * count;
806 }
807 else
808 {
809 return FALSE;
810 }
811
812 TRACE("Converting DIB file to BMP\n");
813
814 new_size = *size + sizeof(BITMAPFILEHEADER);
815 new_data = malloc(new_size);
816 CopyMemory(new_data + sizeof(BITMAPFILEHEADER), *data, *size);
817
818 /* Add BMP header */
819 header = (BITMAPFILEHEADER*)new_data;
820 header->bfType = 0x4d42; /* BM */
821 header->bfSize = new_size;
822 header->bfReserved1 = 0;
823 header->bfReserved2 = 0;
824 header->bfOffBits = offset;
825
826 /* Update input data */
827 *data = new_data;
828 *size = new_size;
829
830 return TRUE;
831}
832
833/* windowscodecs always returns xRGB, but we should return ARGB if and only if
834 * at least one pixel has a non-zero alpha component. */
836{
837 unsigned int size, i;
838 BYTE *buffer;
839 HRESULT hr;
840
841 if (image->format != D3DX_PIXEL_FORMAT_B8G8R8X8_UNORM || image->image_file_format != D3DXIFF_BMP)
842 return FALSE;
843
844 size = image->size.width * image->size.height * 4;
845 if (!(buffer = malloc(size)))
846 return FALSE;
847
848 if (FAILED(hr = IWICBitmapFrameDecode_CopyPixels(frame, NULL, image->size.width * 4, size, buffer)))
849 {
850 ERR("Failed to copy pixels, hr %#lx.\n", hr);
851 free(buffer);
852 return FALSE;
853 }
854
855 for (i = 0; i < image->size.width * image->size.height; ++i)
856 {
857 if (buffer[i * 4 + 3])
858 {
859 free(buffer);
860 return TRUE;
861 }
862 }
863
864 free(buffer);
865 return FALSE;
866}
867
869{
872};
873
875{
876 switch (iff)
877 {
878 case D3DXIFF_BMP: return &GUID_ContainerFormatBmp;
879 case D3DXIFF_JPG: return &GUID_ContainerFormatJpeg;
880 case D3DXIFF_PNG: return &GUID_ContainerFormatPng;
881 default:
882 assert(0); /* Shouldn't happen. */
883 return NULL;
884 }
885}
886
888{
889 switch (format)
890 {
891#define FMT_TO_STR(format) case format: return #format
901#undef FMT_TO_STR
902 default:
903 return "unrecognized";
904 }
905}
906
908 IWICImagingFactory *wic_factory, IWICBitmapFrameDecode *bitmap_frame)
909{
910 const struct pixel_format_desc *fmt_desc;
911 uint32_t row_pitch, slice_pitch;
912 IWICPalette *wic_palette = NULL;
914 WICColor *colors = NULL;
915 BYTE *buffer = NULL;
916 HRESULT hr;
917
918 fmt_desc = get_d3dx_pixel_format_info(image->format);
919 hr = d3dx_calculate_pixels_size(image->format, image->size.width, image->size.height, &row_pitch, &slice_pitch);
920 if (FAILED(hr))
921 return hr;
922
923 /* Allocate a buffer for our image. */
924 if (!(buffer = malloc(slice_pitch)))
925 return E_OUTOFMEMORY;
926
927 hr = IWICBitmapFrameDecode_CopyPixels(bitmap_frame, NULL, row_pitch, slice_pitch, buffer);
928 if (FAILED(hr))
929 {
930 free(buffer);
931 return hr;
932 }
933
934 if (is_index_format(fmt_desc))
935 {
936 uint32_t nb_colors, i;
937
938 hr = IWICImagingFactory_CreatePalette(wic_factory, &wic_palette);
939 if (FAILED(hr))
940 goto exit;
941
942 hr = IWICBitmapFrameDecode_CopyPalette(bitmap_frame, wic_palette);
943 if (FAILED(hr))
944 goto exit;
945
946 hr = IWICPalette_GetColorCount(wic_palette, &nb_colors);
947 if (FAILED(hr))
948 goto exit;
949
950 colors = malloc(nb_colors * sizeof(colors[0]));
951 palette = malloc(nb_colors * sizeof(palette[0]));
952 if (!colors || !palette)
953 {
955 goto exit;
956 }
957
958 hr = IWICPalette_GetColors(wic_palette, nb_colors, colors, &nb_colors);
959 if (FAILED(hr))
960 goto exit;
961
962 /* Convert colors from WICColor (ARGB) to PALETTEENTRY (ABGR) */
963 for (i = 0; i < nb_colors; i++)
964 {
965 palette[i].peRed = (colors[i] >> 16) & 0xff;
966 palette[i].peGreen = (colors[i] >> 8) & 0xff;
967 palette[i].peBlue = colors[i] & 0xff;
968 palette[i].peFlags = (colors[i] >> 24) & 0xff; /* peFlags is the alpha component in DX8 and higher */
969 }
970 }
971
972 image->image_buf = image->pixels = buffer;
973 image->image_palette = image->palette = palette;
974
975exit:
976 free(colors);
977 if (image->image_buf != buffer)
978 free(buffer);
979 if (image->image_palette != palette)
980 free(palette);
981 if (wic_palette)
982 IWICPalette_Release(wic_palette);
983
984 return hr;
985}
986
987static HRESULT d3dx_initialize_image_from_wic(const void *src_data, uint32_t src_data_size,
989{
990 const GUID *container_format_guid = d3dx_file_format_to_wic_container_guid(d3dx_file_format);
991 IWICBitmapFrameDecode *bitmap_frame = NULL;
992 IWICBitmapDecoder *bitmap_decoder = NULL;
993 IWICImagingFactory *wic_factory;
995 IWICStream *wic_stream = NULL;
996 uint32_t frame_count = 0;
997 HRESULT hr;
998
999 hr = WICCreateImagingFactory_Proxy(WINCODEC_SDK_VERSION, &wic_factory);
1000 if (FAILED(hr))
1001 return hr;
1002
1003 hr = IWICImagingFactory_CreateDecoder(wic_factory, container_format_guid, NULL, &bitmap_decoder);
1004 if (FAILED(hr))
1005 goto exit;
1006
1007 hr = IWICImagingFactory_CreateStream(wic_factory, &wic_stream);
1008 if (FAILED(hr))
1009 goto exit;
1010
1011 hr = IWICStream_InitializeFromMemory(wic_stream, (BYTE *)src_data, src_data_size);
1012 if (FAILED(hr))
1013 goto exit;
1014
1015 hr = IWICBitmapDecoder_Initialize(bitmap_decoder, (IStream *)wic_stream, 0);
1016 if (FAILED(hr))
1017 goto exit;
1018
1019 hr = IWICBitmapDecoder_GetFrameCount(bitmap_decoder, &frame_count);
1020 if (FAILED(hr) || (SUCCEEDED(hr) && !frame_count))
1021 {
1023 goto exit;
1024 }
1025
1026 image->image_file_format = d3dx_file_format;
1027 hr = IWICBitmapDecoder_GetFrame(bitmap_decoder, 0, &bitmap_frame);
1028 if (FAILED(hr))
1029 goto exit;
1030
1031 hr = IWICBitmapFrameDecode_GetSize(bitmap_frame, &image->size.width, &image->size.height);
1032 if (FAILED(hr))
1033 goto exit;
1034
1035 hr = IWICBitmapFrameDecode_GetPixelFormat(bitmap_frame, &pixel_format);
1036 if (FAILED(hr))
1037 goto exit;
1038
1040 if (image->format == D3DX_PIXEL_FORMAT_COUNT)
1041 {
1042 WARN("Unsupported pixel format %s.\n", debugstr_guid(&pixel_format));
1044 goto exit;
1045 }
1046
1047 if (image_is_argb(bitmap_frame, image))
1049
1050 if (!(flags & D3DX_IMAGE_INFO_ONLY))
1051 {
1052 hr = d3dx_image_wic_frame_decode(image, wic_factory, bitmap_frame);
1053 if (FAILED(hr))
1054 goto exit;
1055 }
1056
1057 image->size.depth = 1;
1058 image->mip_levels = 1;
1059 image->layer_count = 1;
1060 image->resource_type = D3DRTYPE_TEXTURE;
1061
1062exit:
1063 if (bitmap_frame)
1064 IWICBitmapFrameDecode_Release(bitmap_frame);
1065 if (bitmap_decoder)
1066 IWICBitmapDecoder_Release(bitmap_decoder);
1067 if (wic_stream)
1068 IWICStream_Release(wic_stream);
1069 IWICImagingFactory_Release(wic_factory);
1070
1071 return hr;
1072}
1073
1075{
1076 switch (bpp)
1077 {
1078 case 15: return D3DX_PIXEL_FORMAT_B5G5R5X1_UNORM;
1079 case 16: return D3DX_PIXEL_FORMAT_B5G5R5A1_UNORM;
1080 case 24: return D3DX_PIXEL_FORMAT_B8G8R8_UNORM;
1081 case 32: return D3DX_PIXEL_FORMAT_B8G8R8A8_UNORM;
1082 default:
1083 WARN("Unhandled bpp %u for targa.\n", bpp);
1085 }
1086}
1087
1088#define IMAGETYPE_COLORMAPPED 1
1089#define IMAGETYPE_TRUECOLOR 2
1090#define IMAGETYPE_GRAYSCALE 3
1091#define IMAGETYPE_MASK 0x07
1092#define IMAGETYPE_RLE 8
1093
1094#define IMAGE_RIGHTTOLEFT 0x10
1095#define IMAGE_TOPTOBOTTOM 0x20
1096
1097#include "pshpack1.h"
1099{
1112};
1113#include "poppack.h"
1114
1115static HRESULT d3dx_image_tga_rle_decode_row(const uint8_t **src, uint32_t src_bytes_left, uint32_t row_width,
1116 uint32_t bytes_per_pixel, uint8_t *dst_row)
1117{
1118 const uint8_t *src_ptr = *src;
1119 uint32_t pixel_count = 0;
1120
1121 while (pixel_count != row_width)
1122 {
1123 uint32_t rle_count = (src_ptr[0] & 0x7f) + 1;
1124 uint32_t rle_packet_size = 1;
1125
1126 rle_packet_size += (src_ptr[0] & 0x80) ? bytes_per_pixel : (bytes_per_pixel * rle_count);
1127 if ((rle_packet_size > src_bytes_left) || (pixel_count + rle_count) > row_width)
1128 return D3DXERR_INVALIDDATA;
1129
1130 if (src_ptr[0] & 0x80)
1131 {
1132 uint32_t i;
1133
1134 for (i = 0; i < rle_count; ++i)
1135 memcpy(&dst_row[(pixel_count + i) * bytes_per_pixel], src_ptr + 1, bytes_per_pixel);
1136 }
1137 else
1138 {
1139 memcpy(&dst_row[pixel_count * bytes_per_pixel], src_ptr + 1, rle_packet_size - 1);
1140 }
1141
1142 src_ptr += rle_packet_size;
1143 src_bytes_left -= rle_packet_size;
1144 pixel_count += rle_count;
1145 if (!src_bytes_left && pixel_count != row_width)
1146 return D3DXERR_INVALIDDATA;
1147 }
1148
1149 *src = src_ptr;
1150 return D3D_OK;
1151}
1152
1153static HRESULT d3dx_image_tga_decode(const void *src_data, uint32_t src_data_size, uint32_t src_header_size,
1154 struct d3dx_image *image)
1155{
1156 const struct pixel_format_desc *fmt_desc = get_d3dx_pixel_format_info(image->format);
1157 const struct tga_header *header = (const struct tga_header *)src_data;
1158 const BOOL right_to_left = !!(header->image_descriptor & IMAGE_RIGHTTOLEFT);
1159 const BOOL bottom_to_top = !(header->image_descriptor & IMAGE_TOPTOBOTTOM);
1160 const BOOL is_rle = !!(header->image_type & IMAGETYPE_RLE);
1161 uint8_t *img_buf = NULL, *src_row = NULL;
1162 uint32_t row_pitch, slice_pitch, i;
1164 const uint8_t *src_pos;
1165 HRESULT hr;
1166
1167 hr = d3dx_calculate_pixels_size(image->format, image->size.width, image->size.height, &row_pitch, &slice_pitch);
1168 if (FAILED(hr))
1169 return hr;
1170
1171 /* File is too small. */
1172 if (!is_rle && (src_header_size + slice_pitch) > src_data_size)
1173 return D3DXERR_INVALIDDATA;
1174
1175 if (image->format == D3DX_PIXEL_FORMAT_P8_UINT)
1176 {
1177 const uint8_t *src_palette = ((const uint8_t *)src_data) + sizeof(*header) + header->id_length;
1178 const struct volume image_map_size = { header->color_map_length, 1, 1 };
1179 uint32_t src_row_pitch, src_slice_pitch, dst_row_pitch, dst_slice_pitch;
1180 const struct pixel_format_desc *src_desc, *dst_desc;
1181
1182 if (!(palette = malloc(sizeof(*palette) * 256)))
1183 return E_OUTOFMEMORY;
1184
1185 /*
1186 * Convert from a TGA colormap to PALETTEENTRY. TGA is BGRA,
1187 * PALETTEENTRY is RGBA.
1188 */
1189 src_desc = get_d3dx_pixel_format_info(d3dx_get_tga_format_for_bpp(header->color_map_entrysize));
1190 hr = d3dx_calculate_pixels_size(src_desc->format, header->color_map_length, 1, &src_row_pitch, &src_slice_pitch);
1191 if (FAILED(hr))
1192 goto exit;
1193
1194 dst_desc = get_format_info(D3DFMT_A8B8G8R8);
1195 d3dx_calculate_pixels_size(dst_desc->format, 256, 1, &dst_row_pitch, &dst_slice_pitch);
1196 convert_argb_pixels(src_palette, src_row_pitch, src_slice_pitch, &image_map_size, src_desc, (BYTE *)palette,
1197 dst_row_pitch, dst_slice_pitch, &image_map_size, dst_desc, 0, NULL);
1198
1199 /* Initialize unused palette entries to 0xff. */
1200 if (header->color_map_length < 256)
1201 memset(&palette[header->color_map_length], 0xff, sizeof(*palette) * (256 - header->color_map_length));
1202 }
1203
1204 if (!is_rle && !bottom_to_top && !right_to_left)
1205 {
1206 image->pixels = (uint8_t *)src_data + src_header_size;
1207 image->image_palette = image->palette = palette;
1208 return D3D_OK;
1209 }
1210
1211 if (!(img_buf = malloc(slice_pitch)))
1212 {
1213 hr = E_OUTOFMEMORY;
1214 goto exit;
1215 }
1216
1217 /* Allocate an extra row to use as a temporary buffer. */
1218 if (is_rle)
1219 {
1220 if (!(src_row = malloc(row_pitch)))
1221 {
1222 hr = E_OUTOFMEMORY;
1223 goto exit;
1224 }
1225 }
1226
1227 src_pos = (const uint8_t *)src_data + src_header_size;
1228 for (i = 0; i < image->size.height; ++i)
1229 {
1230 const uint32_t dst_row_idx = bottom_to_top ? (image->size.height - i - 1) : i;
1231 uint8_t *dst_row = img_buf + (dst_row_idx * row_pitch);
1232
1233 if (is_rle)
1234 {
1235 hr = d3dx_image_tga_rle_decode_row(&src_pos, src_data_size - (src_pos - (const uint8_t *)src_data),
1236 image->size.width, fmt_desc->bytes_per_pixel, src_row);
1237 if (FAILED(hr))
1238 goto exit;
1239 }
1240 else
1241 {
1242 src_row = (uint8_t *)src_pos;
1243 src_pos += row_pitch;
1244 }
1245
1246 if (right_to_left)
1247 {
1248 const uint8_t *src_pixel = &src_row[((image->size.width - 1)) * fmt_desc->bytes_per_pixel];
1249 uint8_t *dst_pixel = dst_row;
1250 uint32_t j;
1251
1252 for (j = 0; j < image->size.width; ++j)
1253 {
1254 memcpy(dst_pixel, src_pixel, fmt_desc->bytes_per_pixel);
1255 src_pixel -= fmt_desc->bytes_per_pixel;
1256 dst_pixel += fmt_desc->bytes_per_pixel;
1257 }
1258 }
1259 else
1260 {
1261 memcpy(dst_row, src_row, row_pitch);
1262 }
1263 }
1264
1265 image->image_buf = image->pixels = img_buf;
1266 image->image_palette = image->palette = palette;
1267
1268exit:
1269 if (is_rle)
1270 free(src_row);
1271 if (img_buf && (image->image_buf != img_buf))
1272 free(img_buf);
1273 if (palette && (image->image_palette != palette))
1274 free(palette);
1275
1276 return hr;
1277}
1278
1279static HRESULT d3dx_initialize_image_from_tga(const void *src_data, uint32_t src_data_size, struct d3dx_image *image,
1281{
1282 const struct tga_header *header = (const struct tga_header *)src_data;
1283 uint32_t expected_header_size = sizeof(*header);
1284
1285 if (src_data_size < sizeof(*header))
1286 return D3DXERR_INVALIDDATA;
1287
1288 expected_header_size += header->id_length;
1289 expected_header_size += header->color_map_length * ((header->color_map_entrysize + 7) / CHAR_BIT);
1290 if (src_data_size < expected_header_size)
1291 return D3DXERR_INVALIDDATA;
1292
1293 if (header->color_map_type && ((header->color_map_type > 1) || (!header->color_map_length)
1294 || (d3dx_get_tga_format_for_bpp(header->color_map_entrysize) == D3DX_PIXEL_FORMAT_COUNT)))
1295 return D3DXERR_INVALIDDATA;
1296
1297 switch (header->image_type & IMAGETYPE_MASK)
1298 {
1300 if (header->depth != 8 || !header->color_map_type)
1301 return D3DXERR_INVALIDDATA;
1303 break;
1304
1307 return D3DXERR_INVALIDDATA;
1308 break;
1309
1311 if (header->depth != 8)
1312 return D3DXERR_INVALIDDATA;
1314 break;
1315
1316 default:
1317 return D3DXERR_INVALIDDATA;
1318 }
1319
1320 set_volume_struct(&image->size, header->width, header->height, 1);
1321 image->mip_levels = 1;
1322 image->layer_count = 1;
1323 image->resource_type = D3DRTYPE_TEXTURE;
1324 image->image_file_format = D3DXIFF_TGA;
1325
1326 if (!(flags & D3DX_IMAGE_INFO_ONLY))
1327 return d3dx_image_tga_decode(src_data, src_data_size, expected_header_size, image);
1328
1329 return D3D_OK;
1330}
1331
1332HRESULT d3dx_image_init(const void *src_data, uint32_t src_data_size, struct d3dx_image *image,
1333 uint32_t starting_mip_level, uint32_t flags)
1334{
1336 HRESULT hr;
1337
1338 if (!src_data || !src_data_size || !image)
1339 return D3DERR_INVALIDCALL;
1340
1341 memset(image, 0, sizeof(*image));
1342 if (!d3dx_get_image_file_format_from_file_signature(src_data, src_data_size, &iff))
1343 {
1344 uint32_t src_image_size = src_data_size;
1345 const void *src_image = src_data;
1346
1347 if (convert_dib_to_bmp(&src_image, &src_image_size))
1348 {
1349 hr = d3dx_image_init(src_image, src_image_size, image, starting_mip_level, flags);
1350 free((void *)src_image);
1351 if (SUCCEEDED(hr))
1352 image->image_file_format = D3DXIFF_DIB;
1353 return hr;
1354 }
1355
1356 /* Last resort, try TGA. */
1357 return d3dx_initialize_image_from_tga(src_data, src_data_size, image, flags);
1358 }
1359
1360 switch (iff)
1361 {
1362 case D3DXIFF_BMP:
1363 case D3DXIFF_JPG:
1364 case D3DXIFF_PNG:
1365 hr = d3dx_initialize_image_from_wic(src_data, src_data_size, image, iff, flags);
1366 break;
1367
1368 case D3DXIFF_DDS:
1369 hr = d3dx_initialize_image_from_dds(src_data, src_data_size, image, starting_mip_level);
1370 break;
1371
1372 case D3DXIFF_PPM:
1373 case D3DXIFF_HDR:
1374 case D3DXIFF_PFM:
1375 WARN("Unsupported file format %s.\n", debug_d3dx_image_file_format(iff));
1376 hr = E_NOTIMPL;
1377 break;
1378
1380 ERR("Unrecognized file format.\n");
1382 break;
1383
1384 default:
1385 assert(0);
1386 return E_FAIL;
1387 }
1388
1389 return hr;
1390}
1391
1393{
1394 free(image->image_buf);
1395 free(image->image_palette);
1396}
1397
1399 struct d3dx_pixels *pixels)
1400{
1401 struct volume mip_level_size = image->size;
1402 const BYTE *pixels_ptr = image->pixels;
1403 uint32_t row_pitch, slice_pitch, i;
1404 RECT unaligned_rect;
1405 HRESULT hr = S_OK;
1406
1407 if (mip_level >= image->mip_levels)
1408 {
1409 ERR("Tried to retrieve mip level %u, but image only has %u mip levels.\n", mip_level, image->mip_levels);
1410 return E_FAIL;
1411 }
1412
1413 if (layer >= image->layer_count)
1414 {
1415 ERR("Tried to retrieve layer %u, but image only has %u layers.\n", layer, image->layer_count);
1416 return E_FAIL;
1417 }
1418
1419 slice_pitch = row_pitch = 0;
1420 for (i = 0; i < image->mip_levels; i++)
1421 {
1422 hr = d3dx_calculate_pixels_size(image->format, mip_level_size.width, mip_level_size.height, &row_pitch, &slice_pitch);
1423 if (FAILED(hr))
1424 return hr;
1425
1426 if (i == mip_level)
1427 break;
1428
1429 pixels_ptr += slice_pitch * mip_level_size.depth;
1430 d3dx_get_next_mip_level_size(&mip_level_size);
1431 }
1432
1433 pixels_ptr += (layer * image->layer_pitch);
1434 SetRect(&unaligned_rect, 0, 0, mip_level_size.width, mip_level_size.height);
1435 set_d3dx_pixels(pixels, pixels_ptr, row_pitch, slice_pitch, image->palette, mip_level_size.width,
1436 mip_level_size.height, mip_level_size.depth, &unaligned_rect);
1437
1438 return D3D_OK;
1439}
1440
1442{
1443 info->ImageFileFormat = image->image_file_format;
1444 info->Width = image->size.width;
1445 info->Height = image->size.height;
1446 info->Depth = image->size.depth;
1447 info->MipLevels = image->mip_levels;
1448 switch (image->format)
1449 {
1451 info->Format = D3DFMT_A16B16G16R16;
1452 break;
1453
1455 if (info->ImageFileFormat == D3DXIFF_PNG || info->ImageFileFormat == D3DXIFF_JPG)
1456 info->Format = D3DFMT_X8R8G8B8;
1457 else
1459 break;
1460
1461 default:
1463 break;
1464 }
1465 info->ResourceType = image->resource_type;
1466}
1467
1468/************************************************************
1469 * D3DXGetImageInfoFromFileInMemory
1470 *
1471 * Fills a D3DXIMAGE_INFO structure with info about an image
1472 *
1473 * PARAMS
1474 * data [I] pointer to the image file data
1475 * datasize [I] size of the passed data
1476 * info [O] pointer to the destination structure
1477 *
1478 * RETURNS
1479 * Success: D3D_OK, if info is not NULL and data and datasize make up a valid image file or
1480 * if info is NULL and data and datasize are not NULL
1481 * Failure: D3DXERR_INVALIDDATA, if data is no valid image file and datasize and info are not NULL
1482 * D3DERR_INVALIDCALL, if data is NULL or
1483 * if datasize is 0
1484 *
1485 * NOTES
1486 * datasize may be bigger than the actual file size
1487 *
1488 */
1490{
1491 struct d3dx_image image;
1492 HRESULT hr;
1493
1494 TRACE("(%p, %d, %p)\n", data, datasize, info);
1495
1496 if (!data || !datasize)
1497 return D3DERR_INVALIDCALL;
1498
1499 if (!info)
1500 return D3D_OK;
1501
1503 if (FAILED(hr)) {
1504 TRACE("Invalid or unsupported image file\n");
1505 return D3DXERR_INVALIDDATA;
1506 }
1507
1509 return D3D_OK;
1510}
1511
1512/************************************************************
1513 * D3DXGetImageInfoFromFile
1514 *
1515 * RETURNS
1516 * Success: D3D_OK, if we successfully load a valid image file or
1517 * if we successfully load a file which is no valid image and info is NULL
1518 * Failure: D3DXERR_INVALIDDATA, if we fail to load file or
1519 * if file is not a valid image file and info is not NULL
1520 * D3DERR_INVALIDCALL, if file is NULL
1521 *
1522 */
1524{
1525 WCHAR *widename;
1526 HRESULT hr;
1527 int strlength;
1528
1529 TRACE("file %s, info %p.\n", debugstr_a(file), info);
1530
1531 if( !file ) return D3DERR_INVALIDCALL;
1532
1533 strlength = MultiByteToWideChar(CP_ACP, 0, file, -1, NULL, 0);
1534 widename = malloc(strlength * sizeof(*widename));
1535 MultiByteToWideChar(CP_ACP, 0, file, -1, widename, strlength);
1536
1537 hr = D3DXGetImageInfoFromFileW(widename, info);
1538 free(widename);
1539
1540 return hr;
1541}
1542
1544{
1545 void *buffer;
1546 HRESULT hr;
1547 DWORD size;
1548
1549 TRACE("file %s, info %p.\n", debugstr_w(file), info);
1550
1551 if (!file)
1552 return D3DERR_INVALIDCALL;
1553
1555 return D3DXERR_INVALIDDATA;
1556
1559
1560 return hr;
1561}
1562
1563/************************************************************
1564 * D3DXGetImageInfoFromResource
1565 *
1566 * RETURNS
1567 * Success: D3D_OK, if resource is a valid image file
1568 * Failure: D3DXERR_INVALIDDATA, if resource is no valid image file or NULL or
1569 * if we fail to load resource
1570 *
1571 */
1573{
1574 HRSRC resinfo;
1575 void *buffer;
1576 DWORD size;
1577
1578 TRACE("module %p, resource %s, info %p.\n", module, debugstr_a(resource), info);
1579
1580 if (!(resinfo = FindResourceA(module, resource, (const char *)RT_RCDATA))
1581 /* Try loading the resource as bitmap data (which is in DIB format D3DXIFF_DIB) */
1582 && !(resinfo = FindResourceA(module, resource, (const char *)RT_BITMAP)))
1583 return D3DXERR_INVALIDDATA;
1584
1586 return D3DXERR_INVALIDDATA;
1587
1589}
1590
1592{
1593 HRSRC resinfo;
1594 void *buffer;
1595 DWORD size;
1596
1597 TRACE("module %p, resource %s, info %p.\n", module, debugstr_w(resource), info);
1598
1599 if (!(resinfo = FindResourceW(module, resource, (const WCHAR *)RT_RCDATA))
1600 /* Try loading the resource as bitmap data (which is in DIB format D3DXIFF_DIB) */
1601 && !(resinfo = FindResourceW(module, resource, (const WCHAR *)RT_BITMAP)))
1602 return D3DXERR_INVALIDDATA;
1603
1605 return D3DXERR_INVALIDDATA;
1606
1608}
1609
1611 const PALETTEENTRY *dst_palette, const RECT *dst_rect, const void *src_memory,
1612 enum d3dx_pixel_format_id src_format, uint32_t src_pitch, const PALETTEENTRY *src_palette, const RECT *src_rect,
1614{
1615 const struct pixel_format_desc *src_desc, *dst_desc;
1616 struct d3dx_pixels src_pixels, dst_pixels;
1617 RECT dst_rect_tmp, dst_rect_aligned;
1618 IDirect3DSurface9 *surface;
1619 D3DLOCKED_RECT lock_rect;
1621 HRESULT hr;
1622
1623 IDirect3DSurface9_GetDesc(dst_surface, &desc);
1624 if (desc.MultiSampleType != D3DMULTISAMPLE_NONE)
1625 {
1626 TRACE("Multisampled destination surface, doing nothing.\n");
1627 return D3D_OK;
1628 }
1629
1630 dst_desc = get_format_info(desc.Format);
1631 if (!dst_rect)
1632 {
1633 SetRect(&dst_rect_tmp, 0, 0, desc.Width, desc.Height);
1634 dst_rect = &dst_rect_tmp;
1635 }
1636 else
1637 {
1638 if (dst_rect->left > dst_rect->right || dst_rect->right > desc.Width
1639 || dst_rect->top > dst_rect->bottom || dst_rect->bottom > desc.Height
1640 || dst_rect->left < 0 || dst_rect->top < 0)
1641 {
1642 WARN("Invalid dst_rect specified.\n");
1643 return D3DERR_INVALIDCALL;
1644 }
1645 if (dst_rect->left == dst_rect->right || dst_rect->top == dst_rect->bottom)
1646 {
1647 WARN("Empty dst_rect specified.\n");
1648 return D3D_OK;
1649 }
1650 }
1651
1652 src_desc = get_d3dx_pixel_format_info(src_format);
1653 hr = d3dx_pixels_init(src_memory, src_pitch, 0, src_palette, src_desc->format,
1654 src_rect->left, src_rect->top, src_rect->right, src_rect->bottom, 0, 1, &src_pixels);
1655 if (FAILED(hr))
1656 return hr;
1657
1658 get_aligned_rect(dst_rect->left, dst_rect->top, dst_rect->right, dst_rect->bottom, desc.Width, desc.Height,
1659 dst_desc, &dst_rect_aligned);
1660 if (FAILED(hr = lock_surface(dst_surface, &dst_rect_aligned, &lock_rect, &surface, TRUE)))
1661 return hr;
1662
1663 set_d3dx_pixels(&dst_pixels, lock_rect.pBits, lock_rect.Pitch, 0, dst_palette,
1664 (dst_rect_aligned.right - dst_rect_aligned.left), (dst_rect_aligned.bottom - dst_rect_aligned.top), 1,
1665 dst_rect);
1666 OffsetRect(&dst_pixels.unaligned_rect, -dst_rect_aligned.left, -dst_rect_aligned.top);
1667
1668 if (FAILED(hr = d3dx_load_pixels_from_pixels(&dst_pixels, dst_desc, &src_pixels, src_desc, filter, color_key)))
1669 {
1670 unlock_surface(dst_surface, &dst_rect_aligned, surface, FALSE);
1671 return hr;
1672 }
1673
1674 return unlock_surface(dst_surface, &dst_rect_aligned, surface, TRUE);
1675}
1676
1677/************************************************************
1678 * D3DXLoadSurfaceFromFileInMemory
1679 *
1680 * Loads data from a given buffer into a surface and fills a given
1681 * D3DXIMAGE_INFO structure with info about the source data.
1682 *
1683 * PARAMS
1684 * pDestSurface [I] pointer to the surface
1685 * pDestPalette [I] palette to use
1686 * pDestRect [I] to be filled area of the surface
1687 * pSrcData [I] pointer to the source data
1688 * SrcDataSize [I] size of the source data in bytes
1689 * pSrcRect [I] area of the source data to load
1690 * dwFilter [I] filter to apply on stretching
1691 * Colorkey [I] colorkey
1692 * pSrcInfo [O] pointer to a D3DXIMAGE_INFO structure
1693 *
1694 * RETURNS
1695 * Success: D3D_OK
1696 * Failure: D3DERR_INVALIDCALL, if pDestSurface, pSrcData or SrcDataSize is NULL
1697 * D3DXERR_INVALIDDATA, if pSrcData is no valid image file
1698 *
1699 */
1701 const PALETTEENTRY *pDestPalette, const RECT *pDestRect, const void *pSrcData, UINT SrcDataSize,
1702 const RECT *pSrcRect, DWORD dwFilter, D3DCOLOR Colorkey, D3DXIMAGE_INFO *pSrcInfo)
1703{
1704 struct d3dx_pixels pixels = { 0 };
1705 struct d3dx_image image;
1706 D3DXIMAGE_INFO img_info;
1707 RECT src_rect;
1708 HRESULT hr;
1709
1710 TRACE("dst_surface %p, dst_palette %p, dst_rect %s, src_data %p, src_data_size %u, "
1711 "src_rect %s, filter %#lx, color_key 0x%08lx, src_info %p.\n",
1712 pDestSurface, pDestPalette, wine_dbgstr_rect(pDestRect), pSrcData, SrcDataSize,
1713 wine_dbgstr_rect(pSrcRect), dwFilter, Colorkey, pSrcInfo);
1714
1715 if (!pDestSurface || !pSrcData || !SrcDataSize)
1716 return D3DERR_INVALIDCALL;
1717
1718 if (FAILED(hr = d3dx9_handle_load_filter(&dwFilter)))
1719 return hr;
1720
1721 hr = d3dx_image_init(pSrcData, SrcDataSize, &image, 0, 0);
1722 if (FAILED(hr))
1723 return D3DXERR_INVALIDDATA;
1724
1726 if (pSrcRect)
1727 src_rect = *pSrcRect;
1728 else
1729 SetRect(&src_rect, 0, 0, img_info.Width, img_info.Height);
1730
1732 if (FAILED(hr))
1733 goto exit;
1734
1735 hr = d3dx_load_surface_from_memory(pDestSurface, pDestPalette, pDestRect, pixels.data, image.format, pixels.row_pitch,
1736 pixels.palette, &src_rect, dwFilter, Colorkey);
1737 if (SUCCEEDED(hr) && pSrcInfo)
1738 *pSrcInfo = img_info;
1739
1740exit:
1742 return FAILED(hr) ? D3DXERR_INVALIDDATA : D3D_OK;
1743}
1744
1746 const PALETTEENTRY *dst_palette, const RECT *dst_rect, const char *src_file,
1747 const RECT *src_rect, DWORD filter, D3DCOLOR color_key, D3DXIMAGE_INFO *src_info)
1748{
1749 WCHAR *src_file_w;
1750 HRESULT hr;
1751 int strlength;
1752
1753 TRACE("dst_surface %p, dst_palette %p, dst_rect %s, src_file %s, "
1754 "src_rect %s, filter %#lx, color_key 0x%08lx, src_info %p.\n",
1755 dst_surface, dst_palette, wine_dbgstr_rect(dst_rect), debugstr_a(src_file),
1756 wine_dbgstr_rect(src_rect), filter, color_key, src_info);
1757
1758 if (!src_file || !dst_surface)
1759 return D3DERR_INVALIDCALL;
1760
1761 strlength = MultiByteToWideChar(CP_ACP, 0, src_file, -1, NULL, 0);
1762 src_file_w = malloc(strlength * sizeof(*src_file_w));
1763 MultiByteToWideChar(CP_ACP, 0, src_file, -1, src_file_w, strlength);
1764
1765 hr = D3DXLoadSurfaceFromFileW(dst_surface, dst_palette, dst_rect,
1766 src_file_w, src_rect, filter, color_key, src_info);
1767 free(src_file_w);
1768
1769 return hr;
1770}
1771
1773 const PALETTEENTRY *dst_palette, const RECT *dst_rect, const WCHAR *src_file,
1774 const RECT *src_rect, DWORD filter, D3DCOLOR color_key, D3DXIMAGE_INFO *src_info)
1775{
1776 DWORD data_size;
1777 void *data;
1778 HRESULT hr;
1779
1780 TRACE("dst_surface %p, dst_palette %p, dst_rect %s, src_file %s, "
1781 "src_rect %s, filter %#lx, color_key 0x%08lx, src_info %p.\n",
1782 dst_surface, dst_palette, wine_dbgstr_rect(dst_rect), debugstr_w(src_file),
1783 wine_dbgstr_rect(src_rect), filter, color_key, src_info);
1784
1785 if (!src_file || !dst_surface)
1786 return D3DERR_INVALIDCALL;
1787
1788 if (FAILED(map_view_of_file(src_file, &data, &data_size)))
1789 return D3DXERR_INVALIDDATA;
1790
1791 hr = D3DXLoadSurfaceFromFileInMemory(dst_surface, dst_palette, dst_rect,
1792 data, data_size, src_rect, filter, color_key, src_info);
1794
1795 return hr;
1796}
1797
1799 const PALETTEENTRY *dst_palette, const RECT *dst_rect, HMODULE src_module, const char *resource,
1800 const RECT *src_rect, DWORD filter, D3DCOLOR color_key, D3DXIMAGE_INFO *src_info)
1801{
1802 DWORD data_size;
1803 HRSRC resinfo;
1804 void *data;
1805
1806 TRACE("dst_surface %p, dst_palette %p, dst_rect %s, src_module %p, resource %s, "
1807 "src_rect %s, filter %#lx, color_key 0x%08lx, src_info %p.\n",
1808 dst_surface, dst_palette, wine_dbgstr_rect(dst_rect), src_module, debugstr_a(resource),
1809 wine_dbgstr_rect(src_rect), filter, color_key, src_info);
1810
1811 if (!dst_surface)
1812 return D3DERR_INVALIDCALL;
1813
1814 if (!(resinfo = FindResourceA(src_module, resource, (const char *)RT_RCDATA))
1815 /* Try loading the resource as bitmap data (which is in DIB format D3DXIFF_DIB) */
1816 && !(resinfo = FindResourceA(src_module, resource, (const char *)RT_BITMAP)))
1817 return D3DXERR_INVALIDDATA;
1818
1819 if (FAILED(load_resource_into_memory(src_module, resinfo, &data, &data_size)))
1820 return D3DXERR_INVALIDDATA;
1821
1822 return D3DXLoadSurfaceFromFileInMemory(dst_surface, dst_palette, dst_rect,
1823 data, data_size, src_rect, filter, color_key, src_info);
1824}
1825
1827 const PALETTEENTRY *dst_palette, const RECT *dst_rect, HMODULE src_module, const WCHAR *resource,
1828 const RECT *src_rect, DWORD filter, D3DCOLOR color_key, D3DXIMAGE_INFO *src_info)
1829{
1830 DWORD data_size;
1831 HRSRC resinfo;
1832 void *data;
1833
1834 TRACE("dst_surface %p, dst_palette %p, dst_rect %s, src_module %p, resource %s, "
1835 "src_rect %s, filter %#lx, color_key 0x%08lx, src_info %p.\n",
1836 dst_surface, dst_palette, wine_dbgstr_rect(dst_rect), src_module, debugstr_w(resource),
1837 wine_dbgstr_rect(src_rect), filter, color_key, src_info);
1838
1839 if (!dst_surface)
1840 return D3DERR_INVALIDCALL;
1841
1842 if (!(resinfo = FindResourceW(src_module, resource, (const WCHAR *)RT_RCDATA))
1843 /* Try loading the resource as bitmap data (which is in DIB format D3DXIFF_DIB) */
1844 && !(resinfo = FindResourceW(src_module, resource, (const WCHAR *)RT_BITMAP)))
1845 return D3DXERR_INVALIDDATA;
1846
1847 if (FAILED(load_resource_into_memory(src_module, resinfo, &data, &data_size)))
1848 return D3DXERR_INVALIDDATA;
1849
1850 return D3DXLoadSurfaceFromFileInMemory(dst_surface, dst_palette, dst_rect,
1851 data, data_size, src_rect, filter, color_key, src_info);
1852}
1853
1854
1855/************************************************************
1856 * helper functions for D3DXLoadSurfaceFromMemory
1857 */
1859{
1866};
1867
1868static void init_argb_conversion_info(const struct pixel_format_desc *srcformat, const struct pixel_format_desc *destformat, struct argb_conversion_info *info)
1869{
1870 UINT i;
1871 ZeroMemory(info->process_channel, 4 * sizeof(BOOL));
1872 info->channelmask = 0;
1873
1874 info->srcformat = srcformat;
1875 info->destformat = destformat;
1876
1877 for(i = 0;i < 4;i++) {
1878 /* srcshift is used to extract the _relevant_ components */
1879 info->srcshift[i] = srcformat->shift[i] + max( srcformat->bits[i] - destformat->bits[i], 0);
1880
1881 /* destshift is used to move the components to the correct position */
1882 info->destshift[i] = destformat->shift[i] + max(destformat->bits[i] - srcformat->bits[i], 0);
1883
1884 info->srcmask[i] = ((1 << srcformat->bits[i]) - 1) << srcformat->shift[i];
1885 info->destmask[i] = ((1 << destformat->bits[i]) - 1) << destformat->shift[i];
1886
1887 /* channelmask specifies bits which aren't used in the source format but in the destination one */
1888 if(destformat->bits[i]) {
1889 if(srcformat->bits[i]) info->process_channel[i] = TRUE;
1890 else info->channelmask |= info->destmask[i];
1891 }
1892 }
1893}
1894
1895/************************************************************
1896 * get_relevant_argb_components
1897 *
1898 * Extracts the relevant components from the source color and
1899 * drops the less significant bits if they aren't used by the destination format.
1900 */
1901static void get_relevant_argb_components(const struct argb_conversion_info *info, const BYTE *col, DWORD *out)
1902{
1903 unsigned int i, j;
1904 unsigned int component, mask;
1905
1906 for (i = 0; i < 4; ++i)
1907 {
1908 if (!info->process_channel[i])
1909 continue;
1910
1911 component = 0;
1912 mask = info->srcmask[i];
1913 for (j = 0; j < 4 && mask; ++j)
1914 {
1915 if (info->srcshift[i] < j * 8)
1916 component |= (col[j] & mask) << (j * 8 - info->srcshift[i]);
1917 else
1918 component |= (col[j] & mask) >> (info->srcshift[i] - j * 8);
1919 mask >>= 8;
1920 }
1921 out[i] = component;
1922 }
1923}
1924
1925static float d3dx_clamp(float value, float min_value, float max_value)
1926{
1927 if (isnan(value))
1928 return max_value;
1929 return value < min_value ? min_value : value > max_value ? max_value : value;
1930}
1931
1932/************************************************************
1933 * make_argb_color
1934 *
1935 * Recombines the output of get_relevant_argb_components and converts
1936 * it to the destination format.
1937 */
1939{
1940 UINT i;
1941 DWORD val = 0;
1942
1943 for(i = 0;i < 4;i++) {
1944 if(info->process_channel[i]) {
1945 /* necessary to make sure that e.g. an X4R4G4B4 white maps to an R8G8B8 white instead of 0xf0f0f0 */
1946 signed int shift;
1947 for(shift = info->destshift[i]; shift > info->destformat->shift[i]; shift -= info->srcformat->bits[i]) val |= in[i] << shift;
1948 val |= (in[i] >> (info->destformat->shift[i] - shift)) << info->destformat->shift[i];
1949 }
1950 }
1951 val |= info->channelmask; /* new channels are set to their maximal value */
1952 return val;
1953}
1954
1956{
1957 switch (type)
1958 {
1959 case CTYPE_SNORM:
1960 return RANGE_SNORM;
1961
1962 case CTYPE_LUMA:
1963 case CTYPE_INDEX:
1964 case CTYPE_UNORM:
1965 return RANGE_UNORM;
1966
1967 case CTYPE_EMPTY:
1968 case CTYPE_FLOAT:
1969 return RANGE_FULL;
1970
1971 default:
1972 assert(0);
1973 return RANGE_FULL;
1974 }
1975}
1976
1977/* It doesn't work for components bigger than 32 bits (or somewhat smaller but unaligned). */
1979 struct d3dx_color *dst)
1980{
1981 DWORD mask, tmp;
1982 unsigned int c;
1983
1984 dst->rgb_range = get_range_for_component_type(format->rgb_type);
1985 dst->a_range = get_range_for_component_type(format->a_type);
1986 for (c = 0; c < 4; ++c)
1987 {
1988 const enum component_type dst_ctype = !c ? format->a_type : format->rgb_type;
1989 static const unsigned int component_offsets[4] = {3, 0, 1, 2};
1990 float *dst_component = &dst->value.x + component_offsets[c];
1991
1992 if (format->bits[c])
1993 {
1994 mask = ~0u >> (32 - format->bits[c]);
1995
1996 memcpy(&tmp, src + format->shift[c] / 8,
1997 min(sizeof(DWORD), (format->shift[c] % 8 + format->bits[c] + 7) / 8));
1998 tmp = (tmp >> (format->shift[c] % 8)) & mask;
1999
2000 switch (dst_ctype)
2001 {
2002 case CTYPE_FLOAT:
2003 if (format->bits[c] == 16)
2004 *dst_component = float_16_to_32(tmp);
2005 else
2006 *dst_component = *(float *)&tmp;
2007 break;
2008
2009 case CTYPE_INDEX:
2010 *dst_component = (&palette[tmp].peRed)[component_offsets[c]] / 255.0f;
2011 break;
2012
2013 case CTYPE_LUMA:
2014 case CTYPE_UNORM:
2015 *dst_component = (float)tmp / mask;
2016 break;
2017
2018 case CTYPE_SNORM:
2019 {
2020 const uint32_t sign_bit = (1u << (format->bits[c] - 1));
2021 uint32_t tmp_extended = (tmp & sign_bit) ? (tmp | ~(sign_bit - 1)) : tmp;
2022
2023 /*
2024 * In order to clamp to an even range, we need to ignore
2025 * the maximum negative value.
2026 */
2027 if (tmp == sign_bit)
2028 tmp_extended |= 1;
2029
2030 *dst_component = (float)(((int32_t)tmp_extended)) / (sign_bit - 1);
2031 break;
2032 }
2033
2034 default:
2035 break;
2036 }
2037 }
2038 else if (dst_ctype == CTYPE_LUMA)
2039 {
2040 assert(format->bits[1]);
2041 *dst_component = dst->value.x;
2042 }
2043 else
2044 {
2045 *dst_component = 1.0f;
2046 }
2047 }
2048}
2049
2050/* It doesn't work for components bigger than 32 bits. */
2052{
2053 DWORD v, mask32;
2054 unsigned int c, i;
2055
2056 memset(dst, 0, format->bytes_per_pixel);
2057
2058 for (c = 0; c < 4; ++c)
2059 {
2060 const enum component_type dst_ctype = !c ? format->a_type : format->rgb_type;
2061 static const unsigned int component_offsets[4] = {3, 0, 1, 2};
2062 const float src_component = *(&src->value.x + component_offsets[c]);
2063 const enum range src_range = !c ? src->a_range : src->rgb_range;
2064
2065 if (!format->bits[c])
2066 continue;
2067
2068 mask32 = ~0u >> (32 - format->bits[c]);
2069
2070 switch (dst_ctype)
2071 {
2072 case CTYPE_FLOAT:
2073 if (format->bits[c] == 16)
2074 v = float_32_to_16(src_component);
2075 else
2076 v = *(DWORD *)&src_component;
2077 break;
2078
2079 case CTYPE_LUMA:
2080 {
2081 float val = src->value.x * 0.2125f + src->value.y * 0.7154f + src->value.z * 0.0721f;
2082
2083 if (src_range == RANGE_SNORM)
2084 val = (val + 1.0f) / 2.0f;
2085
2086 v = d3dx_clamp(val, 0.0f, 1.0f) * ((1u << format->bits[c]) - 1) + 0.5f;
2087 break;
2088 }
2089
2090 case CTYPE_UNORM:
2091 {
2092 float val = src_component;
2093
2094 if (src_range == RANGE_SNORM)
2095 val = (val + 1.0f) / 2.0f;
2096
2097 v = d3dx_clamp(val, 0.0f, 1.0f) * ((1u << format->bits[c]) - 1) + 0.5f;
2098 break;
2099 }
2100
2101 case CTYPE_SNORM:
2102 {
2103 const uint32_t max_value = (1u << (format->bits[c] - 1)) - 1;
2104 float val = src_component;
2105
2106 if (src_range == RANGE_UNORM)
2107 val = (val * 2.0f) - 1.0f;
2108
2109 v = d3dx_clamp(val, -1.0f, 1.0f) * max_value + 0.5f;
2110 break;
2111 }
2112
2113 /* We shouldn't be trying to output to CTYPE_INDEX. */
2114 case CTYPE_INDEX:
2115 assert(0);
2116 break;
2117
2118 default:
2119 v = 0;
2120 break;
2121 }
2122
2123 for (i = format->shift[c] / 8 * 8; i < format->shift[c] + format->bits[c]; i += 8)
2124 {
2125 BYTE mask, byte;
2126
2127 if (format->shift[c] > i)
2128 {
2129 mask = mask32 << (format->shift[c] - i);
2130 byte = (v << (format->shift[c] - i)) & mask;
2131 }
2132 else
2133 {
2134 mask = mask32 >> (i - format->shift[c]);
2135 byte = (v >> (i - format->shift[c])) & mask;
2136 }
2137 dst[i / 8] |= byte;
2138 }
2139 }
2140}
2141
2142/************************************************************
2143 * copy_pixels
2144 *
2145 * Copies the source buffer to the destination buffer.
2146 * Works for any pixel format.
2147 * The source and the destination must be block-aligned.
2148 */
2149void copy_pixels(const BYTE *src, UINT src_row_pitch, UINT src_slice_pitch,
2150 BYTE *dst, UINT dst_row_pitch, UINT dst_slice_pitch, const struct volume *size,
2151 const struct pixel_format_desc *format)
2152{
2153 UINT row, slice;
2154 BYTE *dst_addr;
2155 const BYTE *src_addr;
2156 UINT row_block_count = (size->width + format->block_width - 1) / format->block_width;
2157 UINT row_count = (size->height + format->block_height - 1) / format->block_height;
2158
2159 for (slice = 0; slice < size->depth; slice++)
2160 {
2161 src_addr = src + slice * src_slice_pitch;
2162 dst_addr = dst + slice * dst_slice_pitch;
2163
2164 for (row = 0; row < row_count; row++)
2165 {
2166 memcpy(dst_addr, src_addr, row_block_count * format->block_byte_count);
2167 src_addr += src_row_pitch;
2168 dst_addr += dst_row_pitch;
2169 }
2170 }
2171}
2172
2173/************************************************************
2174 * convert_argb_pixels
2175 *
2176 * Copies the source buffer to the destination buffer, performing
2177 * any necessary format conversion and color keying.
2178 * Pixels outsize the source rect are blacked out.
2179 */
2180void convert_argb_pixels(const BYTE *src, UINT src_row_pitch, UINT src_slice_pitch, const struct volume *src_size,
2181 const struct pixel_format_desc *src_format, BYTE *dst, UINT dst_row_pitch, UINT dst_slice_pitch,
2182 const struct volume *dst_size, const struct pixel_format_desc *dst_format, D3DCOLOR color_key,
2183 const PALETTEENTRY *palette)
2184{
2185 struct argb_conversion_info conv_info, ck_conv_info;
2186 const struct pixel_format_desc *ck_format;
2187 DWORD channels[4];
2188 UINT min_width, min_height, min_depth;
2189 UINT x, y, z;
2190
2191 TRACE("src %p, src_row_pitch %u, src_slice_pitch %u, src_size %p, src_format %p, dst %p, "
2192 "dst_row_pitch %u, dst_slice_pitch %u, dst_size %p, dst_format %p, color_key 0x%08lx, palette %p.\n",
2193 src, src_row_pitch, src_slice_pitch, src_size, src_format, dst, dst_row_pitch, dst_slice_pitch, dst_size,
2195
2196 ZeroMemory(channels, sizeof(channels));
2197 init_argb_conversion_info(src_format, dst_format, &conv_info);
2198
2199 min_width = min(src_size->width, dst_size->width);
2200 min_height = min(src_size->height, dst_size->height);
2201 min_depth = min(src_size->depth, dst_size->depth);
2202
2203 if (color_key)
2204 {
2205 /* Color keys are always represented in D3DFMT_A8R8G8B8 format. */
2206 ck_format = get_format_info(D3DFMT_A8R8G8B8);
2207 init_argb_conversion_info(src_format, ck_format, &ck_conv_info);
2208 }
2209
2210 for (z = 0; z < min_depth; z++) {
2211 const BYTE *src_slice_ptr = src + z * src_slice_pitch;
2212 BYTE *dst_slice_ptr = dst + z * dst_slice_pitch;
2213
2214 for (y = 0; y < min_height; y++) {
2215 const BYTE *src_ptr = src_slice_ptr + y * src_row_pitch;
2216 BYTE *dst_ptr = dst_slice_ptr + y * dst_row_pitch;
2217
2218 for (x = 0; x < min_width; x++) {
2219 if (format_types_match(src_format, dst_format)
2220 && src_format->bytes_per_pixel <= 4 && dst_format->bytes_per_pixel <= 4)
2221 {
2222 DWORD val;
2223
2224 get_relevant_argb_components(&conv_info, src_ptr, channels);
2225 val = make_argb_color(&conv_info, channels);
2226
2227 if (color_key)
2228 {
2229 DWORD ck_pixel;
2230
2231 get_relevant_argb_components(&ck_conv_info, src_ptr, channels);
2232 ck_pixel = make_argb_color(&ck_conv_info, channels);
2233 if (ck_pixel == color_key)
2234 val &= ~conv_info.destmask[0];
2235 }
2236 memcpy(dst_ptr, &val, dst_format->bytes_per_pixel);
2237 }
2238 else
2239 {
2240 struct d3dx_color color, tmp;
2241
2242 format_to_d3dx_color(src_format, src_ptr, palette, &color);
2243 tmp = color;
2244
2245 if (color_key)
2246 {
2247 DWORD ck_pixel;
2248
2249 format_from_d3dx_color(ck_format, &tmp, (BYTE *)&ck_pixel);
2250 if (ck_pixel == color_key)
2251 tmp.value.w = 0.0f;
2252 }
2253
2254 color = tmp;
2256 }
2257
2258 src_ptr += src_format->bytes_per_pixel;
2259 dst_ptr += dst_format->bytes_per_pixel;
2260 }
2261
2262 if (src_size->width < dst_size->width) /* black out remaining pixels */
2263 memset(dst_ptr, 0, dst_format->bytes_per_pixel * (dst_size->width - src_size->width));
2264 }
2265
2266 if (src_size->height < dst_size->height) /* black out remaining pixels */
2267 memset(dst + src_size->height * dst_row_pitch, 0, dst_row_pitch * (dst_size->height - src_size->height));
2268 }
2269 if (src_size->depth < dst_size->depth) /* black out remaining pixels */
2270 memset(dst + src_size->depth * dst_slice_pitch, 0, dst_slice_pitch * (dst_size->depth - src_size->depth));
2271}
2272
2273/************************************************************
2274 * point_filter_argb_pixels
2275 *
2276 * Copies the source buffer to the destination buffer, performing
2277 * any necessary format conversion, color keying and stretching
2278 * using a point filter.
2279 */
2280void point_filter_argb_pixels(const BYTE *src, UINT src_row_pitch, UINT src_slice_pitch, const struct volume *src_size,
2281 const struct pixel_format_desc *src_format, BYTE *dst, UINT dst_row_pitch, UINT dst_slice_pitch,
2282 const struct volume *dst_size, const struct pixel_format_desc *dst_format, D3DCOLOR color_key,
2283 const PALETTEENTRY *palette)
2284{
2285 struct argb_conversion_info conv_info, ck_conv_info;
2286 const struct pixel_format_desc *ck_format;
2287 DWORD channels[4];
2288 UINT x, y, z;
2289
2290 TRACE("src %p, src_row_pitch %u, src_slice_pitch %u, src_size %p, src_format %p, dst %p, "
2291 "dst_row_pitch %u, dst_slice_pitch %u, dst_size %p, dst_format %p, color_key 0x%08lx, palette %p.\n",
2292 src, src_row_pitch, src_slice_pitch, src_size, src_format, dst, dst_row_pitch, dst_slice_pitch, dst_size,
2294
2295 ZeroMemory(channels, sizeof(channels));
2296 init_argb_conversion_info(src_format, dst_format, &conv_info);
2297
2298 if (color_key)
2299 {
2300 /* Color keys are always represented in D3DFMT_A8R8G8B8 format. */
2301 ck_format = get_format_info(D3DFMT_A8R8G8B8);
2302 init_argb_conversion_info(src_format, ck_format, &ck_conv_info);
2303 }
2304
2305 for (z = 0; z < dst_size->depth; z++)
2306 {
2307 BYTE *dst_slice_ptr = dst + z * dst_slice_pitch;
2308 const BYTE *src_slice_ptr = src + src_slice_pitch * (z * src_size->depth / dst_size->depth);
2309
2310 for (y = 0; y < dst_size->height; y++)
2311 {
2312 BYTE *dst_ptr = dst_slice_ptr + y * dst_row_pitch;
2313 const BYTE *src_row_ptr = src_slice_ptr + src_row_pitch * (y * src_size->height / dst_size->height);
2314
2315 for (x = 0; x < dst_size->width; x++)
2316 {
2317 const BYTE *src_ptr = src_row_ptr + (x * src_size->width / dst_size->width) * src_format->bytes_per_pixel;
2318
2319 if (format_types_match(src_format, dst_format)
2320 && src_format->bytes_per_pixel <= 4 && dst_format->bytes_per_pixel <= 4)
2321 {
2322 DWORD val;
2323
2324 get_relevant_argb_components(&conv_info, src_ptr, channels);
2325 val = make_argb_color(&conv_info, channels);
2326
2327 if (color_key)
2328 {
2329 DWORD ck_pixel;
2330
2331 get_relevant_argb_components(&ck_conv_info, src_ptr, channels);
2332 ck_pixel = make_argb_color(&ck_conv_info, channels);
2333 if (ck_pixel == color_key)
2334 val &= ~conv_info.destmask[0];
2335 }
2336 memcpy(dst_ptr, &val, dst_format->bytes_per_pixel);
2337 }
2338 else
2339 {
2340 struct d3dx_color color, tmp;
2341
2342 format_to_d3dx_color(src_format, src_ptr, palette, &color);
2343 tmp = color;
2344
2345 if (color_key)
2346 {
2347 DWORD ck_pixel;
2348
2349 format_from_d3dx_color(ck_format, &tmp, (BYTE *)&ck_pixel);
2350 if (ck_pixel == color_key)
2351 tmp.value.w = 0.0f;
2352 }
2353
2354 color = tmp;
2356 }
2357
2358 dst_ptr += dst_format->bytes_per_pixel;
2359 }
2360 }
2361 }
2362}
2363
2365 BOOL is_dst, void **out_memory, uint32_t *out_row_pitch, uint32_t *out_slice_pitch,
2366 const struct pixel_format_desc **out_desc)
2367{
2368 void (*fetch_dxt_texel)(int srcRowStride, const BYTE *pixdata, int i, int j, void *texel);
2369 uint32_t x, y, z, tmp_pitch, uncompressed_slice_pitch, uncompressed_row_pitch;
2370 const struct pixel_format_desc *uncompressed_desc = NULL;
2371 const struct volume *size = &pixels->size;
2372 BYTE *uncompressed_mem;
2373
2374 switch (desc->format)
2375 {
2377 uncompressed_desc = get_format_info(D3DFMT_A8B8G8R8);
2378 fetch_dxt_texel = fetch_2d_texel_rgba_dxt1;
2379 break;
2382 uncompressed_desc = get_format_info(D3DFMT_A8B8G8R8);
2383 fetch_dxt_texel = fetch_2d_texel_rgba_dxt3;
2384 break;
2387 uncompressed_desc = get_format_info(D3DFMT_A8B8G8R8);
2388 fetch_dxt_texel = fetch_2d_texel_rgba_dxt5;
2389 break;
2390 default:
2391 FIXME("Unexpected compressed texture format %u.\n", desc->format);
2392 return E_NOTIMPL;
2393 }
2394
2395 uncompressed_row_pitch = size->width * uncompressed_desc->bytes_per_pixel;
2396 uncompressed_slice_pitch = uncompressed_row_pitch * size->height;
2397 if (!(uncompressed_mem = malloc(size->depth * uncompressed_slice_pitch)))
2398 return E_OUTOFMEMORY;
2399
2400 /*
2401 * For compressed destination pixels, width/height will represent
2402 * the entire set of compressed blocks our destination rectangle touches.
2403 * If we're only updating a sub-area of any blocks, we need to decompress
2404 * the pixels outside of the sub-area.
2405 */
2406 if (is_dst)
2407 {
2408 const RECT aligned_rect = { 0, 0, size->width, size->height };
2409
2410 /*
2411 * If our destination covers the entire set of blocks, no
2412 * decompression needs to be done, just return the allocated memory.
2413 */
2414 if (EqualRect(&aligned_rect, &pixels->unaligned_rect))
2415 goto exit;
2416 }
2417
2418 TRACE("Decompressing pixels.\n");
2419 tmp_pitch = pixels->row_pitch * desc->block_width / desc->block_byte_count;
2420 for (z = 0; z < size->depth; ++z)
2421 {
2422 const BYTE *slice_data = ((BYTE *)pixels->data) + (pixels->slice_pitch * z);
2423
2424 for (y = 0; y < size->height; ++y)
2425 {
2426 BYTE *ptr = &uncompressed_mem[(z * uncompressed_slice_pitch) + (y * uncompressed_row_pitch)];
2427 for (x = 0; x < size->width; ++x)
2428 {
2429 const POINT pt = { x, y };
2430
2431 if (!is_dst)
2432 fetch_dxt_texel(tmp_pitch, slice_data, x + pixels->unaligned_rect.left,
2433 y + pixels->unaligned_rect.top, ptr);
2434 else if (!PtInRect(&pixels->unaligned_rect, pt))
2435 fetch_dxt_texel(tmp_pitch, slice_data, x, y, ptr);
2436 ptr += uncompressed_desc->bytes_per_pixel;
2437 }
2438 }
2439 }
2440
2441exit:
2442 *out_memory = uncompressed_mem;
2443 *out_row_pitch = uncompressed_row_pitch;
2444 *out_slice_pitch = uncompressed_slice_pitch;
2445 *out_desc = uncompressed_desc;
2446
2447 return S_OK;
2448}
2449
2450HRESULT d3dx_pixels_init(const void *data, uint32_t row_pitch, uint32_t slice_pitch,
2453{
2454 const struct pixel_format_desc *fmt_desc = get_d3dx_pixel_format_info(format);
2455 const BYTE *ptr = data;
2456 RECT unaligned_rect;
2457
2458 memset(pixels, 0, sizeof(*pixels));
2459 if (is_unknown_format(fmt_desc))
2460 {
2461 FIXME("Unsupported format %#x.\n", format);
2462 return E_NOTIMPL;
2463 }
2464
2465 ptr += front * slice_pitch;
2466 ptr += (top / fmt_desc->block_height) * row_pitch;
2467 ptr += (left / fmt_desc->block_width) * fmt_desc->block_byte_count;
2468
2469 if (is_compressed_format(fmt_desc))
2470 {
2471 uint32_t left_aligned, top_aligned;
2472
2473 top_aligned = top & ~(fmt_desc->block_height - 1);
2474 left_aligned = left & ~(fmt_desc->block_width - 1);
2475 SetRect(&unaligned_rect, left, top, right, bottom);
2476 OffsetRect(&unaligned_rect, -left_aligned, -top_aligned);
2477 }
2478 else
2479 {
2480 SetRect(&unaligned_rect, 0, 0, (right - left), (bottom - top));
2481 }
2482
2483 set_d3dx_pixels(pixels, ptr, row_pitch, slice_pitch, palette, (right - left), (bottom - top), (back - front),
2484 &unaligned_rect);
2485
2486 return S_OK;
2487}
2488
2489static const char *debug_d3dx_pixels(struct d3dx_pixels *pixels)
2490{
2491 if (!pixels)
2492 return "(null)";
2493 return wine_dbg_sprintf("(data %p, row_pitch %d, slice_pitch %d, palette %p, width %d, height %d, depth %d, "
2494 "unaligned_rect %s)", pixels->data, pixels->row_pitch, pixels->slice_pitch, pixels->palette,
2495 pixels->size.width, pixels->size.height, pixels->size.depth, wine_dbgstr_rect(&pixels->unaligned_rect));
2496}
2497
2499 const struct pixel_format_desc *dst_desc, struct d3dx_pixels *src_pixels,
2500 const struct pixel_format_desc *src_desc, uint32_t filter_flags, uint32_t color_key)
2501{
2502 struct volume src_size, dst_size, dst_size_aligned;
2503 HRESULT hr = S_OK;
2504
2505 TRACE("dst_pixels %s, dst_desc %p, src_pixels %s, src_desc %p, filter_flags %#x, color_key %#x.\n",
2506 debug_d3dx_pixels(dst_pixels), dst_desc, debug_d3dx_pixels(src_pixels), src_desc,
2507 filter_flags, color_key);
2508
2509 if (is_compressed_format(src_desc))
2510 set_volume_struct(&src_size, (src_pixels->unaligned_rect.right - src_pixels->unaligned_rect.left),
2511 (src_pixels->unaligned_rect.bottom - src_pixels->unaligned_rect.top), src_pixels->size.depth);
2512 else
2513 src_size = src_pixels->size;
2514
2515 dst_size_aligned = dst_pixels->size;
2516 if (is_compressed_format(dst_desc))
2517 set_volume_struct(&dst_size, (dst_pixels->unaligned_rect.right - dst_pixels->unaligned_rect.left),
2518 (dst_pixels->unaligned_rect.bottom - dst_pixels->unaligned_rect.top), dst_pixels->size.depth);
2519 else
2520 dst_size = dst_size_aligned;
2521
2522 /* Everything matches, simply copy the pixels. */
2523 if (src_desc->format == dst_desc->format
2524 && (dst_size.width == src_size.width && !(dst_size.width % dst_desc->block_width))
2525 && (dst_size.height == src_size.height && !(dst_size.height % dst_desc->block_height))
2526 && (dst_size.depth == src_size.depth)
2527 && color_key == 0
2528 && !(src_pixels->unaligned_rect.left & (src_desc->block_width - 1))
2529 && !(src_pixels->unaligned_rect.top & (src_desc->block_height - 1))
2530 && !(dst_pixels->unaligned_rect.left & (dst_desc->block_width - 1))
2531 && !(dst_pixels->unaligned_rect.top & (dst_desc->block_height - 1)))
2532 {
2533 TRACE("Simple copy.\n");
2534 copy_pixels(src_pixels->data, src_pixels->row_pitch, src_pixels->slice_pitch, (void *)dst_pixels->data,
2535 dst_pixels->row_pitch, dst_pixels->slice_pitch, &src_size, src_desc);
2536 return S_OK;
2537 }
2538
2539 /* Stretching or format conversion. */
2540 if (!is_conversion_from_supported(src_desc)
2541 || !is_conversion_to_supported(dst_desc))
2542 {
2543 FIXME("Unsupported format conversion %#x -> %#x.\n", src_desc->format, dst_desc->format);
2544 return E_NOTIMPL;
2545 }
2546
2547 /*
2548 * If the source is a compressed image, we need to decompress it first
2549 * before doing any modifications.
2550 */
2551 if (is_compressed_format(src_desc))
2552 {
2553 uint32_t uncompressed_row_pitch, uncompressed_slice_pitch;
2554 const struct pixel_format_desc *uncompressed_desc;
2555 void *uncompressed_mem = NULL;
2556
2557 hr = d3dx_pixels_decompress(src_pixels, src_desc, FALSE, &uncompressed_mem, &uncompressed_row_pitch,
2558 &uncompressed_slice_pitch, &uncompressed_desc);
2559 if (SUCCEEDED(hr))
2560 {
2561 struct d3dx_pixels uncompressed_pixels;
2562
2563 d3dx_pixels_init(uncompressed_mem, uncompressed_row_pitch, uncompressed_slice_pitch, NULL,
2564 uncompressed_desc->format, 0, 0, src_pixels->size.width, src_pixels->size.height,
2565 0, src_pixels->size.depth, &uncompressed_pixels);
2566
2567 hr = d3dx_load_pixels_from_pixels(dst_pixels, dst_desc, &uncompressed_pixels, uncompressed_desc,
2568 filter_flags, color_key);
2569 }
2570 free(uncompressed_mem);
2571 goto exit;
2572 }
2573
2574 /* Same as the above, need to decompress the destination prior to modifying. */
2575 if (is_compressed_format(dst_desc))
2576 {
2577 uint32_t uncompressed_row_pitch, uncompressed_slice_pitch;
2578 const struct pixel_format_desc *uncompressed_desc;
2579 struct d3dx_pixels uncompressed_pixels;
2580 void *uncompressed_mem = NULL;
2581
2582 hr = d3dx_pixels_decompress(dst_pixels, dst_desc, TRUE, &uncompressed_mem, &uncompressed_row_pitch,
2583 &uncompressed_slice_pitch, &uncompressed_desc);
2584 if (FAILED(hr))
2585 goto exit;
2586
2587 d3dx_pixels_init(uncompressed_mem, uncompressed_row_pitch, uncompressed_slice_pitch, NULL,
2588 uncompressed_desc->format, dst_pixels->unaligned_rect.left, dst_pixels->unaligned_rect.top,
2589 dst_pixels->unaligned_rect.right, dst_pixels->unaligned_rect.bottom, 0, dst_pixels->size.depth,
2590 &uncompressed_pixels);
2591
2592 hr = d3dx_load_pixels_from_pixels(&uncompressed_pixels, uncompressed_desc, src_pixels, src_desc, filter_flags,
2593 color_key);
2594 if (SUCCEEDED(hr))
2595 {
2596 GLenum gl_format = 0;
2597 uint32_t i;
2598
2599 TRACE("Compressing DXTn surface.\n");
2600 switch (dst_desc->format)
2601 {
2604 break;
2608 break;
2612 break;
2613 default:
2614 ERR("Unexpected destination compressed format %u.\n", dst_desc->format);
2615 }
2616
2617 for (i = 0; i < dst_size_aligned.depth; ++i)
2618 {
2619 BYTE *uncompressed_mem_slice = (BYTE *)uncompressed_mem + (i * uncompressed_slice_pitch);
2620 BYTE *dst_memory_slice = ((BYTE *)dst_pixels->data) + (i * dst_pixels->slice_pitch);
2621
2622 tx_compress_dxtn(4, dst_size_aligned.width, dst_size_aligned.height, uncompressed_mem_slice, gl_format,
2623 dst_memory_slice, dst_pixels->row_pitch);
2624 }
2625 }
2626 free(uncompressed_mem);
2627 goto exit;
2628 }
2629
2630 if ((filter_flags & 0xf) == D3DX_FILTER_NONE)
2631 {
2632 convert_argb_pixels(src_pixels->data, src_pixels->row_pitch, src_pixels->slice_pitch, &src_size, src_desc,
2633 (BYTE *)dst_pixels->data, dst_pixels->row_pitch, dst_pixels->slice_pitch, &dst_size, dst_desc,
2634 color_key, src_pixels->palette);
2635 }
2636 else /* if ((filter & 0xf) == D3DX_FILTER_POINT) */
2637 {
2638 if ((filter_flags & 0xf) != D3DX_FILTER_POINT)
2639 FIXME("Unhandled filter %#x.\n", filter_flags);
2640
2641 /* Always apply a point filter until D3DX_FILTER_LINEAR,
2642 * D3DX_FILTER_TRIANGLE and D3DX_FILTER_BOX are implemented. */
2643 point_filter_argb_pixels(src_pixels->data, src_pixels->row_pitch, src_pixels->slice_pitch, &src_size,
2644 src_desc, (BYTE *)dst_pixels->data, dst_pixels->row_pitch, dst_pixels->slice_pitch, &dst_size,
2645 dst_desc, color_key, src_pixels->palette);
2646 }
2647
2648exit:
2649 if (FAILED(hr))
2650 WARN("Failed to load pixels, hr %#lx.\n", hr);
2651 return hr;
2652}
2653
2655 const struct pixel_format_desc *fmt_desc, RECT *aligned_rect)
2656{
2657 SetRect(aligned_rect, left, top, right, bottom);
2658 if (aligned_rect->left & (fmt_desc->block_width - 1))
2659 aligned_rect->left = aligned_rect->left & ~(fmt_desc->block_width - 1);
2660 if (aligned_rect->top & (fmt_desc->block_height - 1))
2661 aligned_rect->top = aligned_rect->top & ~(fmt_desc->block_height - 1);
2662 if (aligned_rect->right & (fmt_desc->block_width - 1) && aligned_rect->right != width)
2663 aligned_rect->right = min((aligned_rect->right + fmt_desc->block_width - 1)
2664 & ~(fmt_desc->block_width - 1), width);
2665 if (aligned_rect->bottom & (fmt_desc->block_height - 1) && aligned_rect->bottom != height)
2666 aligned_rect->bottom = min((aligned_rect->bottom + fmt_desc->block_height - 1)
2667 & ~(fmt_desc->block_height - 1), height);
2668}
2669
2670/************************************************************
2671 * D3DXLoadSurfaceFromMemory
2672 *
2673 * Loads data from a given memory chunk into a surface,
2674 * applying any of the specified filters.
2675 *
2676 * PARAMS
2677 * pDestSurface [I] pointer to the surface
2678 * pDestPalette [I] palette to use
2679 * pDestRect [I] to be filled area of the surface
2680 * pSrcMemory [I] pointer to the source data
2681 * SrcFormat [I] format of the source pixel data
2682 * SrcPitch [I] number of bytes in a row
2683 * pSrcPalette [I] palette used in the source image
2684 * pSrcRect [I] area of the source data to load
2685 * dwFilter [I] filter to apply on stretching
2686 * Colorkey [I] colorkey
2687 *
2688 * RETURNS
2689 * Success: D3D_OK, if we successfully load the pixel data into our surface or
2690 * if pSrcMemory is NULL but the other parameters are valid
2691 * Failure: D3DERR_INVALIDCALL, if pDestSurface, SrcPitch or pSrcRect is NULL or
2692 * if SrcFormat is an invalid format (other than D3DFMT_UNKNOWN) or
2693 * if DestRect is invalid
2694 * D3DXERR_INVALIDDATA, if we fail to lock pDestSurface
2695 * E_FAIL, if SrcFormat is D3DFMT_UNKNOWN or the dimensions of pSrcRect are invalid
2696 *
2697 * NOTES
2698 * pSrcRect specifies the dimensions of the source data;
2699 * negative values for pSrcRect are allowed as we're only looking at the width and height anyway.
2700 *
2701 */
2703 const PALETTEENTRY *dst_palette, const RECT *dst_rect, const void *src_memory,
2704 D3DFORMAT src_format, UINT src_pitch, const PALETTEENTRY *src_palette, const RECT *src_rect,
2706{
2707 const struct pixel_format_desc *src_desc;
2708 HRESULT hr;
2709
2710 TRACE("dst_surface %p, dst_palette %p, dst_rect %s, src_memory %p, src_format %#x, "
2711 "src_pitch %u, src_palette %p, src_rect %s, filter %#lx, color_key 0x%08lx.\n",
2712 dst_surface, dst_palette, wine_dbgstr_rect(dst_rect), src_memory, src_format,
2713 src_pitch, src_palette, wine_dbgstr_rect(src_rect), filter, color_key);
2714
2715 if (!dst_surface || !src_memory || !src_rect)
2716 {
2717 WARN("Invalid argument specified.\n");
2718 return D3DERR_INVALIDCALL;
2719 }
2720
2722 return hr;
2723
2724 if (src_format == D3DFMT_UNKNOWN
2725 || src_rect->left >= src_rect->right
2726 || src_rect->top >= src_rect->bottom)
2727 {
2728 WARN("Invalid src_format or src_rect.\n");
2729 return E_FAIL;
2730 }
2731
2732 src_desc = get_format_info(src_format);
2733 if (is_unknown_format(src_desc))
2734 {
2735 FIXME("Unsupported format %#x.\n", src_format);
2736 return E_NOTIMPL;
2737 }
2738
2739 return d3dx_load_surface_from_memory(dst_surface, dst_palette, dst_rect, src_memory, src_desc->format, src_pitch,
2740 src_palette, src_rect, filter, color_key);
2741}
2742
2743/************************************************************
2744 * D3DXLoadSurfaceFromSurface
2745 *
2746 * Copies the contents from one surface to another, performing any required
2747 * format conversion, resizing or filtering.
2748 *
2749 * PARAMS
2750 * pDestSurface [I] pointer to the destination surface
2751 * pDestPalette [I] palette to use
2752 * pDestRect [I] to be filled area of the surface
2753 * pSrcSurface [I] pointer to the source surface
2754 * pSrcPalette [I] palette used for the source surface
2755 * pSrcRect [I] area of the source data to load
2756 * dwFilter [I] filter to apply on resizing
2757 * Colorkey [I] any ARGB value or 0 to disable color-keying
2758 *
2759 * RETURNS
2760 * Success: D3D_OK
2761 * Failure: D3DERR_INVALIDCALL, if pDestSurface or pSrcSurface is NULL
2762 * D3DXERR_INVALIDDATA, if one of the surfaces is not lockable
2763 *
2764 */
2766 const PALETTEENTRY *dst_palette, const RECT *dst_rect, IDirect3DSurface9 *src_surface,
2767 const PALETTEENTRY *src_palette, const RECT *src_rect, DWORD filter, D3DCOLOR color_key)
2768{
2769 const struct pixel_format_desc *src_format_desc, *dst_format_desc;
2770 D3DSURFACE_DESC src_desc, dst_desc;
2771 struct volume src_size, dst_size;
2772 IDirect3DSurface9 *temp_surface;
2773 D3DTEXTUREFILTERTYPE d3d_filter;
2776 RECT dst_rect_temp;
2777 HRESULT hr;
2778 RECT s;
2779
2780 TRACE("dst_surface %p, dst_palette %p, dst_rect %s, src_surface %p, "
2781 "src_palette %p, src_rect %s, filter %#lx, color_key 0x%08lx.\n",
2782 dst_surface, dst_palette, wine_dbgstr_rect(dst_rect), src_surface,
2783 src_palette, wine_dbgstr_rect(src_rect), filter, color_key);
2784
2785 if (!dst_surface || !src_surface)
2786 return D3DERR_INVALIDCALL;
2787
2789 return hr;
2790
2791 IDirect3DSurface9_GetDesc(src_surface, &src_desc);
2792 src_format_desc = get_format_info(src_desc.Format);
2793 if (!src_rect)
2794 {
2795 SetRect(&s, 0, 0, src_desc.Width, src_desc.Height);
2796 src_rect = &s;
2797 }
2798 else if (src_rect->left == src_rect->right || src_rect->top == src_rect->bottom)
2799 {
2800 WARN("Empty src_rect specified.\n");
2801 return filter == D3DX_FILTER_NONE ? D3D_OK : E_FAIL;
2802 }
2803 else if (src_rect->left > src_rect->right || src_rect->right > src_desc.Width
2804 || src_rect->left < 0 || src_rect->left > src_desc.Width
2805 || src_rect->top > src_rect->bottom || src_rect->bottom > src_desc.Height
2806 || src_rect->top < 0 || src_rect->top > src_desc.Height)
2807 {
2808 WARN("Invalid src_rect specified.\n");
2809 return D3DERR_INVALIDCALL;
2810 }
2811
2812 src_size.width = src_rect->right - src_rect->left;
2813 src_size.height = src_rect->bottom - src_rect->top;
2814 src_size.depth = 1;
2815
2816 IDirect3DSurface9_GetDesc(dst_surface, &dst_desc);
2817 dst_format_desc = get_format_info(dst_desc.Format);
2818 if (!dst_rect)
2819 {
2820 SetRect(&dst_rect_temp, 0, 0, dst_desc.Width, dst_desc.Height);
2821 dst_rect = &dst_rect_temp;
2822 }
2823 else if (dst_rect->left == dst_rect->right || dst_rect->top == dst_rect->bottom)
2824 {
2825 WARN("Empty dst_rect specified.\n");
2826 return filter == D3DX_FILTER_NONE ? D3D_OK : E_FAIL;
2827 }
2828 else if (dst_rect->left > dst_rect->right || dst_rect->right > dst_desc.Width
2829 || dst_rect->left < 0 || dst_rect->left > dst_desc.Width
2830 || dst_rect->top > dst_rect->bottom || dst_rect->bottom > dst_desc.Height
2831 || dst_rect->top < 0 || dst_rect->top > dst_desc.Height)
2832 {
2833 WARN("Invalid dst_rect specified.\n");
2834 return D3DERR_INVALIDCALL;
2835 }
2836
2837 dst_size.width = dst_rect->right - dst_rect->left;
2838 dst_size.height = dst_rect->bottom - dst_rect->top;
2839 dst_size.depth = 1;
2840
2841 if (!dst_palette && !src_palette && !color_key)
2842 {
2843 if (src_desc.Format == dst_desc.Format
2844 && dst_size.width == src_size.width
2845 && dst_size.height == src_size.height
2846 && color_key == 0
2847 && !(src_rect->left & (src_format_desc->block_width - 1))
2848 && !(src_rect->top & (src_format_desc->block_height - 1))
2849 && !(dst_rect->left & (dst_format_desc->block_width - 1))
2850 && !(dst_rect->top & (dst_format_desc->block_height - 1)))
2851 {
2852 d3d_filter = D3DTEXF_NONE;
2853 }
2854 else
2855 {
2856 switch (filter)
2857 {
2858 case D3DX_FILTER_NONE:
2859 d3d_filter = D3DTEXF_NONE;
2860 break;
2861
2862 case D3DX_FILTER_POINT:
2863 d3d_filter = D3DTEXF_POINT;
2864 break;
2865
2866 case D3DX_FILTER_LINEAR:
2867 d3d_filter = D3DTEXF_LINEAR;
2868 break;
2869
2870 default:
2871 d3d_filter = D3DTEXF_FORCE_DWORD;
2872 break;
2873 }
2874 }
2875
2876 if (d3d_filter != D3DTEXF_FORCE_DWORD)
2877 {
2878 IDirect3DSurface9_GetDevice(src_surface, &device);
2879 hr = IDirect3DDevice9_StretchRect(device, src_surface, src_rect, dst_surface, dst_rect, d3d_filter);
2881 if (SUCCEEDED(hr))
2882 return D3D_OK;
2883 }
2884 }
2885
2886 if (FAILED(lock_surface(src_surface, NULL, &lock, &temp_surface, FALSE)))
2887 return D3DXERR_INVALIDDATA;
2888
2889 hr = D3DXLoadSurfaceFromMemory(dst_surface, dst_palette, dst_rect, lock.pBits,
2890 src_desc.Format, lock.Pitch, src_palette, src_rect, filter, color_key);
2891
2892 if (FAILED(unlock_surface(src_surface, NULL, temp_surface, FALSE)))
2893 return D3DXERR_INVALIDDATA;
2894
2895 return hr;
2896}
2897
2898
2899HRESULT WINAPI D3DXSaveSurfaceToFileA(const char *dst_filename, D3DXIMAGE_FILEFORMAT file_format,
2900 IDirect3DSurface9 *src_surface, const PALETTEENTRY *src_palette, const RECT *src_rect)
2901{
2902 int len;
2903 WCHAR *filename;
2904 HRESULT hr;
2906
2907 TRACE("(%s, %#x, %p, %p, %s): relay\n",
2908 wine_dbgstr_a(dst_filename), file_format, src_surface, src_palette, wine_dbgstr_rect(src_rect));
2909
2910 if (!dst_filename) return D3DERR_INVALIDCALL;
2911
2912 len = MultiByteToWideChar(CP_ACP, 0, dst_filename, -1, NULL, 0);
2913 filename = malloc(len * sizeof(WCHAR));
2914 if (!filename) return E_OUTOFMEMORY;
2915 MultiByteToWideChar(CP_ACP, 0, dst_filename, -1, filename, len);
2916
2917 hr = D3DXSaveSurfaceToFileInMemory(&buffer, file_format, src_surface, src_palette, src_rect);
2918 if (SUCCEEDED(hr))
2919 {
2922 }
2923
2924 free(filename);
2925 return hr;
2926}
2927
2929 IDirect3DSurface9 *src_surface, const PALETTEENTRY *src_palette, const RECT *src_rect)
2930{
2931 HRESULT hr;
2933
2934 TRACE("(%s, %#x, %p, %p, %s): relay\n",
2935 wine_dbgstr_w(dst_filename), file_format, src_surface, src_palette, wine_dbgstr_rect(src_rect));
2936
2937 if (!dst_filename) return D3DERR_INVALIDCALL;
2938
2939 hr = D3DXSaveSurfaceToFileInMemory(&buffer, file_format, src_surface, src_palette, src_rect);
2940 if (SUCCEEDED(hr))
2941 {
2942 hr = write_buffer_to_file(dst_filename, buffer);
2944 }
2945
2946 return hr;
2947}
2948
2950 IDirect3DSurface9 *src_surface, const PALETTEENTRY *src_palette, const RECT *src_rect)
2951{
2953 IWICBitmapFrameEncode *frame = NULL;
2954 IPropertyBag2 *encoder_options = NULL;
2955 IStream *stream = NULL;
2956 HRESULT hr;
2957 const GUID *container_format;
2958 const GUID *pixel_format_guid;
2959 WICPixelFormatGUID wic_pixel_format;
2961 D3DFORMAT d3d_pixel_format;
2962 D3DSURFACE_DESC src_surface_desc;
2963 IDirect3DSurface9 *temp_surface;
2964 D3DLOCKED_RECT locked_rect;
2965 int width, height;
2966 STATSTG stream_stats;
2967 HGLOBAL stream_hglobal;
2969 DWORD size;
2970
2971 TRACE("dst_buffer %p, file_format %#x, src_surface %p, src_palette %p, src_rect %s.\n",
2972 dst_buffer, file_format, src_surface, src_palette, wine_dbgstr_rect(src_rect));
2973
2974 if (!dst_buffer || !src_surface) return D3DERR_INVALIDCALL;
2975
2976 IDirect3DSurface9_GetDesc(src_surface, &src_surface_desc);
2977 if (file_format != D3DXIFF_DDS && (src_palette || is_index_format(get_format_info(src_surface_desc.Format))))
2978 {
2979 FIXME("Saving surfaces with palettized pixel formats to non-DDS files is not implemented yet.\n");
2980 return D3DERR_INVALIDCALL;
2981 }
2982
2983 switch (file_format)
2984 {
2985 case D3DXIFF_BMP:
2986 case D3DXIFF_DIB:
2987 container_format = &GUID_ContainerFormatBmp;
2988 break;
2989 case D3DXIFF_PNG:
2990 container_format = &GUID_ContainerFormatPng;
2991 break;
2992 case D3DXIFF_JPG:
2993 container_format = &GUID_ContainerFormatJpeg;
2994 break;
2995 case D3DXIFF_DDS:
2996 return save_dds_surface_to_memory(dst_buffer, src_surface, src_palette, src_rect);
2997 case D3DXIFF_HDR:
2998 case D3DXIFF_PFM:
2999 case D3DXIFF_TGA:
3000 case D3DXIFF_PPM:
3001 FIXME("File format %#x is not supported yet\n", file_format);
3002 return E_NOTIMPL;
3003 default:
3004 return D3DERR_INVALIDCALL;
3005 }
3006
3007 if (src_rect)
3008 {
3009 if (src_rect->left == src_rect->right || src_rect->top == src_rect->bottom)
3010 {
3011 WARN("Invalid rectangle with 0 area\n");
3012 return D3DXCreateBuffer(64, dst_buffer);
3013 }
3014 if (src_rect->left < 0 || src_rect->top < 0)
3015 return D3DERR_INVALIDCALL;
3016 if (src_rect->left > src_rect->right || src_rect->top > src_rect->bottom)
3017 return D3DERR_INVALIDCALL;
3018 if (src_rect->right > src_surface_desc.Width || src_rect->bottom > src_surface_desc.Height)
3019 return D3DERR_INVALIDCALL;
3020
3021 width = src_rect->right - src_rect->left;
3022 height = src_rect->bottom - src_rect->top;
3023 }
3024 else
3025 {
3026 width = src_surface_desc.Width;
3027 height = src_surface_desc.Height;
3028 }
3029
3030 hr = WICCreateImagingFactory_Proxy(WINCODEC_SDK_VERSION, &factory);
3031 if (FAILED(hr)) goto cleanup_err;
3032
3033 hr = IWICImagingFactory_CreateEncoder(factory, container_format, NULL, &encoder);
3034 IWICImagingFactory_Release(factory);
3035 if (FAILED(hr)) goto cleanup_err;
3036
3038 if (FAILED(hr)) goto cleanup_err;
3039
3040 hr = IWICBitmapEncoder_Initialize(encoder, stream, WICBitmapEncoderNoCache);
3041 if (FAILED(hr)) goto cleanup_err;
3042
3043 hr = IWICBitmapEncoder_CreateNewFrame(encoder, &frame, &encoder_options);
3044 if (FAILED(hr)) goto cleanup_err;
3045
3046 hr = IWICBitmapFrameEncode_Initialize(frame, encoder_options);
3047 if (FAILED(hr)) goto cleanup_err;
3048
3049 hr = IWICBitmapFrameEncode_SetSize(frame, width, height);
3050 if (FAILED(hr)) goto cleanup_err;
3051
3052 pixel_format_guid = wic_guid_from_d3dformat(src_surface_desc.Format);
3053 if (!pixel_format_guid)
3054 {
3055 FIXME("Pixel format %#x is not supported yet\n", src_surface_desc.Format);
3056 hr = E_NOTIMPL;
3057 goto cleanup;
3058 }
3059
3060 memcpy(&wic_pixel_format, pixel_format_guid, sizeof(GUID));
3061 hr = IWICBitmapFrameEncode_SetPixelFormat(frame, &wic_pixel_format);
3063 if (SUCCEEDED(hr) && d3d_pixel_format != D3DFMT_UNKNOWN)
3064 {
3065 TRACE("Using pixel format %s %#x\n", debugstr_guid(&wic_pixel_format), d3d_pixel_format);
3066 if (src_surface_desc.Format == d3d_pixel_format) /* Simple copy */
3067 {
3068 if (FAILED(hr = lock_surface(src_surface, src_rect, &locked_rect, &temp_surface, FALSE)))
3069 goto cleanup;
3070
3071 IWICBitmapFrameEncode_WritePixels(frame, height,
3072 locked_rect.Pitch, height * locked_rect.Pitch, locked_rect.pBits);
3073 unlock_surface(src_surface, src_rect, temp_surface, FALSE);
3074 }
3075 else /* Pixel format conversion */
3076 {
3077 const struct pixel_format_desc *src_format_desc, *dst_format_desc;
3078 struct volume size;
3079 DWORD dst_pitch;
3080 void *dst_data;
3081
3082 src_format_desc = get_format_info(src_surface_desc.Format);
3083 dst_format_desc = get_format_info(d3d_pixel_format);
3084 if (!is_conversion_from_supported(src_format_desc)
3085 || !is_conversion_to_supported(dst_format_desc))
3086 {
3087 FIXME("Unsupported format conversion %#x -> %#x.\n",
3088 src_surface_desc.Format, d3d_pixel_format);
3089 hr = E_NOTIMPL;
3090 goto cleanup;
3091 }
3092
3093 size.width = width;
3094 size.height = height;
3095 size.depth = 1;
3096 dst_pitch = width * dst_format_desc->bytes_per_pixel;
3097 dst_data = malloc(dst_pitch * height);
3098 if (!dst_data)
3099 {
3100 hr = E_OUTOFMEMORY;
3101 goto cleanup;
3102 }
3103 if (FAILED(hr = lock_surface(src_surface, src_rect, &locked_rect, &temp_surface, FALSE)))
3104 {
3105 free(dst_data);
3106 goto cleanup;
3107 }
3108 convert_argb_pixels(locked_rect.pBits, locked_rect.Pitch, 0, &size, src_format_desc,
3109 dst_data, dst_pitch, 0, &size, dst_format_desc, 0, NULL);
3110 unlock_surface(src_surface, src_rect, temp_surface, FALSE);
3111
3112 IWICBitmapFrameEncode_WritePixels(frame, height, dst_pitch, dst_pitch * height, dst_data);
3113 free(dst_data);
3114 }
3115
3116 hr = IWICBitmapFrameEncode_Commit(frame);
3117 if (SUCCEEDED(hr)) hr = IWICBitmapEncoder_Commit(encoder);
3118 }
3119 else WARN("Unsupported pixel format %#x\n", src_surface_desc.Format);
3120
3121 /* copy data from stream to ID3DXBuffer */
3122 hr = IStream_Stat(stream, &stream_stats, STATFLAG_NONAME);
3123 if (FAILED(hr)) goto cleanup_err;
3124
3125 if (stream_stats.cbSize.u.HighPart != 0)
3126 {
3128 goto cleanup;
3129 }
3130 size = stream_stats.cbSize.u.LowPart;
3131
3132 /* Remove BMP header for DIB */
3133 if (file_format == D3DXIFF_DIB)
3134 size -= sizeof(BITMAPFILEHEADER);
3135
3137 if (FAILED(hr)) goto cleanup;
3138
3139 hr = GetHGlobalFromStream(stream, &stream_hglobal);
3140 if (SUCCEEDED(hr))
3141 {
3142 void *buffer_pointer = ID3DXBuffer_GetBufferPointer(buffer);
3143 void *stream_data = GlobalLock(stream_hglobal);
3144 /* Remove BMP header for DIB */
3145 if (file_format == D3DXIFF_DIB)
3146 stream_data = (void*)((BYTE*)stream_data + sizeof(BITMAPFILEHEADER));
3147 memcpy(buffer_pointer, stream_data, size);
3148 GlobalUnlock(stream_hglobal);
3149 *dst_buffer = buffer;
3150 }
3152
3153cleanup_err:
3154 if (FAILED(hr) && hr != E_OUTOFMEMORY)
3156
3157cleanup:
3158 if (stream) IStream_Release(stream);
3159
3160 if (frame) IWICBitmapFrameEncode_Release(frame);
3161 if (encoder_options) IPropertyBag2_Release(encoder_options);
3162
3163 if (encoder) IWICBitmapEncoder_Release(encoder);
3164
3165 return hr;
3166}
void tx_compress_dxtn(GLint srccomps, GLint width, GLint height, const GLubyte *srcPixData, GLenum destFormat, GLubyte *dest, GLint dstRowStride)
void fetch_2d_texel_rgba_dxt3(GLint srcRowStride, const GLubyte *pixdata, GLint i, GLint j, GLvoid *texel)
void fetch_2d_texel_rgba_dxt1(GLint srcRowStride, const GLubyte *pixdata, GLint i, GLint j, GLvoid *texel)
void fetch_2d_texel_rgba_dxt5(GLint srcRowStride, const GLubyte *pixdata, GLint i, GLint j, GLvoid *texel)
#define write
Definition: acwin.h:98
static const char * wine_dbgstr_rect(const RECT *prc)
Definition: atltest.h:160
unsigned int channels
Definition: audiorecord.c:89
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define ARRAY_SIZE(A)
Definition: main.h:20
#define FIXME(fmt,...)
Definition: precomp.h:53
#define WARN(fmt,...)
Definition: precomp.h:61
#define ERR(fmt,...)
Definition: precomp.h:57
#define D3DERR_INVALIDCALL
Definition: d3d10_private.h:42
@ D3DTEXF_POINT
Definition: d3d8types.h:871
@ D3DTEXF_NONE
Definition: d3d8types.h:870
@ D3DTEXF_LINEAR
Definition: d3d8types.h:872
@ D3DTEXF_FORCE_DWORD
Definition: d3d8types.h:877
enum _D3DRESOURCETYPE D3DRESOURCETYPE
@ D3DMULTISAMPLE_NONE
Definition: d3d8types.h:672
@ D3DFMT_A8R8G8B8
Definition: d3d8types.h:604
@ D3DFMT_UNKNOWN
Definition: d3d8types.h:601
@ D3DFMT_X8R8G8B8
Definition: d3d8types.h:605
@ D3DRTYPE_TEXTURE
Definition: d3d8types.h:812
@ D3DRTYPE_VOLUMETEXTURE
Definition: d3d8types.h:813
@ D3DRTYPE_CUBETEXTURE
Definition: d3d8types.h:814
@ D3DPOOL_SYSTEMMEM
Definition: d3d8types.h:711
enum _D3DFORMAT D3DFORMAT
enum _D3DTEXTUREFILTERTYPE D3DTEXTUREFILTERTYPE
#define D3DLOCK_READONLY
Definition: d3d8types.h:69
#define IDirect3DSurface9_GetDevice(p, a)
Definition: d3d9.h:452
#define IDirect3DSurface9_LockRect(p, a, b, c)
Definition: d3d9.h:463
#define IDirect3DDevice9_StretchRect(p, a, b, c, d, e)
Definition: d3d9.h:1369
#define IDirect3DSurface9_GetDesc(p, a)
Definition: d3d9.h:462
#define IDirect3DDevice9_Release(p)
Definition: d3d9.h:1336
#define IDirect3DSurface9_UnlockRect(p)
Definition: d3d9.h:464
#define IDirect3DDevice9_UpdateSurface(p, a, b, c, d)
Definition: d3d9.h:1365
#define IDirect3DSurface9_Release(p)
Definition: d3d9.h:450
#define IDirect3DDevice9_CreateRenderTarget(p, a, b, c, d, e, f, g, h)
Definition: d3d9.h:1363
#define IDirect3DDevice9_CreateOffscreenPlainSurface(p, a, b, c, d, e, f)
Definition: d3d9.h:1371
@ D3DFMT_A8B8G8R8
Definition: d3d9types.h:802
@ D3DFMT_A16B16G16R16
Definition: d3d9types.h:806
#define D3D_OK
Definition: d3d.h:106
static SIZE_T datasize
Definition: asm.c:30
#define D3DXERR_INVALIDDATA
Definition: compiler.c:53
struct ID3DXBuffer ID3DXBuffer
Definition: d3dx8core.h:51
#define D3DX_IMAGE_INFO_ONLY
const struct pixel_format_desc * get_format_info(D3DFORMAT format)
Definition: util.c:312
static BOOL is_conversion_to_supported(const struct pixel_format_desc *format)
static BOOL format_types_match(const struct pixel_format_desc *src, const struct pixel_format_desc *dst)
static BOOL is_index_format(const struct pixel_format_desc *format)
HRESULT map_view_of_file(const WCHAR *filename, void **buffer, DWORD *length)
Definition: util.c:211
static BOOL is_unknown_format(const struct pixel_format_desc *format)
float float_16_to_32(const unsigned short in)
Definition: math.c:2203
component_type
@ CTYPE_INDEX
@ CTYPE_SNORM
@ CTYPE_FLOAT
@ CTYPE_LUMA
@ CTYPE_EMPTY
@ CTYPE_UNORM
static void set_volume_struct(struct volume *volume, uint32_t width, uint32_t height, uint32_t depth)
Definition: d3dx9_private.h:86
HRESULT write_buffer_to_file(const WCHAR *filename, ID3DXBuffer *buffer)
Definition: util.c:277
range
Definition: d3dx9_private.h:58
@ RANGE_SNORM
Definition: d3dx9_private.h:61
@ RANGE_FULL
Definition: d3dx9_private.h:59
@ RANGE_UNORM
Definition: d3dx9_private.h:60
const struct pixel_format_desc * get_d3dx_pixel_format_info(enum d3dx_pixel_format_id format)
Definition: util.c:297
static HRESULT d3dx9_handle_load_filter(DWORD *filter)
Definition: d3dx9_private.h:45
static void set_d3dx_pixels(struct d3dx_pixels *pixels, const void *data, uint32_t row_pitch, uint32_t slice_pitch, const PALETTEENTRY *palette, uint32_t width, uint32_t height, uint32_t depth, const RECT *unaligned_rect)
static BOOL is_conversion_from_supported(const struct pixel_format_desc *format)
enum d3dx_pixel_format_id d3dx_pixel_format_id_from_d3dformat(D3DFORMAT format)
Definition: util.c:138
static BOOL is_compressed_format(const struct pixel_format_desc *format)
D3DFORMAT d3dformat_from_d3dx_pixel_format_id(enum d3dx_pixel_format_id format)
Definition: util.c:83
HRESULT load_resource_into_memory(HMODULE module, HRSRC resinfo, void **buffer, DWORD *length)
Definition: util.c:261
d3dx_pixel_format_id
Definition: d3dx9_private.h:95
@ D3DX_PIXEL_FORMAT_R16G16B16A16_UNORM
@ D3DX_PIXEL_FORMAT_R32G32_FLOAT
@ D3DX_PIXEL_FORMAT_U10V10W10_SNORM_A2_UNORM
@ D3DX_PIXEL_FORMAT_DXT4_UNORM
@ D3DX_PIXEL_FORMAT_B2G3R3_UNORM
@ D3DX_PIXEL_FORMAT_U8V8_SNORM_L8X8_UNORM
@ D3DX_PIXEL_FORMAT_B5G5R5A1_UNORM
@ D3DX_PIXEL_FORMAT_R32G32B32A32_FLOAT
@ D3DX_PIXEL_FORMAT_U8V8W8Q8_SNORM
@ D3DX_PIXEL_FORMAT_R16G16_UNORM
@ D3DX_PIXEL_FORMAT_B5G6R5_UNORM
@ D3DX_PIXEL_FORMAT_B10G10R10A2_UNORM
@ D3DX_PIXEL_FORMAT_A8_UNORM
@ D3DX_PIXEL_FORMAT_G8R8_G8B8_UNORM
@ D3DX_PIXEL_FORMAT_R16G16B16A16_FLOAT
@ D3DX_PIXEL_FORMAT_B8G8R8_UNORM
Definition: d3dx9_private.h:96
@ D3DX_PIXEL_FORMAT_R8G8B8X8_UNORM
@ D3DX_PIXEL_FORMAT_R16G16B16_UNORM
@ D3DX_PIXEL_FORMAT_B2G3R3A8_UNORM
@ D3DX_PIXEL_FORMAT_UYVY
@ D3DX_PIXEL_FORMAT_U16V16_SNORM
@ D3DX_PIXEL_FORMAT_U16V16W16Q16_SNORM
@ D3DX_PIXEL_FORMAT_R16_FLOAT
@ D3DX_PIXEL_FORMAT_P8_UINT_A8_UNORM
@ D3DX_PIXEL_FORMAT_B4G4R4A4_UNORM
@ D3DX_PIXEL_FORMAT_B5G5R5X1_UNORM
@ D3DX_PIXEL_FORMAT_U8V8_SNORM
@ D3DX_PIXEL_FORMAT_B8G8R8X8_UNORM
Definition: d3dx9_private.h:98
@ D3DX_PIXEL_FORMAT_R8G8B8A8_UNORM
Definition: d3dx9_private.h:99
@ D3DX_PIXEL_FORMAT_DXT3_UNORM
@ D3DX_PIXEL_FORMAT_DXT2_UNORM
@ D3DX_PIXEL_FORMAT_COUNT
@ D3DX_PIXEL_FORMAT_R10G10B10A2_UNORM
@ D3DX_PIXEL_FORMAT_R16G16_FLOAT
@ D3DX_PIXEL_FORMAT_L8_UNORM
@ D3DX_PIXEL_FORMAT_YUY2
@ D3DX_PIXEL_FORMAT_R32_FLOAT
@ D3DX_PIXEL_FORMAT_L4A4_UNORM
@ D3DX_PIXEL_FORMAT_P8_UINT
@ D3DX_PIXEL_FORMAT_DXT1_UNORM
@ D3DX_PIXEL_FORMAT_L8A8_UNORM
@ D3DX_PIXEL_FORMAT_DXT5_UNORM
@ D3DX_PIXEL_FORMAT_L16_UNORM
@ D3DX_PIXEL_FORMAT_B8G8R8A8_UNORM
Definition: d3dx9_private.h:97
@ D3DX_PIXEL_FORMAT_B4G4R4X4_UNORM
@ D3DX_PIXEL_FORMAT_R8G8_B8G8_UNORM
unsigned short float_32_to_16(const float in)
Definition: math.c:2102
static const uint8_t pixdata[]
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define E_NOTIMPL
Definition: ddrawi.h:99
#define E_FAIL
Definition: ddrawi.h:102
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
HRESULT hr
Definition: delayimp.cpp:582
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
INT32 int32_t
Definition: types.h:71
UINT32 uint32_t
Definition: types.h:75
D3DX10_IMAGE_FILE_FORMAT d3dx_file_format
Definition: texture.c:35
HRESULT WINAPI D3DXCreateBuffer(DWORD size, ID3DXBuffer **buffer)
Definition: core.c:127
HRESULT WINAPI D3DXLoadSurfaceFromMemory(IDirect3DSurface9 *dst_surface, const PALETTEENTRY *dst_palette, const RECT *dst_rect, const void *src_memory, D3DFORMAT src_format, UINT src_pitch, const PALETTEENTRY *src_palette, const RECT *src_rect, DWORD filter, D3DCOLOR color_key)
Definition: surface.c:2702
static HRESULT d3dx_initialize_image_from_tga(const void *src_data, uint32_t src_data_size, struct d3dx_image *image, uint32_t flags)
Definition: surface.c:1279
void format_from_d3dx_color(const struct pixel_format_desc *format, const struct d3dx_color *src, BYTE *dst)
Definition: surface.c:2051
HRESULT WINAPI D3DXLoadSurfaceFromFileA(IDirect3DSurface9 *dst_surface, const PALETTEENTRY *dst_palette, const RECT *dst_rect, const char *src_file, const RECT *src_rect, DWORD filter, D3DCOLOR color_key, D3DXIMAGE_INFO *src_info)
Definition: surface.c:1745
HRESULT WINAPI D3DXGetImageInfoFromFileInMemory(const void *data, UINT datasize, D3DXIMAGE_INFO *info)
Definition: surface.c:1489
static const char * debug_volume(const struct volume *volume)
Definition: surface.c:419
HRESULT unlock_surface(IDirect3DSurface9 *surface, const RECT *surface_rect, IDirect3DSurface9 *temp_surface, BOOL update)
Definition: surface.c:214
static const uint8_t dds_file_signature[]
Definition: surface.c:634
static const struct @284 wic_pixel_formats[]
static const GUID * d3dx_file_format_to_wic_container_guid(D3DXIMAGE_FILEFORMAT iff)
Definition: surface.c:874
static HRESULT d3dx_save_pixels_to_memory(struct d3dx_pixels *src_pixels, const struct pixel_format_desc *src_fmt_desc, D3DXIMAGE_FILEFORMAT file_format, ID3DXBuffer **dst_buffer)
Definition: surface.c:493
#define DDS_CAPS
Definition: surface.c:85
#define DDS_HEIGHT
Definition: surface.c:86
const GUID * wic_guid
Definition: surface.c:37
static const uint8_t ppm_raw_file_signature[]
Definition: surface.c:636
void get_aligned_rect(uint32_t left, uint32_t top, uint32_t right, uint32_t bottom, uint32_t width, uint32_t height, const struct pixel_format_desc *fmt_desc, RECT *aligned_rect)
Definition: surface.c:2654
#define DDS_CAPS2_CUBEMAP_ALL_FACES
Definition: surface.c:109
static void d3dx_get_next_mip_level_size(struct volume *size)
Definition: surface.c:412
HRESULT WINAPI D3DXGetImageInfoFromResourceA(HMODULE module, const char *resource, D3DXIMAGE_INFO *info)
Definition: surface.c:1572
static BOOL convert_dib_to_bmp(const void **data, unsigned int *size)
Definition: surface.c:768
static BOOL d3dx_get_image_file_format_from_file_signature(const void *src_data, uint32_t src_data_size, D3DXIMAGE_FILEFORMAT *out_iff)
Definition: surface.c:665
HRESULT lock_surface(IDirect3DSurface9 *surface, const RECT *surface_rect, D3DLOCKED_RECT *lock, IDirect3DSurface9 **temp_surface, BOOL write)
Definition: surface.c:156
static HRESULT dds_pixel_format_from_d3dx_pixel_format_id(struct dds_pixel_format *pixel_format, enum d3dx_pixel_format_id d3dx_pixel_format)
Definition: surface.c:385
#define IMAGETYPE_MASK
Definition: surface.c:1091
static const struct d3dx_file_format_signature file_format_signatures[]
Definition: surface.c:652
#define DDS_PF_RGB
Definition: surface.c:119
HRESULT WINAPI D3DXGetImageInfoFromFileW(const WCHAR *file, D3DXIMAGE_INFO *info)
Definition: surface.c:1543
HRESULT d3dx_load_pixels_from_pixels(struct d3dx_pixels *dst_pixels, const struct pixel_format_desc *dst_desc, struct d3dx_pixels *src_pixels, const struct pixel_format_desc *src_desc, uint32_t filter_flags, uint32_t color_key)
Definition: surface.c:2498
static HRESULT d3dx_image_wic_frame_decode(struct d3dx_image *image, IWICImagingFactory *wic_factory, IWICBitmapFrameDecode *bitmap_frame)
Definition: surface.c:907
HRESULT WINAPI D3DXSaveSurfaceToFileA(const char *dst_filename, D3DXIMAGE_FILEFORMAT file_format, IDirect3DSurface9 *src_surface, const PALETTEENTRY *src_palette, const RECT *src_rect)
Definition: surface.c:2899
#define DDS_CAPS_TEXTURE
Definition: surface.c:98
static const char * debug_d3dx_image_file_format(D3DXIMAGE_FILEFORMAT format)
Definition: surface.c:887
enum d3dx_pixel_format_id d3dx_pixel_format
Definition: surface.c:38
#define IMAGETYPE_COLORMAPPED
Definition: surface.c:1088
HRESULT WINAPI D3DXLoadSurfaceFromFileW(IDirect3DSurface9 *dst_surface, const PALETTEENTRY *dst_palette, const RECT *dst_rect, const WCHAR *src_file, const RECT *src_rect, DWORD filter, D3DCOLOR color_key, D3DXIMAGE_INFO *src_info)
Definition: surface.c:1772
static const GUID * wic_guid_from_d3dformat(D3DFORMAT format)
Definition: surface.c:68
static const uint8_t pfm_color_file_signature[]
Definition: surface.c:638
void d3dx_image_cleanup(struct d3dx_image *image)
Definition: surface.c:1392
static BOOL dds_pixel_format_compare(const struct dds_pixel_format *pf_a, const struct dds_pixel_format *pf_b, BOOL check_rmask, BOOL check_gmask, BOOL check_bmask, BOOL check_amask)
Definition: surface.c:312
static HRESULT d3dx_image_tga_decode(const void *src_data, uint32_t src_data_size, uint32_t src_header_size, struct d3dx_image *image)
Definition: surface.c:1153
static enum range get_range_for_component_type(enum component_type type)
Definition: surface.c:1955
#define DDS_PF_LUMINANCE
Definition: surface.c:121
void convert_argb_pixels(const BYTE *src, UINT src_row_pitch, UINT src_slice_pitch, const struct volume *src_size, const struct pixel_format_desc *src_format, BYTE *dst, UINT dst_row_pitch, UINT dst_slice_pitch, const struct volume *dst_size, const struct pixel_format_desc *dst_format, D3DCOLOR color_key, const PALETTEENTRY *palette)
Definition: surface.c:2180
static void init_argb_conversion_info(const struct pixel_format_desc *srcformat, const struct pixel_format_desc *destformat, struct argb_conversion_info *info)
Definition: surface.c:1868
HRESULT WINAPI D3DXSaveSurfaceToFileInMemory(ID3DXBuffer **dst_buffer, D3DXIMAGE_FILEFORMAT file_format, IDirect3DSurface9 *src_surface, const PALETTEENTRY *src_palette, const RECT *src_rect)
Definition: surface.c:2949
HRESULT WINAPI D3DXGetImageInfoFromFileA(const char *file, D3DXIMAGE_INFO *info)
Definition: surface.c:1523
static HRESULT d3dx_init_dds_header(struct dds_header *header, D3DRESOURCETYPE resource_type, enum d3dx_pixel_format_id format, const struct volume *size, uint32_t mip_levels)
Definition: surface.c:468
#define DDS_PF_BUMPLUMINANCE
Definition: surface.c:122
HRESULT WINAPI D3DXGetImageInfoFromResourceW(HMODULE module, const WCHAR *resource, D3DXIMAGE_INFO *info)
Definition: surface.c:1591
#define DDSCAPS_PALETTE
Definition: surface.c:97
#define DDS_PF_BUMPDUDV
Definition: surface.c:123
HRESULT WINAPI D3DXLoadSurfaceFromResourceA(IDirect3DSurface9 *dst_surface, const PALETTEENTRY *dst_palette, const RECT *dst_rect, HMODULE src_module, const char *resource, const RECT *src_rect, DWORD filter, D3DCOLOR color_key, D3DXIMAGE_INFO *src_info)
Definition: surface.c:1798
void format_to_d3dx_color(const struct pixel_format_desc *format, const BYTE *src, const PALETTEENTRY *palette, struct d3dx_color *dst)
Definition: surface.c:1978
#define DDS_DEPTH
Definition: surface.c:92
HRESULT WINAPI D3DXLoadSurfaceFromResourceW(IDirect3DSurface9 *dst_surface, const PALETTEENTRY *dst_palette, const RECT *dst_rect, HMODULE src_module, const WCHAR *resource, const RECT *src_rect, DWORD filter, D3DCOLOR color_key, D3DXIMAGE_INFO *src_info)
Definition: surface.c:1826
static BOOL image_is_argb(IWICBitmapFrameDecode *frame, struct d3dx_image *image)
Definition: surface.c:835
static HRESULT save_dds_surface_to_memory(ID3DXBuffer **dst_buffer, IDirect3DSurface9 *src_surface, const PALETTEENTRY *src_palette, const RECT *src_rect)
Definition: surface.c:562
#define DDS_PALETTE_SIZE
Definition: surface.c:82
static const uint8_t jpg_file_signature[]
Definition: surface.c:632
void copy_pixels(const BYTE *src, UINT src_row_pitch, UINT src_slice_pitch, BYTE *dst, UINT dst_row_pitch, UINT dst_slice_pitch, const struct volume *size, const struct pixel_format_desc *format)
Definition: surface.c:2149
static const uint8_t bmp_file_signature[]
Definition: surface.c:631
static const uint8_t hdr_file_signature[]
Definition: surface.c:637
#define DDS_PF_INDEXED
Definition: surface.c:118
HRESULT WINAPI D3DXLoadSurfaceFromSurface(IDirect3DSurface9 *dst_surface, const PALETTEENTRY *dst_palette, const RECT *dst_rect, IDirect3DSurface9 *src_surface, const PALETTEENTRY *src_palette, const RECT *src_rect, DWORD filter, D3DCOLOR color_key)
Definition: surface.c:2765
#define IMAGE_RIGHTTOLEFT
Definition: surface.c:1094
#define DDS_PF_ALPHA_ONLY
Definition: surface.c:116
static const uint8_t ppm_plain_file_signature[]
Definition: surface.c:635
static void get_relevant_argb_components(const struct argb_conversion_info *info, const BYTE *col, DWORD *out)
Definition: surface.c:1901
static HRESULT d3dx_load_surface_from_memory(IDirect3DSurface9 *dst_surface, const PALETTEENTRY *dst_palette, const RECT *dst_rect, const void *src_memory, enum d3dx_pixel_format_id src_format, uint32_t src_pitch, const PALETTEENTRY *src_palette, const RECT *src_rect, DWORD filter, D3DCOLOR color_key)
Definition: surface.c:1610
static enum d3dx_pixel_format_id d3dx_pixel_format_id_from_wic_pixel_format(const GUID *guid)
Definition: surface.c:54
HRESULT WINAPI D3DXLoadSurfaceFromFileInMemory(IDirect3DSurface9 *pDestSurface, const PALETTEENTRY *pDestPalette, const RECT *pDestRect, const void *pSrcData, UINT SrcDataSize, const RECT *pSrcRect, DWORD dwFilter, D3DCOLOR Colorkey, D3DXIMAGE_INFO *pSrcInfo)
Definition: surface.c:1700
#define DDSCAPS_ALPHA
Definition: surface.c:95
#define IMAGE_TOPTOBOTTOM
Definition: surface.c:1095
static const uint8_t pfm_gray_file_signature[]
Definition: surface.c:639
static const struct @285 dds_pixel_formats[]
HRESULT d3dx_image_init(const void *src_data, uint32_t src_data_size, struct d3dx_image *image, uint32_t starting_mip_level, uint32_t flags)
Definition: surface.c:1332
static HRESULT d3dx_initialize_image_from_wic(const void *src_data, uint32_t src_data_size, struct d3dx_image *image, D3DXIMAGE_FILEFORMAT d3dx_file_format, uint32_t flags)
Definition: surface.c:987
#define DDS_PIXELFORMAT
Definition: surface.c:89
static HRESULT d3dx_initialize_image_from_dds(const void *src_data, uint32_t src_data_size, struct d3dx_image *image, uint32_t starting_mip_level)
Definition: surface.c:685
static HRESULT d3dx_pixels_decompress(struct d3dx_pixels *pixels, const struct pixel_format_desc *desc, BOOL is_dst, void **out_memory, uint32_t *out_row_pitch, uint32_t *out_slice_pitch, const struct pixel_format_desc **out_desc)
Definition: surface.c:2364
HRESULT WINAPI D3DXSaveSurfaceToFileW(const WCHAR *dst_filename, D3DXIMAGE_FILEFORMAT file_format, IDirect3DSurface9 *src_surface, const PALETTEENTRY *src_palette, const RECT *src_rect)
Definition: surface.c:2928
static enum d3dx_pixel_format_id d3dx_get_tga_format_for_bpp(uint8_t bpp)
Definition: surface.c:1074
#define DDS_CAPS2_CUBEMAP
Definition: surface.c:102
HRESULT d3dx_image_get_pixels(struct d3dx_image *image, uint32_t layer, uint32_t mip_level, struct d3dx_pixels *pixels)
Definition: surface.c:1398
static const char * debug_d3dx_pixels(struct d3dx_pixels *pixels)
Definition: surface.c:2489
#define DDS_WIDTH
Definition: surface.c:87
static HRESULT d3dx_image_tga_rle_decode_row(const uint8_t **src, uint32_t src_bytes_left, uint32_t row_width, uint32_t bytes_per_pixel, uint8_t *dst_row)
Definition: surface.c:1115
static enum d3dx_pixel_format_id d3dx_pixel_format_id_from_dds_pixel_format(const struct dds_pixel_format *pixel_format)
Definition: surface.c:320
#define IMAGETYPE_GRAYSCALE
Definition: surface.c:1090
HRESULT WINAPI WICCreateImagingFactory_Proxy(UINT, IWICImagingFactory **)
Definition: proxy.c:649
static HRESULT d3dx_calculate_pixels_size(enum d3dx_pixel_format_id format, uint32_t width, uint32_t height, uint32_t *pitch, uint32_t *size)
Definition: surface.c:426
#define DDS_PF_FOURCC
Definition: surface.c:117
#define IMAGETYPE_RLE
Definition: surface.c:1092
static const uint8_t png_file_signature[]
Definition: surface.c:633
#define FMT_TO_STR(format)
#define IMAGETYPE_TRUECOLOR
Definition: surface.c:1089
void point_filter_argb_pixels(const BYTE *src, UINT src_row_pitch, UINT src_slice_pitch, const struct volume *src_size, const struct pixel_format_desc *src_format, BYTE *dst, UINT dst_row_pitch, UINT dst_slice_pitch, const struct volume *dst_size, const struct pixel_format_desc *dst_format, D3DCOLOR color_key, const PALETTEENTRY *palette)
Definition: surface.c:2280
static float d3dx_clamp(float value, float min_value, float max_value)
Definition: surface.c:1925
HRESULT d3dx_pixels_init(const void *data, uint32_t row_pitch, uint32_t slice_pitch, const PALETTEENTRY *palette, enum d3dx_pixel_format_id format, uint32_t left, uint32_t top, uint32_t right, uint32_t bottom, uint32_t front, uint32_t back, struct d3dx_pixels *pixels)
Definition: surface.c:2450
static uint32_t d3dx_calculate_layer_pixels_size(enum d3dx_pixel_format_id format, uint32_t width, uint32_t height, uint32_t depth, uint32_t mip_levels)
Definition: surface.c:450
static DWORD make_argb_color(const struct argb_conversion_info *info, const DWORD *in)
Definition: surface.c:1938
#define DDS_PF_ALPHA
Definition: surface.c:115
void d3dximage_info_from_d3dx_image(D3DXIMAGE_INFO *info, struct d3dx_image *image)
Definition: surface.c:1441
#define CHAR_BIT
Definition: cabinet.h:45
HRESULT WINAPI GetHGlobalFromStream(IStream *stream, HGLOBAL *phglobal)
HRESULT WINAPI CreateStreamOnHGlobal(HGLOBAL hGlobal, BOOL delete_on_release, IStream **stream)
const char * wine_dbg_sprintf(const char *format,...)
Definition: compat.c:296
#define UnmapViewOfFile
Definition: compat.h:746
#define CP_ACP
Definition: compat.h:109
#define MultiByteToWideChar
Definition: compat.h:110
static void cleanup(void)
Definition: main.c:1335
HRSRC WINAPI FindResourceW(HINSTANCE hModule, LPCWSTR name, LPCWSTR type)
Definition: res.c:176
HRSRC WINAPI FindResourceA(HMODULE hModule, LPCSTR name, LPCSTR type)
Definition: res.c:155
GUID guid
Definition: version.c:147
#define assert(_expr)
Definition: assert.h:32
_ACRTIMP int __cdecl memcmp(const void *, const void *, size_t)
Definition: string.c:2807
#define isnan(x)
Definition: math.h:360
unsigned short uint16_t
Definition: stdint.h:35
unsigned char uint8_t
Definition: stdint.h:33
static BOOL is_dst(const SYSTEMTIME *st)
Definition: time.c:196
#define byte(x, n)
Definition: tomcrypt.h:118
#define MAKEFOURCC(ch0, ch1, ch2, ch3)
Definition: ddsformat.c:45
struct png_info_def *typedef unsigned char **typedef struct png_info_def *typedef struct png_info_def *typedef struct png_info_def *typedef unsigned char ** row
Definition: typeof.h:78
#define pt(x, y)
Definition: drawing.c:79
ULONG RGBQUAD
Definition: precomp.h:47
D3DXIMAGE_FILEFORMAT
Definition: dx8vb.idl:61
@ D3DXIFF_JPG
Definition: dx8vb.idl:63
@ D3DXIFF_DDS
Definition: dx8vb.idl:66
@ D3DXIFF_BMP
Definition: dx8vb.idl:62
@ D3DXIFF_TGA
Definition: dx8vb.idl:64
@ D3DXIFF_DIB
Definition: dx8vb.idl:68
@ D3DXIFF_FORCE_DWORD
Definition: dx8vb.idl:69
@ D3DXIFF_PPM
Definition: dx8vb.idl:67
@ D3DXIFF_PNG
Definition: dx8vb.idl:65
#define ID3DXBuffer_GetBufferPointer(p)
Definition: d3dx9core.h:85
#define ID3DXBuffer_Release(p)
Definition: d3dx9core.h:83
#define D3DX_FILTER_LINEAR
Definition: d3dx9tex.h:29
#define D3DX_FILTER_POINT
Definition: d3dx9tex.h:28
@ D3DXIFF_HDR
Definition: d3dx9tex.h:71
@ D3DXIFF_PFM
Definition: d3dx9tex.h:72
#define D3DX_FILTER_NONE
Definition: d3dx9tex.h:27
DWORD IDirect3DSurface9
Definition: dxva2api.idl:23
DWORD IDirect3DDevice9
Definition: dxva2api.idl:22
size_t const new_size
Definition: expand.cpp:66
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLint GLint GLsizei GLsizei GLsizei depth
Definition: gl.h:1546
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
const GLdouble * v
Definition: gl.h:2040
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLint GLint GLsizei GLsizei height
Definition: gl.h:1546
GLint GLint GLsizei GLsizei GLsizei GLint GLenum GLenum const GLvoid * pixels
Definition: gl.h:1546
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
unsigned int GLenum
Definition: gl.h:150
GLdouble s
Definition: gl.h:2039
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLint GLint GLsizei width
Definition: gl.h:1546
GLenum src
Definition: glext.h:6340
GLuint buffer
Definition: glext.h:5915
GLsizeiptr size
Definition: glext.h:5919
GLintptr offset
Definition: glext.h:5920
GLuint color
Definition: glext.h:6243
const GLubyte * c
Definition: glext.h:8905
GLenum GLint GLuint mask
Definition: glext.h:6028
GLdouble GLdouble GLdouble GLdouble top
Definition: glext.h:10859
#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
Definition: glext.h:3492
GLdouble GLdouble right
Definition: glext.h:10859
GLuint in
Definition: glext.h:9616
GLint left
Definition: glext.h:7726
GLenum GLenum dst
Definition: glext.h:6340
GLbitfield flags
Definition: glext.h:7161
GLint GLint bottom
Definition: glext.h:7726
GLuint GLfloat * val
Definition: glext.h:7180
#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
Definition: glext.h:3491
#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
Definition: glext.h:3490
GLenum GLuint GLint GLint layer
Definition: glext.h:7007
GLenum GLsizei len
Definition: glext.h:6722
GLdouble GLdouble z
Definition: glext.h:5874
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble * u
Definition: glfuncs.h:240
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
unsigned int UINT
Definition: sysinfo.c:13
BOOL NTAPI GlobalUnlock(HGLOBAL hMem)
Definition: heapmem.c:1190
#define S_OK
Definition: intsafe.h:52
#define SUCCEEDED(hr)
Definition: intsafe.h:50
#define FAILED(hr)
Definition: intsafe.h:51
const char * filename
Definition: ioapi.h:137
static ERESOURCE GlobalLock
Definition: sys_arch.c:8
#define c
Definition: ke_i.h:80
#define debugstr_guid
Definition: kernel32.h:35
#define debugstr_a
Definition: kernel32.h:31
#define debugstr_w
Definition: kernel32.h:32
#define wine_dbgstr_w
Definition: kernel32.h:34
if(dx< 0)
Definition: linetemp.h:194
#define ZeroMemory
Definition: minwinbase.h:31
#define CopyMemory
Definition: minwinbase.h:29
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define BI_BITFIELDS
Definition: mmreg.h:507
static PVOID ptr
Definition: dispmode.c:27
D3D11_SHADER_VARIABLE_DESC desc
Definition: reflection.c:1683
static const char * dst_format
Definition: dib.c:1339
static const char stream_data[]
Definition: mlang.c:2412
static float(__cdecl *square_half_float)(float x
static HPALETTE palette
Definition: clipboard.c:1457
#define shift
Definition: input.c:3280
#define min(a, b)
Definition: monoChain.cc:55
#define RT_BITMAP
Definition: pedump.c:364
short WCHAR
Definition: pedump.c:58
#define RT_RCDATA
Definition: pedump.c:372
#define IsEqualGUID(rguid1, rguid2)
Definition: guiddef.h:147
BOOL WINAPI PtInRect(_In_ LPCRECT, _In_ POINT)
BOOL WINAPI OffsetRect(_Inout_ LPRECT, _In_ int, _In_ int)
BOOL WINAPI EqualRect(_In_ LPCRECT, _In_ LPCRECT)
BOOL WINAPI SetRect(_Out_ LPRECT, _In_ int, _In_ int, _In_ int, _In_ int)
static struct address_cache * front
Definition: rpcb_clnt.c:83
int int static __inline const char * wine_dbgstr_a(const char *s)
Definition: debug.h:160
#define exit(n)
Definition: config.h:202
#define memset(x, y, z)
Definition: compat.h:39
#define TRACE(s)
Definition: solgame.cpp:4
DWORD biCompression
Definition: amvideo.idl:35
long y
Definition: dcommon.idl:24
long x
Definition: dcommon.idl:24
Definition: dcommon.idl:28
long bottom
Definition: dcommon.idl:29
long right
Definition: dcommon.idl:29
long left
Definition: dcommon.idl:29
long top
Definition: dcommon.idl:29
D3DFORMAT Format
Definition: d3d8types.h:1170
const struct pixel_format_desc * destformat
Definition: surface.c:1861
BOOL process_channel[4]
Definition: surface.c:1864
DWORD destshift[4]
Definition: surface.c:1862
const struct pixel_format_desc * srcformat
Definition: surface.c:1860
struct vec4 value
Definition: d3dx9_private.h:66
D3DXIMAGE_FILEFORMAT image_file_format
Definition: surface.c:649
const uint8_t * file_signature
Definition: surface.c:647
const PALETTEENTRY * palette
uint32_t row_pitch
struct volume size
RECT unaligned_rect
const void * data
uint32_t slice_pitch
const GUID * wic_container_guid
Definition: surface.c:870
D3DXIMAGE_FILEFORMAT d3dx_file_format
Definition: surface.c:871
DWORD caps3
Definition: surface.c:151
DWORD signature
Definition: surface.c:139
DWORD depth
Definition: surface.c:145
DWORD reserved[11]
Definition: surface.c:147
DWORD reserved2
Definition: surface.c:153
DWORD flags
Definition: surface.c:141
DWORD width
Definition: surface.c:143
DWORD caps2
Definition: surface.c:150
DWORD caps
Definition: surface.c:149
DWORD pitch_or_linear_size
Definition: surface.c:144
DWORD size
Definition: surface.c:140
DWORD miplevels
Definition: surface.c:146
DWORD height
Definition: surface.c:142
DWORD caps4
Definition: surface.c:152
Definition: devices.h:37
Definition: main.c:439
Definition: fci.c:123
Definition: filter.c:165
Definition: image.c:84
enum d3dx_pixel_format_id format
Definition: parse.h:23
uint16_t width
Definition: surface.c:1108
uint8_t id_length
Definition: surface.c:1100
uint16_t color_map_firstentry
Definition: surface.c:1103
uint8_t depth
Definition: surface.c:1110
uint16_t height
Definition: surface.c:1109
uint8_t color_map_entrysize
Definition: surface.c:1105
uint16_t color_map_length
Definition: surface.c:1104
uint8_t image_descriptor
Definition: surface.c:1111
uint8_t color_map_type
Definition: surface.c:1101
uint16_t yorigin
Definition: surface.c:1107
uint8_t image_type
Definition: surface.c:1102
uint16_t xorigin
Definition: surface.c:1106
UINT depth
Definition: d3dx9_private.h:83
UINT height
Definition: d3dx9_private.h:82
UINT width
Definition: d3dx9_private.h:81
#define max(a, b)
Definition: svc.c:63
rwlock_t lock
Definition: tcpcore.h:0
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
uint32_t ULONG
Definition: typedefs.h:59
Definition: pdh_main.c:64
wchar_t tm const _CrtWcstime_Writes_and_advances_ptr_ count wchar_t ** out
Definition: wcsftime.cpp:383
@ WICBitmapEncoderNoCache
Definition: wincodec.idl:73
UINT32 WICColor
Definition: wincodec.idl:364
#define WINAPI
Definition: msvc.h:6
struct tagBITMAPFILEHEADER BITMAPFILEHEADER
ULONG bpp[]
Definition: xlate.c:19
unsigned char BYTE
Definition: xxhash.c:193