ReactOS  0.4.15-dev-3326-ga91f5e8
surface.c
Go to the documentation of this file.
1 #ifdef __REACTOS__
2 #include "precomp.h"
3 #else
4 /*
5  * Copyright (C) 2009-2010 Tony Wasserka
6  * Copyright (C) 2012 J√≥zef Kucia
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  *
22  */
23 
24 
25 #include "d3dx9_private.h"
26 
27 #include "initguid.h"
28 #include "ole2.h"
29 #include "wincodec.h"
30 
31 #include "txc_dxtn.h"
32 #endif /* __REACTOS__ */
33 
35 
37 
38 /* Wine-specific WIC GUIDs */
39 DEFINE_GUID(GUID_WineContainerFormatTga, 0x0c44fda1,0xa5c5,0x4298,0x96,0x85,0x47,0x3f,0xc1,0x7c,0xd3,0x22);
40 
41 static const struct
42 {
43  const GUID *wic_guid;
45 } wic_pixel_formats[] = {
46  { &GUID_WICPixelFormat8bppIndexed, D3DFMT_P8 },
47  { &GUID_WICPixelFormat1bppIndexed, D3DFMT_P8 },
48  { &GUID_WICPixelFormat4bppIndexed, D3DFMT_P8 },
49  { &GUID_WICPixelFormat8bppGray, D3DFMT_L8 },
50  { &GUID_WICPixelFormat16bppBGR555, D3DFMT_X1R5G5B5 },
51  { &GUID_WICPixelFormat16bppBGR565, D3DFMT_R5G6B5 },
52  { &GUID_WICPixelFormat24bppBGR, D3DFMT_R8G8B8 },
53  { &GUID_WICPixelFormat32bppBGR, D3DFMT_X8R8G8B8 },
54  { &GUID_WICPixelFormat32bppBGRA, D3DFMT_A8R8G8B8 }
55 };
56 
58 {
59  unsigned int i;
60 
61  for (i = 0; i < ARRAY_SIZE(wic_pixel_formats); i++)
62  {
65  }
66 
67  return D3DFMT_UNKNOWN;
68 }
69 
71 {
72  unsigned int i;
73 
74  for (i = 0; i < ARRAY_SIZE(wic_pixel_formats); i++)
75  {
77  return wic_pixel_formats[i].wic_guid;
78  }
79 
80  return NULL;
81 }
82 
83 /* dds_header.flags */
84 #define DDS_CAPS 0x1
85 #define DDS_HEIGHT 0x2
86 #define DDS_WIDTH 0x4
87 #define DDS_PITCH 0x8
88 #define DDS_PIXELFORMAT 0x1000
89 #define DDS_MIPMAPCOUNT 0x20000
90 #define DDS_LINEARSIZE 0x80000
91 #define DDS_DEPTH 0x800000
92 
93 /* dds_header.caps */
94 #define DDS_CAPS_COMPLEX 0x8
95 #define DDS_CAPS_TEXTURE 0x1000
96 #define DDS_CAPS_MIPMAP 0x400000
97 
98 /* dds_header.caps2 */
99 #define DDS_CAPS2_CUBEMAP 0x200
100 #define DDS_CAPS2_CUBEMAP_POSITIVEX 0x400
101 #define DDS_CAPS2_CUBEMAP_NEGATIVEX 0x800
102 #define DDS_CAPS2_CUBEMAP_POSITIVEY 0x1000
103 #define DDS_CAPS2_CUBEMAP_NEGATIVEY 0x2000
104 #define DDS_CAPS2_CUBEMAP_POSITIVEZ 0x4000
105 #define DDS_CAPS2_CUBEMAP_NEGATIVEZ 0x8000
106 #define DDS_CAPS2_CUBEMAP_ALL_FACES ( DDS_CAPS2_CUBEMAP_POSITIVEX | DDS_CAPS2_CUBEMAP_NEGATIVEX \
107  | DDS_CAPS2_CUBEMAP_POSITIVEY | DDS_CAPS2_CUBEMAP_NEGATIVEY \
108  | DDS_CAPS2_CUBEMAP_POSITIVEZ | DDS_CAPS2_CUBEMAP_NEGATIVEZ )
109 #define DDS_CAPS2_VOLUME 0x200000
110 
111 /* dds_pixel_format.flags */
112 #define DDS_PF_ALPHA 0x1
113 #define DDS_PF_ALPHA_ONLY 0x2
114 #define DDS_PF_FOURCC 0x4
115 #define DDS_PF_INDEXED 0x20
116 #define DDS_PF_RGB 0x40
117 #define DDS_PF_YUV 0x200
118 #define DDS_PF_LUMINANCE 0x20000
119 #define DDS_PF_BUMPLUMINANCE 0x40000
120 #define DDS_PF_BUMPDUDV 0x80000
121 
123 {
132 };
133 
135 {
151 };
152 
154 {
155  unsigned int i;
156  static const DWORD known_fourcc[] = {
157  D3DFMT_UYVY,
158  D3DFMT_YUY2,
161  D3DFMT_DXT1,
162  D3DFMT_DXT2,
163  D3DFMT_DXT3,
164  D3DFMT_DXT4,
165  D3DFMT_DXT5,
166  D3DFMT_R16F,
169  D3DFMT_R32F,
172  };
173 
174  for (i = 0; i < ARRAY_SIZE(known_fourcc); i++)
175  {
176  if (known_fourcc[i] == fourcc)
177  return fourcc;
178  }
179 
180  WARN("Unknown FourCC %#x\n", fourcc);
181  return D3DFMT_UNKNOWN;
182 }
183 
184 static const struct {
191 } rgb_pixel_formats[] = {
192  { 8, 0xe0, 0x1c, 0x03, 0, D3DFMT_R3G3B2 },
193  { 16, 0xf800, 0x07e0, 0x001f, 0x0000, D3DFMT_R5G6B5 },
194  { 16, 0x7c00, 0x03e0, 0x001f, 0x8000, D3DFMT_A1R5G5B5 },
195  { 16, 0x7c00, 0x03e0, 0x001f, 0x0000, D3DFMT_X1R5G5B5 },
196  { 16, 0x0f00, 0x00f0, 0x000f, 0xf000, D3DFMT_A4R4G4B4 },
197  { 16, 0x0f00, 0x00f0, 0x000f, 0x0000, D3DFMT_X4R4G4B4 },
198  { 16, 0x00e0, 0x001c, 0x0003, 0xff00, D3DFMT_A8R3G3B2 },
199  { 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000, D3DFMT_R8G8B8 },
200  { 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000, D3DFMT_A8R8G8B8 },
201  { 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000, D3DFMT_X8R8G8B8 },
202  { 32, 0x3ff00000, 0x000ffc00, 0x000003ff, 0xc0000000, D3DFMT_A2B10G10R10 },
203  { 32, 0x000003ff, 0x000ffc00, 0x3ff00000, 0xc0000000, D3DFMT_A2R10G10B10 },
204  { 32, 0x0000ffff, 0xffff0000, 0x00000000, 0x00000000, D3DFMT_G16R16 },
205  { 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000, D3DFMT_A8B8G8R8 },
206  { 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000, D3DFMT_X8B8G8R8 },
207 };
208 
209 HRESULT lock_surface(IDirect3DSurface9 *surface, const RECT *surface_rect, D3DLOCKED_RECT *lock,
210  IDirect3DSurface9 **temp_surface, BOOL write)
211 {
212  unsigned int width, height;
213  IDirect3DDevice9 *device;
215  DWORD lock_flag;
216  HRESULT hr;
217 
218  lock_flag = write ? 0 : D3DLOCK_READONLY;
219  *temp_surface = NULL;
220  if (FAILED(hr = IDirect3DSurface9_LockRect(surface, lock, surface_rect, lock_flag)))
221  {
223  IDirect3DSurface9_GetDesc(surface, &desc);
224 
225  if (surface_rect)
226  {
227  width = surface_rect->right - surface_rect->left;
228  height = surface_rect->bottom - surface_rect->top;
229  }
230  else
231  {
232  width = desc.Width;
233  height = desc.Height;
234  }
235 
237  desc.Format, D3DPOOL_SYSTEMMEM, temp_surface, NULL)
239  desc.Format, D3DMULTISAMPLE_NONE, 0, TRUE, temp_surface, NULL);
240  if (FAILED(hr))
241  {
242  WARN("Failed to create temporary surface, surface %p, format %#x,"
243  " usage %#x, pool %#x, write %#x, width %u, height %u.\n",
244  surface, desc.Format, desc.Usage, desc.Pool, write, width, height);
246  return hr;
247  }
248 
249  if (write || SUCCEEDED(hr = IDirect3DDevice9_StretchRect(device, surface, surface_rect,
250  *temp_surface, NULL, D3DTEXF_NONE)))
251  hr = IDirect3DSurface9_LockRect(*temp_surface, lock, NULL, lock_flag);
252 
254  if (FAILED(hr))
255  {
256  WARN("Failed to lock surface %p, write %#x, usage %#x, pool %#x.\n",
257  surface, write, desc.Usage, desc.Pool);
258  IDirect3DSurface9_Release(*temp_surface);
259  *temp_surface = NULL;
260  return hr;
261  }
262  TRACE("Created temporary surface %p.\n", surface);
263  }
264  return hr;
265 }
266 
267 HRESULT unlock_surface(IDirect3DSurface9 *surface, const RECT *surface_rect,
268  IDirect3DSurface9 *temp_surface, BOOL update)
269 {
270  IDirect3DDevice9 *device;
271  POINT surface_point;
272  HRESULT hr;
273 
274  if (!temp_surface)
275  {
276  hr = IDirect3DSurface9_UnlockRect(surface);
277  return hr;
278  }
279 
280  hr = IDirect3DSurface9_UnlockRect(temp_surface);
281  if (update)
282  {
283  if (surface_rect)
284  {
285  surface_point.x = surface_rect->left;
286  surface_point.y = surface_rect->top;
287  }
288  else
289  {
290  surface_point.x = 0;
291  surface_point.y = 0;
292  }
294  if (FAILED(hr = IDirect3DDevice9_UpdateSurface(device, temp_surface, NULL, surface, &surface_point)))
295  WARN("Updating surface failed, hr %#x, surface %p, temp_surface %p.\n",
296  hr, surface, temp_surface);
298  }
299  IDirect3DSurface9_Release(temp_surface);
300  return hr;
301 }
302 
304 {
305  unsigned int i;
306 
307  for (i = 0; i < ARRAY_SIZE(rgb_pixel_formats); i++)
308  {
309  if (rgb_pixel_formats[i].bpp == pixel_format->bpp
310  && rgb_pixel_formats[i].rmask == pixel_format->rmask
311  && rgb_pixel_formats[i].gmask == pixel_format->gmask
312  && rgb_pixel_formats[i].bmask == pixel_format->bmask)
313  {
314  if ((pixel_format->flags & DDS_PF_ALPHA) && rgb_pixel_formats[i].amask == pixel_format->amask)
315  return rgb_pixel_formats[i].format;
316  if (rgb_pixel_formats[i].amask == 0)
317  return rgb_pixel_formats[i].format;
318  }
319  }
320 
321  WARN("Unknown RGB pixel format (%#x, %#x, %#x, %#x)\n",
322  pixel_format->rmask, pixel_format->gmask, pixel_format->bmask, pixel_format->amask);
323  return D3DFMT_UNKNOWN;
324 }
325 
327 {
328  if (pixel_format->bpp == 8)
329  {
330  if (pixel_format->rmask == 0xff)
331  return D3DFMT_L8;
332  if ((pixel_format->flags & DDS_PF_ALPHA) && pixel_format->rmask == 0x0f && pixel_format->amask == 0xf0)
333  return D3DFMT_A4L4;
334  }
335  if (pixel_format->bpp == 16)
336  {
337  if (pixel_format->rmask == 0xffff)
338  return D3DFMT_L16;
339  if ((pixel_format->flags & DDS_PF_ALPHA) && pixel_format->rmask == 0x00ff && pixel_format->amask == 0xff00)
340  return D3DFMT_A8L8;
341  }
342 
343  WARN("Unknown luminance pixel format (bpp %u, l %#x, a %#x)\n",
344  pixel_format->bpp, pixel_format->rmask, pixel_format->amask);
345  return D3DFMT_UNKNOWN;
346 }
347 
349 {
350  if (pixel_format->bpp == 8 && pixel_format->amask == 0xff)
351  return D3DFMT_A8;
352 
353  WARN("Unknown Alpha pixel format (%u, %#x)\n", pixel_format->bpp, pixel_format->rmask);
354  return D3DFMT_UNKNOWN;
355 }
356 
358 {
359  if (pixel_format->bpp == 8)
360  return D3DFMT_P8;
361 
362  WARN("Unknown indexed pixel format (%u).\n", pixel_format->bpp);
363  return D3DFMT_UNKNOWN;
364 }
365 
367 {
368  if (pixel_format->bpp == 16 && pixel_format->rmask == 0x00ff && pixel_format->gmask == 0xff00)
369  return D3DFMT_V8U8;
370  if (pixel_format->bpp == 32 && pixel_format->rmask == 0x0000ffff && pixel_format->gmask == 0xffff0000)
371  return D3DFMT_V16U16;
372 
373  WARN("Unknown bump pixel format (%u, %#x, %#x, %#x, %#x)\n", pixel_format->bpp,
374  pixel_format->rmask, pixel_format->gmask, pixel_format->bmask, pixel_format->amask);
375  return D3DFMT_UNKNOWN;
376 }
377 
379 {
380  if (pixel_format->bpp == 32 && pixel_format->rmask == 0x000000ff && pixel_format->gmask == 0x0000ff00
381  && pixel_format->bmask == 0x00ff0000)
382  return D3DFMT_X8L8V8U8;
383 
384  WARN("Unknown bump pixel format (%u, %#x, %#x, %#x, %#x).\n", pixel_format->bpp,
385  pixel_format->rmask, pixel_format->gmask, pixel_format->bmask, pixel_format->amask);
386  return D3DFMT_UNKNOWN;
387 }
388 
390 {
391  TRACE("pixel_format: size %u, flags %#x, fourcc %#x, bpp %u.\n", pixel_format->size,
392  pixel_format->flags, pixel_format->fourcc, pixel_format->bpp);
393  TRACE("rmask %#x, gmask %#x, bmask %#x, amask %#x.\n", pixel_format->rmask, pixel_format->gmask,
394  pixel_format->bmask, pixel_format->amask);
395 
396  if (pixel_format->flags & DDS_PF_FOURCC)
397  return dds_fourcc_to_d3dformat(pixel_format->fourcc);
398  if (pixel_format->flags & DDS_PF_INDEXED)
400  if (pixel_format->flags & DDS_PF_RGB)
402  if (pixel_format->flags & DDS_PF_LUMINANCE)
404  if (pixel_format->flags & DDS_PF_ALPHA_ONLY)
406  if (pixel_format->flags & DDS_PF_BUMPDUDV)
408  if (pixel_format->flags & DDS_PF_BUMPLUMINANCE)
410 
411  WARN("Unknown pixel format (flags %#x, fourcc %#x, bpp %u, r %#x, g %#x, b %#x, a %#x)\n",
412  pixel_format->flags, pixel_format->fourcc, pixel_format->bpp,
413  pixel_format->rmask, pixel_format->gmask, pixel_format->bmask, pixel_format->amask);
414  return D3DFMT_UNKNOWN;
415 }
416 
418 {
419  unsigned int i;
420 
421  memset(pixel_format, 0, sizeof(*pixel_format));
422 
423  pixel_format->size = sizeof(*pixel_format);
424 
425  for (i = 0; i < ARRAY_SIZE(rgb_pixel_formats); i++)
426  {
428  {
429  pixel_format->flags |= DDS_PF_RGB;
430  pixel_format->bpp = rgb_pixel_formats[i].bpp;
431  pixel_format->rmask = rgb_pixel_formats[i].rmask;
432  pixel_format->gmask = rgb_pixel_formats[i].gmask;
433  pixel_format->bmask = rgb_pixel_formats[i].bmask;
434  pixel_format->amask = rgb_pixel_formats[i].amask;
435  if (pixel_format->amask) pixel_format->flags |= DDS_PF_ALPHA;
436  return D3D_OK;
437  }
438  }
439 
440  /* Reuse dds_fourcc_to_d3dformat as D3DFORMAT and FOURCC are DWORD with same values */
442  {
443  pixel_format->flags |= DDS_PF_FOURCC;
444  pixel_format->fourcc = d3dformat;
445  return D3D_OK;
446  }
447 
448  WARN("Unknown pixel format %#x\n", d3dformat);
449  return E_NOTIMPL;
450 }
451 
453  UINT *pitch, UINT *size)
454 {
455  const struct pixel_format_desc *format_desc = get_format_info(format);
456  if (format_desc->type == FORMAT_UNKNOWN)
457  return E_NOTIMPL;
458 
459  if (format_desc->block_width != 1 || format_desc->block_height != 1)
460  {
461  *pitch = format_desc->block_byte_count
462  * max(1, (width + format_desc->block_width - 1) / format_desc->block_width);
463  *size = *pitch
464  * max(1, (height + format_desc->block_height - 1) / format_desc->block_height);
465  }
466  else
467  {
468  *pitch = width * format_desc->bytes_per_pixel;
469  *size = *pitch * height;
470  }
471 
472  return D3D_OK;
473 }
474 
476  UINT miplevels, UINT faces)
477 {
478  UINT i, file_size = 0;
479 
480  for (i = 0; i < miplevels; i++)
481  {
482  UINT pitch, size = 0;
484  size *= depth;
485  file_size += size;
486  width = max(1, width / 2);
487  height = max(1, height / 2);
488  depth = max(1, depth / 2);
489  }
490 
491  file_size *= faces;
492  file_size += sizeof(struct dds_header);
493  return file_size;
494 }
495 
496 /************************************************************
497 * get_image_info_from_dds
498 *
499 * Fills a D3DXIMAGE_INFO structure with information
500 * about a DDS file stored in the memory.
501 *
502 * PARAMS
503 * buffer [I] pointer to DDS data
504 * length [I] size of DDS data
505 * info [O] pointer to D3DXIMAGE_INFO structure
506 *
507 * RETURNS
508 * Success: D3D_OK
509 * Failure: D3DXERR_INVALIDDATA
510 *
511 */
513 {
514  UINT faces = 1;
515  UINT expected_length;
516  const struct dds_header *header = buffer;
517 
518  if (length < sizeof(*header) || !info)
519  return D3DXERR_INVALIDDATA;
520 
521  if (header->pixel_format.size != sizeof(header->pixel_format))
522  return D3DXERR_INVALIDDATA;
523 
524  info->Width = header->width;
525  info->Height = header->height;
526  info->Depth = 1;
527  info->MipLevels = header->miplevels ? header->miplevels : 1;
528 
529  info->Format = dds_pixel_format_to_d3dformat(&header->pixel_format);
530  if (info->Format == D3DFMT_UNKNOWN)
531  return D3DXERR_INVALIDDATA;
532 
533  TRACE("Pixel format is %#x\n", info->Format);
534 
535  if (header->caps2 & DDS_CAPS2_VOLUME)
536  {
537  info->Depth = header->depth;
538  info->ResourceType = D3DRTYPE_VOLUMETEXTURE;
539  }
540  else if (header->caps2 & DDS_CAPS2_CUBEMAP)
541  {
542  DWORD face;
543  faces = 0;
545  {
546  if (header->caps2 & face)
547  faces++;
548  }
549  info->ResourceType = D3DRTYPE_CUBETEXTURE;
550  }
551  else
552  {
553  info->ResourceType = D3DRTYPE_TEXTURE;
554  }
555 
556  expected_length = calculate_dds_file_size(info->Format, info->Width, info->Height, info->Depth,
557  info->MipLevels, faces);
558  if (length < expected_length)
559  {
560  WARN("File is too short %u, expected at least %u bytes\n", length, expected_length);
561  return D3DXERR_INVALIDDATA;
562  }
563 
564  info->ImageFileFormat = D3DXIFF_DDS;
565  return D3D_OK;
566 }
567 
568 static HRESULT load_surface_from_dds(IDirect3DSurface9 *dst_surface, const PALETTEENTRY *dst_palette,
569  const RECT *dst_rect, const void *src_data, const RECT *src_rect, DWORD filter, D3DCOLOR color_key,
570  const D3DXIMAGE_INFO *src_info)
571 {
572  UINT size;
573  UINT src_pitch;
574  const struct dds_header *header = src_data;
575  const BYTE *pixels = (BYTE *)(header + 1);
576 
577  if (src_info->ResourceType != D3DRTYPE_TEXTURE)
578  return D3DXERR_INVALIDDATA;
579 
580  if (FAILED(calculate_dds_surface_size(src_info->Format, src_info->Width, src_info->Height, &src_pitch, &size)))
581  return E_NOTIMPL;
582 
583  return D3DXLoadSurfaceFromMemory(dst_surface, dst_palette, dst_rect, pixels, src_info->Format,
584  src_pitch, NULL, src_rect, filter, color_key);
585 }
586 
587 static HRESULT save_dds_surface_to_memory(ID3DXBuffer **dst_buffer, IDirect3DSurface9 *src_surface, const RECT *src_rect)
588 {
589  HRESULT hr;
590  UINT dst_pitch, surface_size, file_size;
591  D3DSURFACE_DESC src_desc;
592  D3DLOCKED_RECT locked_rect;
594  struct dds_header *header;
595  BYTE *pixels;
596  struct volume volume;
597  const struct pixel_format_desc *pixel_format;
598  IDirect3DSurface9 *temp_surface;
599 
600  if (src_rect)
601  {
602  FIXME("Saving a part of a surface to a DDS file is not implemented yet\n");
603  return E_NOTIMPL;
604  }
605 
606  hr = IDirect3DSurface9_GetDesc(src_surface, &src_desc);
607  if (FAILED(hr)) return hr;
608 
609  pixel_format = get_format_info(src_desc.Format);
610  if (pixel_format->type == FORMAT_UNKNOWN) return E_NOTIMPL;
611 
612  file_size = calculate_dds_file_size(src_desc.Format, src_desc.Width, src_desc.Height, 1, 1, 1);
613 
614  hr = calculate_dds_surface_size(src_desc.Format, src_desc.Width, src_desc.Height, &dst_pitch, &surface_size);
615  if (FAILED(hr)) return hr;
616 
618  if (FAILED(hr)) return hr;
619 
621  pixels = (BYTE *)(header + 1);
622 
623  memset(header, 0, sizeof(*header));
624  header->signature = MAKEFOURCC('D','D','S',' ');
625  /* The signature is not really part of the DDS header */
626  header->size = sizeof(*header) - FIELD_OFFSET(struct dds_header, size);
628  header->height = src_desc.Height;
629  header->width = src_desc.Width;
630  header->caps = DDS_CAPS_TEXTURE;
631  hr = d3dformat_to_dds_pixel_format(&header->pixel_format, src_desc.Format);
632  if (FAILED(hr))
633  {
635  return hr;
636  }
637 
638  hr = lock_surface(src_surface, NULL, &locked_rect, &temp_surface, FALSE);
639  if (FAILED(hr))
640  {
642  return hr;
643  }
644 
645  volume.width = src_desc.Width;
646  volume.height = src_desc.Height;
647  volume.depth = 1;
648  copy_pixels(locked_rect.pBits, locked_rect.Pitch, 0, pixels, dst_pitch, 0,
649  &volume, pixel_format);
650 
651  unlock_surface(src_surface, NULL, temp_surface, FALSE);
652 
653  *dst_buffer = buffer;
654  return D3D_OK;
655 }
656 
657 static HRESULT get_surface(D3DRESOURCETYPE type, struct IDirect3DBaseTexture9 *tex,
658  int face, UINT level, struct IDirect3DSurface9 **surf)
659 {
660  switch (type)
661  {
662  case D3DRTYPE_TEXTURE:
663  return IDirect3DTexture9_GetSurfaceLevel((IDirect3DTexture9*) tex, level, surf);
665  return IDirect3DCubeTexture9_GetCubeMapSurface((IDirect3DCubeTexture9*) tex, face, level, surf);
666  default:
667  ERR("Unexpected texture type\n");
668  return E_NOTIMPL;
669  }
670 }
671 
672 HRESULT save_dds_texture_to_memory(ID3DXBuffer **dst_buffer, IDirect3DBaseTexture9 *src_texture, const PALETTEENTRY *src_palette)
673 {
674  HRESULT hr;
676  UINT mip_levels;
677  IDirect3DSurface9 *surface;
678 
679  type = IDirect3DBaseTexture9_GetType(src_texture);
680 
682  return D3DERR_INVALIDCALL;
683 
684  if (type == D3DRTYPE_CUBETEXTURE)
685  {
686  FIXME("Cube texture not supported yet\n");
687  return E_NOTIMPL;
688  }
689  else if (type == D3DRTYPE_VOLUMETEXTURE)
690  {
691  FIXME("Volume texture not supported yet\n");
692  return E_NOTIMPL;
693  }
694 
695  mip_levels = IDirect3DTexture9_GetLevelCount(src_texture);
696 
697  if (mip_levels > 1)
698  {
699  FIXME("Mipmap not supported yet\n");
700  return E_NOTIMPL;
701  }
702 
703  if (src_palette)
704  {
705  FIXME("Saving surfaces with palettized pixel formats not implemented yet\n");
706  return E_NOTIMPL;
707  }
708 
709  hr = get_surface(type, src_texture, D3DCUBEMAP_FACE_POSITIVE_X, 0, &surface);
710 
711  if (SUCCEEDED(hr))
712  {
713  hr = save_dds_surface_to_memory(dst_buffer, surface, NULL);
714  IDirect3DSurface9_Release(surface);
715  }
716 
717  return hr;
718 }
719 HRESULT load_volume_from_dds(IDirect3DVolume9 *dst_volume, const PALETTEENTRY *dst_palette,
720  const D3DBOX *dst_box, const void *src_data, const D3DBOX *src_box, DWORD filter, D3DCOLOR color_key,
721  const D3DXIMAGE_INFO *src_info)
722 {
723  UINT row_pitch, slice_pitch;
724  const struct dds_header *header = src_data;
725  const BYTE *pixels = (BYTE *)(header + 1);
726 
727  if (src_info->ResourceType != D3DRTYPE_VOLUMETEXTURE)
728  return D3DXERR_INVALIDDATA;
729 
730  if (FAILED(calculate_dds_surface_size(src_info->Format, src_info->Width, src_info->Height, &row_pitch, &slice_pitch)))
731  return E_NOTIMPL;
732 
733  return D3DXLoadVolumeFromMemory(dst_volume, dst_palette, dst_box, pixels, src_info->Format,
734  row_pitch, slice_pitch, NULL, src_box, filter, color_key);
735 }
736 
737 HRESULT load_texture_from_dds(IDirect3DTexture9 *texture, const void *src_data, const PALETTEENTRY *palette,
738  DWORD filter, D3DCOLOR color_key, const D3DXIMAGE_INFO *src_info, unsigned int skip_levels,
739  unsigned int *loaded_miplevels)
740 {
741  HRESULT hr;
742  RECT src_rect;
743  UINT src_pitch;
744  UINT mip_level;
745  UINT mip_levels;
746  UINT mip_level_size;
747  UINT width, height;
748  IDirect3DSurface9 *surface;
749  const struct dds_header *header = src_data;
750  const BYTE *pixels = (BYTE *)(header + 1);
751 
752  /* Loading a cube texture as a simple texture is also supported
753  * (only first face texture is taken). Same with volume textures. */
754  if ((src_info->ResourceType != D3DRTYPE_TEXTURE)
755  && (src_info->ResourceType != D3DRTYPE_CUBETEXTURE)
756  && (src_info->ResourceType != D3DRTYPE_VOLUMETEXTURE))
757  {
758  WARN("Trying to load a %u resource as a 2D texture, returning failure.\n", src_info->ResourceType);
759  return D3DXERR_INVALIDDATA;
760  }
761 
762  width = src_info->Width;
763  height = src_info->Height;
764  mip_levels = min(src_info->MipLevels, IDirect3DTexture9_GetLevelCount(texture));
765  if (src_info->ResourceType == D3DRTYPE_VOLUMETEXTURE)
766  mip_levels = 1;
767  for (mip_level = 0; mip_level < mip_levels + skip_levels; ++mip_level)
768  {
769  hr = calculate_dds_surface_size(src_info->Format, width, height, &src_pitch, &mip_level_size);
770  if (FAILED(hr)) return hr;
771 
772  if (mip_level >= skip_levels)
773  {
774  SetRect(&src_rect, 0, 0, width, height);
775 
776  IDirect3DTexture9_GetSurfaceLevel(texture, mip_level - skip_levels, &surface);
777  hr = D3DXLoadSurfaceFromMemory(surface, palette, NULL, pixels, src_info->Format, src_pitch,
778  NULL, &src_rect, filter, color_key);
779  IDirect3DSurface9_Release(surface);
780  if (FAILED(hr))
781  return hr;
782  }
783 
784  pixels += mip_level_size;
785  width = max(1, width / 2);
786  height = max(1, height / 2);
787  }
788 
789  *loaded_miplevels = mip_levels - skip_levels;
790 
791  return D3D_OK;
792 }
793 
794 HRESULT load_cube_texture_from_dds(IDirect3DCubeTexture9 *cube_texture, const void *src_data,
795  const PALETTEENTRY *palette, DWORD filter, DWORD color_key, const D3DXIMAGE_INFO *src_info)
796 {
797  HRESULT hr;
798  int face;
799  UINT mip_level;
800  UINT size;
801  RECT src_rect;
802  UINT src_pitch;
803  UINT mip_levels;
804  UINT mip_level_size;
805  IDirect3DSurface9 *surface;
806  const struct dds_header *header = src_data;
807  const BYTE *pixels = (BYTE *)(header + 1);
808 
809  if (src_info->ResourceType != D3DRTYPE_CUBETEXTURE)
810  return D3DXERR_INVALIDDATA;
811 
813  {
814  WARN("Only full cubemaps are supported\n");
815  return D3DXERR_INVALIDDATA;
816  }
817 
818  mip_levels = min(src_info->MipLevels, IDirect3DCubeTexture9_GetLevelCount(cube_texture));
820  {
821  size = src_info->Width;
822  for (mip_level = 0; mip_level < src_info->MipLevels; mip_level++)
823  {
824  hr = calculate_dds_surface_size(src_info->Format, size, size, &src_pitch, &mip_level_size);
825  if (FAILED(hr)) return hr;
826 
827  /* if texture has fewer mip levels than DDS file, skip excessive mip levels */
828  if (mip_level < mip_levels)
829  {
830  SetRect(&src_rect, 0, 0, size, size);
831 
832  IDirect3DCubeTexture9_GetCubeMapSurface(cube_texture, face, mip_level, &surface);
833  hr = D3DXLoadSurfaceFromMemory(surface, palette, NULL, pixels, src_info->Format, src_pitch,
834  NULL, &src_rect, filter, color_key);
835  IDirect3DSurface9_Release(surface);
836  if (FAILED(hr)) return hr;
837  }
838 
839  pixels += mip_level_size;
840  size = max(1, size / 2);
841  }
842  }
843 
844  return D3D_OK;
845 }
846 
847 HRESULT load_volume_texture_from_dds(IDirect3DVolumeTexture9 *volume_texture, const void *src_data,
848  const PALETTEENTRY *palette, DWORD filter, DWORD color_key, const D3DXIMAGE_INFO *src_info)
849 {
850  HRESULT hr;
851  UINT mip_level;
852  UINT mip_levels;
853  UINT src_slice_pitch;
854  UINT src_row_pitch;
855  D3DBOX src_box;
857  IDirect3DVolume9 *volume;
858  const struct dds_header *header = src_data;
859  const BYTE *pixels = (BYTE *)(header + 1);
860 
861  if (src_info->ResourceType != D3DRTYPE_VOLUMETEXTURE)
862  return D3DXERR_INVALIDDATA;
863 
864  width = src_info->Width;
865  height = src_info->Height;
866  depth = src_info->Depth;
867  mip_levels = min(src_info->MipLevels, IDirect3DVolumeTexture9_GetLevelCount(volume_texture));
868 
869  for (mip_level = 0; mip_level < mip_levels; mip_level++)
870  {
871  hr = calculate_dds_surface_size(src_info->Format, width, height, &src_row_pitch, &src_slice_pitch);
872  if (FAILED(hr)) return hr;
873 
874  hr = IDirect3DVolumeTexture9_GetVolumeLevel(volume_texture, mip_level, &volume);
875  if (FAILED(hr)) return hr;
876 
877  src_box.Left = 0;
878  src_box.Top = 0;
879  src_box.Right = width;
880  src_box.Bottom = height;
881  src_box.Front = 0;
882  src_box.Back = depth;
883 
885  src_row_pitch, src_slice_pitch, NULL, &src_box, filter, color_key);
886 
888  if (FAILED(hr)) return hr;
889 
890  pixels += depth * src_slice_pitch;
891  width = max(1, width / 2);
892  height = max(1, height / 2);
893  depth = max(1, depth / 2);
894  }
895 
896  return D3D_OK;
897 }
898 
899 static BOOL convert_dib_to_bmp(const void **data, unsigned int *size)
900 {
901  ULONG header_size;
902  ULONG count = 0;
903  ULONG offset;
905  BYTE *new_data;
906  UINT new_size;
907 
908  if ((*size < 4) || (*size < (header_size = *(ULONG*)*data)))
909  return FALSE;
910 
911  if ((header_size == sizeof(BITMAPINFOHEADER)) ||
912  (header_size == sizeof(BITMAPV4HEADER)) ||
913  (header_size == sizeof(BITMAPV5HEADER)) ||
914  (header_size == 64 /* sizeof(BITMAPCOREHEADER2) */))
915  {
916  /* All structures begin with the same memory layout as BITMAPINFOHEADER */
917  BITMAPINFOHEADER *info_header = (BITMAPINFOHEADER*)*data;
918  count = info_header->biClrUsed;
919 
920  if (!count && info_header->biBitCount <= 8)
921  count = 1 << info_header->biBitCount;
922 
923  offset = sizeof(BITMAPFILEHEADER) + header_size + sizeof(RGBQUAD) * count;
924 
925  /* For BITMAPINFOHEADER with BI_BITFIELDS compression, there are 3 additional color masks after header */
926  if ((info_header->biSize == sizeof(BITMAPINFOHEADER)) && (info_header->biCompression == BI_BITFIELDS))
927  offset += 3 * sizeof(DWORD);
928  }
929  else if (header_size == sizeof(BITMAPCOREHEADER))
930  {
931  BITMAPCOREHEADER *core_header = (BITMAPCOREHEADER*)*data;
932 
933  if (core_header->bcBitCount <= 8)
934  count = 1 << core_header->bcBitCount;
935 
936  offset = sizeof(BITMAPFILEHEADER) + header_size + sizeof(RGBTRIPLE) * count;
937  }
938  else
939  {
940  return FALSE;
941  }
942 
943  TRACE("Converting DIB file to BMP\n");
944 
945  new_size = *size + sizeof(BITMAPFILEHEADER);
946  new_data = HeapAlloc(GetProcessHeap(), 0, new_size);
947  CopyMemory(new_data + sizeof(BITMAPFILEHEADER), *data, *size);
948 
949  /* Add BMP header */
950  header = (BITMAPFILEHEADER*)new_data;
951  header->bfType = 0x4d42; /* BM */
952  header->bfSize = new_size;
953  header->bfReserved1 = 0;
954  header->bfReserved2 = 0;
955  header->bfOffBits = offset;
956 
957  /* Update input data */
958  *data = new_data;
959  *size = new_size;
960 
961  return TRUE;
962 }
963 
964 /************************************************************
965  * D3DXGetImageInfoFromFileInMemory
966  *
967  * Fills a D3DXIMAGE_INFO structure with info about an image
968  *
969  * PARAMS
970  * data [I] pointer to the image file data
971  * datasize [I] size of the passed data
972  * info [O] pointer to the destination structure
973  *
974  * RETURNS
975  * Success: D3D_OK, if info is not NULL and data and datasize make up a valid image file or
976  * if info is NULL and data and datasize are not NULL
977  * Failure: D3DXERR_INVALIDDATA, if data is no valid image file and datasize and info are not NULL
978  * D3DERR_INVALIDCALL, if data is NULL or
979  * if datasize is 0
980  *
981  * NOTES
982  * datasize may be bigger than the actual file size
983  *
984  */
986 {
988  IWICBitmapDecoder *decoder = NULL;
990  HRESULT hr;
991  BOOL dib;
992 
993  TRACE("(%p, %d, %p)\n", data, datasize, info);
994 
995  if (!data || !datasize)
996  return D3DERR_INVALIDCALL;
997 
998  if (!info)
999  return D3D_OK;
1000 
1001  if ((datasize >= 4) && !strncmp(data, "DDS ", 4)) {
1002  TRACE("File type is DDS\n");
1004  }
1005 
1006  /* In case of DIB file, convert it to BMP */
1008 
1009  hr = WICCreateImagingFactory_Proxy(WINCODEC_SDK_VERSION, &factory);
1010 
1011  if (SUCCEEDED(hr)) {
1012  IWICImagingFactory_CreateStream(factory, &stream);
1013  IWICStream_InitializeFromMemory(stream, (BYTE*)data, datasize);
1014  hr = IWICImagingFactory_CreateDecoderFromStream(factory, (IStream*)stream, NULL, 0, &decoder);
1015  IWICStream_Release(stream);
1016  IWICImagingFactory_Release(factory);
1017  }
1018 
1019  if (FAILED(hr)) {
1020  if ((datasize >= 2) && (!strncmp(data, "P3", 2) || !strncmp(data, "P6", 2)))
1021  FIXME("File type PPM is not supported yet\n");
1022  else if ((datasize >= 10) && !strncmp(data, "#?RADIANCE", 10))
1023  FIXME("File type HDR is not supported yet\n");
1024  else if ((datasize >= 2) && (!strncmp(data, "PF", 2) || !strncmp(data, "Pf", 2)))
1025  FIXME("File type PFM is not supported yet\n");
1026  }
1027 
1028  if (SUCCEEDED(hr)) {
1029  GUID container_format;
1030  UINT frame_count;
1031 
1032  hr = IWICBitmapDecoder_GetContainerFormat(decoder, &container_format);
1033  if (SUCCEEDED(hr)) {
1034  if (IsEqualGUID(&container_format, &GUID_ContainerFormatBmp)) {
1035  if (dib) {
1036  TRACE("File type is DIB\n");
1037  info->ImageFileFormat = D3DXIFF_DIB;
1038  } else {
1039  TRACE("File type is BMP\n");
1040  info->ImageFileFormat = D3DXIFF_BMP;
1041  }
1042  } else if (IsEqualGUID(&container_format, &GUID_ContainerFormatPng)) {
1043  TRACE("File type is PNG\n");
1044  info->ImageFileFormat = D3DXIFF_PNG;
1045  } else if(IsEqualGUID(&container_format, &GUID_ContainerFormatJpeg)) {
1046  TRACE("File type is JPG\n");
1047  info->ImageFileFormat = D3DXIFF_JPG;
1048  } else if(IsEqualGUID(&container_format, &GUID_WineContainerFormatTga)) {
1049  TRACE("File type is TGA\n");
1050  info->ImageFileFormat = D3DXIFF_TGA;
1051  } else {
1052  WARN("Unsupported image file format %s\n", debugstr_guid(&container_format));
1054  }
1055  }
1056 
1057  if (SUCCEEDED(hr))
1058  hr = IWICBitmapDecoder_GetFrameCount(decoder, &frame_count);
1059  if (SUCCEEDED(hr) && !frame_count)
1061 
1062  if (SUCCEEDED(hr)) {
1063  IWICBitmapFrameDecode *frame = NULL;
1064 
1065  hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame);
1066 
1067  if (SUCCEEDED(hr))
1068  hr = IWICBitmapFrameDecode_GetSize(frame, &info->Width, &info->Height);
1069 
1070  if (SUCCEEDED(hr)) {
1072 
1073  hr = IWICBitmapFrameDecode_GetPixelFormat(frame, &pixel_format);
1074  if (SUCCEEDED(hr)) {
1076  if (info->Format == D3DFMT_UNKNOWN) {
1077  WARN("Unsupported pixel format %s\n", debugstr_guid(&pixel_format));
1079  }
1080  }
1081  }
1082 
1083  /* For 32 bpp BMP, windowscodecs.dll never returns a format with alpha while
1084  * d3dx9_xx.dll returns one if at least 1 pixel has a non zero alpha component */
1085  if (SUCCEEDED(hr) && (info->Format == D3DFMT_X8R8G8B8) && (info->ImageFileFormat == D3DXIFF_BMP)) {
1086  DWORD size = sizeof(DWORD) * info->Width * info->Height;
1088  hr = IWICBitmapFrameDecode_CopyPixels(frame, NULL, sizeof(DWORD) * info->Width, size, buffer);
1089  if (SUCCEEDED(hr)) {
1090  DWORD i;
1091  for (i = 0; i < info->Width * info->Height; i++) {
1092  if (buffer[i*4+3]) {
1093  info->Format = D3DFMT_A8R8G8B8;
1094  break;
1095  }
1096  }
1097  }
1099  }
1100 
1101  if (frame)
1102  IWICBitmapFrameDecode_Release(frame);
1103 
1104  info->Depth = 1;
1105  info->MipLevels = 1;
1106  info->ResourceType = D3DRTYPE_TEXTURE;
1107  }
1108  }
1109 
1110  if (decoder)
1111  IWICBitmapDecoder_Release(decoder);
1112 
1113  if (dib)
1114  HeapFree(GetProcessHeap(), 0, (void*)data);
1115 
1116  if (FAILED(hr)) {
1117  TRACE("Invalid or unsupported image file\n");
1118  return D3DXERR_INVALIDDATA;
1119  }
1120 
1121  return D3D_OK;
1122 }
1123 
1124 /************************************************************
1125  * D3DXGetImageInfoFromFile
1126  *
1127  * RETURNS
1128  * Success: D3D_OK, if we successfully load a valid image file or
1129  * if we successfully load a file which is no valid image and info is NULL
1130  * Failure: D3DXERR_INVALIDDATA, if we fail to load file or
1131  * if file is not a valid image file and info is not NULL
1132  * D3DERR_INVALIDCALL, if file is NULL
1133  *
1134  */
1136 {
1137  WCHAR *widename;
1138  HRESULT hr;
1139  int strlength;
1140 
1141  TRACE("file %s, info %p.\n", debugstr_a(file), info);
1142 
1143  if( !file ) return D3DERR_INVALIDCALL;
1144 
1145  strlength = MultiByteToWideChar(CP_ACP, 0, file, -1, NULL, 0);
1146  widename = HeapAlloc(GetProcessHeap(), 0, strlength * sizeof(*widename));
1147  MultiByteToWideChar(CP_ACP, 0, file, -1, widename, strlength);
1148 
1149  hr = D3DXGetImageInfoFromFileW(widename, info);
1150  HeapFree(GetProcessHeap(), 0, widename);
1151 
1152  return hr;
1153 }
1154 
1156 {
1157  void *buffer;
1158  HRESULT hr;
1159  DWORD size;
1160 
1161  TRACE("file %s, info %p.\n", debugstr_w(file), info);
1162 
1163  if (!file)
1164  return D3DERR_INVALIDCALL;
1165 
1167  return D3DXERR_INVALIDDATA;
1168 
1171 
1172  return hr;
1173 }
1174 
1175 /************************************************************
1176  * D3DXGetImageInfoFromResource
1177  *
1178  * RETURNS
1179  * Success: D3D_OK, if resource is a valid image file
1180  * Failure: D3DXERR_INVALIDDATA, if resource is no valid image file or NULL or
1181  * if we fail to load resource
1182  *
1183  */
1185 {
1186  HRSRC resinfo;
1187  void *buffer;
1188  DWORD size;
1189 
1190  TRACE("module %p, resource %s, info %p.\n", module, debugstr_a(resource), info);
1191 
1192  if (!(resinfo = FindResourceA(module, resource, (const char *)RT_RCDATA))
1193  /* Try loading the resource as bitmap data (which is in DIB format D3DXIFF_DIB) */
1194  && !(resinfo = FindResourceA(module, resource, (const char *)RT_BITMAP)))
1195  return D3DXERR_INVALIDDATA;
1196 
1197  if (FAILED(load_resource_into_memory(module, resinfo, &buffer, &size)))
1198  return D3DXERR_INVALIDDATA;
1199 
1201 }
1202 
1204 {
1205  HRSRC resinfo;
1206  void *buffer;
1207  DWORD size;
1208 
1209  TRACE("module %p, resource %s, info %p.\n", module, debugstr_w(resource), info);
1210 
1211  if (!(resinfo = FindResourceW(module, resource, (const WCHAR *)RT_RCDATA))
1212  /* Try loading the resource as bitmap data (which is in DIB format D3DXIFF_DIB) */
1213  && !(resinfo = FindResourceW(module, resource, (const WCHAR *)RT_BITMAP)))
1214  return D3DXERR_INVALIDDATA;
1215 
1216  if (FAILED(load_resource_into_memory(module, resinfo, &buffer, &size)))
1217  return D3DXERR_INVALIDDATA;
1218 
1220 }
1221 
1222 /************************************************************
1223  * D3DXLoadSurfaceFromFileInMemory
1224  *
1225  * Loads data from a given buffer into a surface and fills a given
1226  * D3DXIMAGE_INFO structure with info about the source data.
1227  *
1228  * PARAMS
1229  * pDestSurface [I] pointer to the surface
1230  * pDestPalette [I] palette to use
1231  * pDestRect [I] to be filled area of the surface
1232  * pSrcData [I] pointer to the source data
1233  * SrcDataSize [I] size of the source data in bytes
1234  * pSrcRect [I] area of the source data to load
1235  * dwFilter [I] filter to apply on stretching
1236  * Colorkey [I] colorkey
1237  * pSrcInfo [O] pointer to a D3DXIMAGE_INFO structure
1238  *
1239  * RETURNS
1240  * Success: D3D_OK
1241  * Failure: D3DERR_INVALIDCALL, if pDestSurface, pSrcData or SrcDataSize is NULL
1242  * D3DXERR_INVALIDDATA, if pSrcData is no valid image file
1243  *
1244  */
1245 HRESULT WINAPI D3DXLoadSurfaceFromFileInMemory(IDirect3DSurface9 *pDestSurface,
1246  const PALETTEENTRY *pDestPalette, const RECT *pDestRect, const void *pSrcData, UINT SrcDataSize,
1247  const RECT *pSrcRect, DWORD dwFilter, D3DCOLOR Colorkey, D3DXIMAGE_INFO *pSrcInfo)
1248 {
1249  D3DXIMAGE_INFO imginfo;
1250  HRESULT hr;
1251 
1253  IWICBitmapDecoder *decoder;
1254  IWICBitmapFrameDecode *bitmapframe;
1255  IWICStream *stream;
1256 
1257  const struct pixel_format_desc *formatdesc;
1258  WICRect wicrect;
1259  RECT rect;
1260 
1261  TRACE("dst_surface %p, dst_palette %p, dst_rect %s, src_data %p, src_data_size %u, "
1262  "src_rect %s, filter %#x, color_key 0x%08x, src_info %p.\n",
1263  pDestSurface, pDestPalette, wine_dbgstr_rect(pDestRect), pSrcData, SrcDataSize,
1264  wine_dbgstr_rect(pSrcRect), dwFilter, Colorkey, pSrcInfo);
1265 
1266  if (!pDestSurface || !pSrcData || !SrcDataSize)
1267  return D3DERR_INVALIDCALL;
1268 
1269  hr = D3DXGetImageInfoFromFileInMemory(pSrcData, SrcDataSize, &imginfo);
1270 
1271  if (FAILED(hr))
1272  return hr;
1273 
1274  if (pSrcRect)
1275  {
1276  wicrect.X = pSrcRect->left;
1277  wicrect.Y = pSrcRect->top;
1278  wicrect.Width = pSrcRect->right - pSrcRect->left;
1279  wicrect.Height = pSrcRect->bottom - pSrcRect->top;
1280  }
1281  else
1282  {
1283  wicrect.X = 0;
1284  wicrect.Y = 0;
1285  wicrect.Width = imginfo.Width;
1286  wicrect.Height = imginfo.Height;
1287  }
1288 
1289  SetRect(&rect, wicrect.X, wicrect.Y, wicrect.X + wicrect.Width, wicrect.Y + wicrect.Height);
1290 
1291  if (imginfo.ImageFileFormat == D3DXIFF_DDS)
1292  {
1293  hr = load_surface_from_dds(pDestSurface, pDestPalette, pDestRect, pSrcData, &rect,
1294  dwFilter, Colorkey, &imginfo);
1295  if (SUCCEEDED(hr) && pSrcInfo)
1296  *pSrcInfo = imginfo;
1297  return hr;
1298  }
1299 
1300  if (imginfo.ImageFileFormat == D3DXIFF_DIB)
1301  convert_dib_to_bmp(&pSrcData, &SrcDataSize);
1302 
1303  if (FAILED(WICCreateImagingFactory_Proxy(WINCODEC_SDK_VERSION, &factory)))
1304  goto cleanup_err;
1305 
1306  if (FAILED(IWICImagingFactory_CreateStream(factory, &stream)))
1307  {
1308  IWICImagingFactory_Release(factory);
1309  factory = NULL;
1310  goto cleanup_err;
1311  }
1312 
1313  IWICStream_InitializeFromMemory(stream, (BYTE*)pSrcData, SrcDataSize);
1314 
1315  hr = IWICImagingFactory_CreateDecoderFromStream(factory, (IStream*)stream, NULL, 0, &decoder);
1316 
1317  IWICStream_Release(stream);
1318 
1319  if (FAILED(hr))
1320  goto cleanup_err;
1321 
1322  hr = IWICBitmapDecoder_GetFrame(decoder, 0, &bitmapframe);
1323 
1324  if (FAILED(hr))
1325  goto cleanup_bmp;
1326 
1327  formatdesc = get_format_info(imginfo.Format);
1328 
1329  if (formatdesc->type == FORMAT_UNKNOWN)
1330  {
1331  FIXME("Unsupported pixel format\n");
1333  }
1334  else
1335  {
1336  BYTE *buffer;
1337  DWORD pitch;
1339  WICColor *colors = NULL;
1340 
1341  pitch = formatdesc->bytes_per_pixel * wicrect.Width;
1342  buffer = HeapAlloc(GetProcessHeap(), 0, pitch * wicrect.Height);
1343 
1344  hr = IWICBitmapFrameDecode_CopyPixels(bitmapframe, &wicrect, pitch,
1345  pitch * wicrect.Height, buffer);
1346 
1347  if (SUCCEEDED(hr) && (formatdesc->type == FORMAT_INDEX))
1348  {
1349  IWICPalette *wic_palette = NULL;
1350  UINT nb_colors;
1351 
1352  hr = IWICImagingFactory_CreatePalette(factory, &wic_palette);
1353  if (SUCCEEDED(hr))
1354  hr = IWICBitmapFrameDecode_CopyPalette(bitmapframe, wic_palette);
1355  if (SUCCEEDED(hr))
1356  hr = IWICPalette_GetColorCount(wic_palette, &nb_colors);
1357  if (SUCCEEDED(hr))
1358  {
1359  colors = HeapAlloc(GetProcessHeap(), 0, nb_colors * sizeof(colors[0]));
1360  palette = HeapAlloc(GetProcessHeap(), 0, nb_colors * sizeof(palette[0]));
1361  if (!colors || !palette)
1362  hr = E_OUTOFMEMORY;
1363  }
1364  if (SUCCEEDED(hr))
1365  hr = IWICPalette_GetColors(wic_palette, nb_colors, colors, &nb_colors);
1366  if (SUCCEEDED(hr))
1367  {
1368  UINT i;
1369 
1370  /* Convert colors from WICColor (ARGB) to PALETTEENTRY (ABGR) */
1371  for (i = 0; i < nb_colors; i++)
1372  {
1373  palette[i].peRed = (colors[i] >> 16) & 0xff;
1374  palette[i].peGreen = (colors[i] >> 8) & 0xff;
1375  palette[i].peBlue = colors[i] & 0xff;
1376  palette[i].peFlags = (colors[i] >> 24) & 0xff; /* peFlags is the alpha component in DX8 and higher */
1377  }
1378  }
1379  if (wic_palette)
1380  IWICPalette_Release(wic_palette);
1381  }
1382 
1383  if (SUCCEEDED(hr))
1384  {
1385  hr = D3DXLoadSurfaceFromMemory(pDestSurface, pDestPalette, pDestRect,
1386  buffer, imginfo.Format, pitch,
1387  palette, &rect, dwFilter, Colorkey);
1388  }
1389 
1390  HeapFree(GetProcessHeap(), 0, colors);
1393  }
1394 
1395  IWICBitmapFrameDecode_Release(bitmapframe);
1396 
1397 cleanup_bmp:
1398  IWICBitmapDecoder_Release(decoder);
1399 
1400 cleanup_err:
1401  if (factory)
1402  IWICImagingFactory_Release(factory);
1403 
1404  if (imginfo.ImageFileFormat == D3DXIFF_DIB)
1405  HeapFree(GetProcessHeap(), 0, (void*)pSrcData);
1406 
1407  if (FAILED(hr))
1408  return D3DXERR_INVALIDDATA;
1409 
1410  if (pSrcInfo)
1411  *pSrcInfo = imginfo;
1412 
1413  return D3D_OK;
1414 }
1415 
1416 HRESULT WINAPI D3DXLoadSurfaceFromFileA(IDirect3DSurface9 *dst_surface,
1417  const PALETTEENTRY *dst_palette, const RECT *dst_rect, const char *src_file,
1418  const RECT *src_rect, DWORD filter, D3DCOLOR color_key, D3DXIMAGE_INFO *src_info)
1419 {
1420  WCHAR *src_file_w;
1421  HRESULT hr;
1422  int strlength;
1423 
1424  TRACE("dst_surface %p, dst_palette %p, dst_rect %s, src_file %s, "
1425  "src_rect %s, filter %#x, color_key 0x%08x, src_info %p.\n",
1426  dst_surface, dst_palette, wine_dbgstr_rect(dst_rect), debugstr_a(src_file),
1427  wine_dbgstr_rect(src_rect), filter, color_key, src_info);
1428 
1429  if (!src_file || !dst_surface)
1430  return D3DERR_INVALIDCALL;
1431 
1432  strlength = MultiByteToWideChar(CP_ACP, 0, src_file, -1, NULL, 0);
1433  src_file_w = HeapAlloc(GetProcessHeap(), 0, strlength * sizeof(*src_file_w));
1434  MultiByteToWideChar(CP_ACP, 0, src_file, -1, src_file_w, strlength);
1435 
1436  hr = D3DXLoadSurfaceFromFileW(dst_surface, dst_palette, dst_rect,
1437  src_file_w, src_rect, filter, color_key, src_info);
1438  HeapFree(GetProcessHeap(), 0, src_file_w);
1439 
1440  return hr;
1441 }
1442 
1443 HRESULT WINAPI D3DXLoadSurfaceFromFileW(IDirect3DSurface9 *dst_surface,
1444  const PALETTEENTRY *dst_palette, const RECT *dst_rect, const WCHAR *src_file,
1445  const RECT *src_rect, DWORD filter, D3DCOLOR color_key, D3DXIMAGE_INFO *src_info)
1446 {
1447  UINT data_size;
1448  void *data;
1449  HRESULT hr;
1450 
1451  TRACE("dst_surface %p, dst_palette %p, dst_rect %s, src_file %s, "
1452  "src_rect %s, filter %#x, color_key 0x%08x, src_info %p.\n",
1453  dst_surface, dst_palette, wine_dbgstr_rect(dst_rect), debugstr_w(src_file),
1454  wine_dbgstr_rect(src_rect), filter, color_key, src_info);
1455 
1456  if (!src_file || !dst_surface)
1457  return D3DERR_INVALIDCALL;
1458 
1459  if (FAILED(map_view_of_file(src_file, &data, &data_size)))
1460  return D3DXERR_INVALIDDATA;
1461 
1462  hr = D3DXLoadSurfaceFromFileInMemory(dst_surface, dst_palette, dst_rect,
1463  data, data_size, src_rect, filter, color_key, src_info);
1465 
1466  return hr;
1467 }
1468 
1469 HRESULT WINAPI D3DXLoadSurfaceFromResourceA(IDirect3DSurface9 *dst_surface,
1470  const PALETTEENTRY *dst_palette, const RECT *dst_rect, HMODULE src_module, const char *resource,
1471  const RECT *src_rect, DWORD filter, D3DCOLOR color_key, D3DXIMAGE_INFO *src_info)
1472 {
1473  UINT data_size;
1474  HRSRC resinfo;
1475  void *data;
1476 
1477  TRACE("dst_surface %p, dst_palette %p, dst_rect %s, src_module %p, resource %s, "
1478  "src_rect %s, filter %#x, color_key 0x%08x, src_info %p.\n",
1479  dst_surface, dst_palette, wine_dbgstr_rect(dst_rect), src_module, debugstr_a(resource),
1480  wine_dbgstr_rect(src_rect), filter, color_key, src_info);
1481 
1482  if (!dst_surface)
1483  return D3DERR_INVALIDCALL;
1484 
1485  if (!(resinfo = FindResourceA(src_module, resource, (const char *)RT_RCDATA))
1486  /* Try loading the resource as bitmap data (which is in DIB format D3DXIFF_DIB) */
1487  && !(resinfo = FindResourceA(src_module, resource, (const char *)RT_BITMAP)))
1488  return D3DXERR_INVALIDDATA;
1489 
1490  if (FAILED(load_resource_into_memory(src_module, resinfo, &data, &data_size)))
1491  return D3DXERR_INVALIDDATA;
1492 
1493  return D3DXLoadSurfaceFromFileInMemory(dst_surface, dst_palette, dst_rect,
1494  data, data_size, src_rect, filter, color_key, src_info);
1495 }
1496 
1497 HRESULT WINAPI D3DXLoadSurfaceFromResourceW(IDirect3DSurface9 *dst_surface,
1498  const PALETTEENTRY *dst_palette, const RECT *dst_rect, HMODULE src_module, const WCHAR *resource,
1499  const RECT *src_rect, DWORD filter, D3DCOLOR color_key, D3DXIMAGE_INFO *src_info)
1500 {
1501  UINT data_size;
1502  HRSRC resinfo;
1503  void *data;
1504 
1505  TRACE("dst_surface %p, dst_palette %p, dst_rect %s, src_module %p, resource %s, "
1506  "src_rect %s, filter %#x, color_key 0x%08x, src_info %p.\n",
1507  dst_surface, dst_palette, wine_dbgstr_rect(dst_rect), src_module, debugstr_w(resource),
1508  wine_dbgstr_rect(src_rect), filter, color_key, src_info);
1509 
1510  if (!dst_surface)
1511  return D3DERR_INVALIDCALL;
1512 
1513  if (!(resinfo = FindResourceW(src_module, resource, (const WCHAR *)RT_RCDATA))
1514  /* Try loading the resource as bitmap data (which is in DIB format D3DXIFF_DIB) */
1515  && !(resinfo = FindResourceW(src_module, resource, (const WCHAR *)RT_BITMAP)))
1516  return D3DXERR_INVALIDDATA;
1517 
1518  if (FAILED(load_resource_into_memory(src_module, resinfo, &data, &data_size)))
1519  return D3DXERR_INVALIDDATA;
1520 
1521  return D3DXLoadSurfaceFromFileInMemory(dst_surface, dst_palette, dst_rect,
1522  data, data_size, src_rect, filter, color_key, src_info);
1523 }
1524 
1525 
1526 /************************************************************
1527  * helper functions for D3DXLoadSurfaceFromMemory
1528  */
1530 {
1537 };
1538 
1539 static void init_argb_conversion_info(const struct pixel_format_desc *srcformat, const struct pixel_format_desc *destformat, struct argb_conversion_info *info)
1540 {
1541  UINT i;
1542  ZeroMemory(info->process_channel, 4 * sizeof(BOOL));
1543  info->channelmask = 0;
1544 
1545  info->srcformat = srcformat;
1546  info->destformat = destformat;
1547 
1548  for(i = 0;i < 4;i++) {
1549  /* srcshift is used to extract the _relevant_ components */
1550  info->srcshift[i] = srcformat->shift[i] + max( srcformat->bits[i] - destformat->bits[i], 0);
1551 
1552  /* destshift is used to move the components to the correct position */
1553  info->destshift[i] = destformat->shift[i] + max(destformat->bits[i] - srcformat->bits[i], 0);
1554 
1555  info->srcmask[i] = ((1 << srcformat->bits[i]) - 1) << srcformat->shift[i];
1556  info->destmask[i] = ((1 << destformat->bits[i]) - 1) << destformat->shift[i];
1557 
1558  /* channelmask specifies bits which aren't used in the source format but in the destination one */
1559  if(destformat->bits[i]) {
1560  if(srcformat->bits[i]) info->process_channel[i] = TRUE;
1561  else info->channelmask |= info->destmask[i];
1562  }
1563  }
1564 }
1565 
1566 /************************************************************
1567  * get_relevant_argb_components
1568  *
1569  * Extracts the relevant components from the source color and
1570  * drops the less significant bits if they aren't used by the destination format.
1571  */
1572 static void get_relevant_argb_components(const struct argb_conversion_info *info, const BYTE *col, DWORD *out)
1573 {
1574  unsigned int i, j;
1575  unsigned int component, mask;
1576 
1577  for (i = 0; i < 4; ++i)
1578  {
1579  if (!info->process_channel[i])
1580  continue;
1581 
1582  component = 0;
1583  mask = info->srcmask[i];
1584  for (j = 0; j < 4 && mask; ++j)
1585  {
1586  if (info->srcshift[i] < j * 8)
1587  component |= (col[j] & mask) << (j * 8 - info->srcshift[i]);
1588  else
1589  component |= (col[j] & mask) >> (info->srcshift[i] - j * 8);
1590  mask >>= 8;
1591  }
1592  out[i] = component;
1593  }
1594 }
1595 
1596 /************************************************************
1597  * make_argb_color
1598  *
1599  * Recombines the output of get_relevant_argb_components and converts
1600  * it to the destination format.
1601  */
1603 {
1604  UINT i;
1605  DWORD val = 0;
1606 
1607  for(i = 0;i < 4;i++) {
1608  if(info->process_channel[i]) {
1609  /* necessary to make sure that e.g. an X4R4G4B4 white maps to an R8G8B8 white instead of 0xf0f0f0 */
1610  signed int shift;
1611  for(shift = info->destshift[i]; shift > info->destformat->shift[i]; shift -= info->srcformat->bits[i]) val |= in[i] << shift;
1612  val |= (in[i] >> (info->destformat->shift[i] - shift)) << info->destformat->shift[i];
1613  }
1614  }
1615  val |= info->channelmask; /* new channels are set to their maximal value */
1616  return val;
1617 }
1618 
1619 /* It doesn't work for components bigger than 32 bits (or somewhat smaller but unaligned). */
1620 static void format_to_vec4(const struct pixel_format_desc *format, const BYTE *src, struct vec4 *dst)
1621 {
1622  DWORD mask, tmp;
1623  unsigned int c;
1624 
1625  for (c = 0; c < 4; ++c)
1626  {
1627  static const unsigned int component_offsets[4] = {3, 0, 1, 2};
1628  float *dst_component = (float *)dst + component_offsets[c];
1629 
1630  if (format->bits[c])
1631  {
1632  mask = ~0u >> (32 - format->bits[c]);
1633 
1634  memcpy(&tmp, src + format->shift[c] / 8,
1635  min(sizeof(DWORD), (format->shift[c] % 8 + format->bits[c] + 7) / 8));
1636 
1637  if (format->type == FORMAT_ARGBF16)
1638  *dst_component = float_16_to_32(tmp);
1639  else if (format->type == FORMAT_ARGBF)
1640  *dst_component = *(float *)&tmp;
1641  else
1642  *dst_component = (float)((tmp >> format->shift[c] % 8) & mask) / mask;
1643  }
1644  else
1645  *dst_component = 1.0f;
1646  }
1647 }
1648 
1649 /* It doesn't work for components bigger than 32 bits. */
1650 static void format_from_vec4(const struct pixel_format_desc *format, const struct vec4 *src, BYTE *dst)
1651 {
1652  DWORD v, mask32;
1653  unsigned int c, i;
1654 
1655  memset(dst, 0, format->bytes_per_pixel);
1656 
1657  for (c = 0; c < 4; ++c)
1658  {
1659  static const unsigned int component_offsets[4] = {3, 0, 1, 2};
1660  const float src_component = *((const float *)src + component_offsets[c]);
1661 
1662  if (!format->bits[c])
1663  continue;
1664 
1665  mask32 = ~0u >> (32 - format->bits[c]);
1666 
1667  if (format->type == FORMAT_ARGBF16)
1668  v = float_32_to_16(src_component);
1669  else if (format->type == FORMAT_ARGBF)
1670  v = *(DWORD *)&src_component;
1671  else
1672  v = (DWORD)(src_component * ((1 << format->bits[c]) - 1) + 0.5f);
1673 
1674  for (i = format->shift[c] / 8 * 8; i < format->shift[c] + format->bits[c]; i += 8)
1675  {
1676  BYTE mask, byte;
1677 
1678  if (format->shift[c] > i)
1679  {
1680  mask = mask32 << (format->shift[c] - i);
1681  byte = (v << (format->shift[c] - i)) & mask;
1682  }
1683  else
1684  {
1685  mask = mask32 >> (i - format->shift[c]);
1686  byte = (v >> (i - format->shift[c])) & mask;
1687  }
1688  dst[i / 8] |= byte;
1689  }
1690  }
1691 }
1692 
1693 /************************************************************
1694  * copy_pixels
1695  *
1696  * Copies the source buffer to the destination buffer.
1697  * Works for any pixel format.
1698  * The source and the destination must be block-aligned.
1699  */
1700 void copy_pixels(const BYTE *src, UINT src_row_pitch, UINT src_slice_pitch,
1701  BYTE *dst, UINT dst_row_pitch, UINT dst_slice_pitch, const struct volume *size,
1702  const struct pixel_format_desc *format)
1703 {
1704  UINT row, slice;
1705  BYTE *dst_addr;
1706  const BYTE *src_addr;
1707  UINT row_block_count = (size->width + format->block_width - 1) / format->block_width;
1708  UINT row_count = (size->height + format->block_height - 1) / format->block_height;
1709 
1710  for (slice = 0; slice < size->depth; slice++)
1711  {
1712  src_addr = src + slice * src_slice_pitch;
1713  dst_addr = dst + slice * dst_slice_pitch;
1714 
1715  for (row = 0; row < row_count; row++)
1716  {
1717  memcpy(dst_addr, src_addr, row_block_count * format->block_byte_count);
1718  src_addr += src_row_pitch;
1719  dst_addr += dst_row_pitch;
1720  }
1721  }
1722 }
1723 
1724 /************************************************************
1725  * convert_argb_pixels
1726  *
1727  * Copies the source buffer to the destination buffer, performing
1728  * any necessary format conversion and color keying.
1729  * Pixels outsize the source rect are blacked out.
1730  */
1731 void convert_argb_pixels(const BYTE *src, UINT src_row_pitch, UINT src_slice_pitch, const struct volume *src_size,
1732  const struct pixel_format_desc *src_format, BYTE *dst, UINT dst_row_pitch, UINT dst_slice_pitch,
1733  const struct volume *dst_size, const struct pixel_format_desc *dst_format, D3DCOLOR color_key,
1734  const PALETTEENTRY *palette)
1735 {
1736  struct argb_conversion_info conv_info, ck_conv_info;
1737  const struct pixel_format_desc *ck_format = NULL;
1738  DWORD channels[4];
1739  UINT min_width, min_height, min_depth;
1740  UINT x, y, z;
1741 
1742  TRACE("src %p, src_row_pitch %u, src_slice_pitch %u, src_size %p, src_format %p, dst %p, "
1743  "dst_row_pitch %u, dst_slice_pitch %u, dst_size %p, dst_format %p, color_key 0x%08x, palette %p.\n",
1744  src, src_row_pitch, src_slice_pitch, src_size, src_format, dst, dst_row_pitch, dst_slice_pitch, dst_size,
1746 
1747  ZeroMemory(channels, sizeof(channels));
1748  init_argb_conversion_info(src_format, dst_format, &conv_info);
1749 
1750  min_width = min(src_size->width, dst_size->width);
1751  min_height = min(src_size->height, dst_size->height);
1752  min_depth = min(src_size->depth, dst_size->depth);
1753 
1754  if (color_key)
1755  {
1756  /* Color keys are always represented in D3DFMT_A8R8G8B8 format. */
1757  ck_format = get_format_info(D3DFMT_A8R8G8B8);
1758  init_argb_conversion_info(src_format, ck_format, &ck_conv_info);
1759  }
1760 
1761  for (z = 0; z < min_depth; z++) {
1762  const BYTE *src_slice_ptr = src + z * src_slice_pitch;
1763  BYTE *dst_slice_ptr = dst + z * dst_slice_pitch;
1764 
1765  for (y = 0; y < min_height; y++) {
1766  const BYTE *src_ptr = src_slice_ptr + y * src_row_pitch;
1767  BYTE *dst_ptr = dst_slice_ptr + y * dst_row_pitch;
1768 
1769  for (x = 0; x < min_width; x++) {
1770  if (!src_format->to_rgba && !dst_format->from_rgba
1771  && src_format->type == dst_format->type
1772  && src_format->bytes_per_pixel <= 4 && dst_format->bytes_per_pixel <= 4)
1773  {
1774  DWORD val;
1775 
1776  get_relevant_argb_components(&conv_info, src_ptr, channels);
1777  val = make_argb_color(&conv_info, channels);
1778 
1779  if (color_key)
1780  {
1781  DWORD ck_pixel;
1782 
1783  get_relevant_argb_components(&ck_conv_info, src_ptr, channels);
1784  ck_pixel = make_argb_color(&ck_conv_info, channels);
1785  if (ck_pixel == color_key)
1786  val &= ~conv_info.destmask[0];
1787  }
1788  memcpy(dst_ptr, &val, dst_format->bytes_per_pixel);
1789  }
1790  else
1791  {
1792  struct vec4 color, tmp;
1793 
1794  format_to_vec4(src_format, src_ptr, &color);
1795  if (src_format->to_rgba)
1796  src_format->to_rgba(&color, &tmp, palette);
1797  else
1798  tmp = color;
1799 
1800  if (ck_format)
1801  {
1802  DWORD ck_pixel;
1803 
1804  format_from_vec4(ck_format, &tmp, (BYTE *)&ck_pixel);
1805  if (ck_pixel == color_key)
1806  tmp.w = 0.0f;
1807  }
1808 
1809  if (dst_format->from_rgba)
1810  dst_format->from_rgba(&tmp, &color);
1811  else
1812  color = tmp;
1813 
1814  format_from_vec4(dst_format, &color, dst_ptr);
1815  }
1816 
1817  src_ptr += src_format->bytes_per_pixel;
1818  dst_ptr += dst_format->bytes_per_pixel;
1819  }
1820 
1821  if (src_size->width < dst_size->width) /* black out remaining pixels */
1822  memset(dst_ptr, 0, dst_format->bytes_per_pixel * (dst_size->width - src_size->width));
1823  }
1824 
1825  if (src_size->height < dst_size->height) /* black out remaining pixels */
1826  memset(dst + src_size->height * dst_row_pitch, 0, dst_row_pitch * (dst_size->height - src_size->height));
1827  }
1828  if (src_size->depth < dst_size->depth) /* black out remaining pixels */
1829  memset(dst + src_size->depth * dst_slice_pitch, 0, dst_slice_pitch * (dst_size->depth - src_size->depth));
1830 }
1831 
1832 /************************************************************
1833  * point_filter_argb_pixels
1834  *
1835  * Copies the source buffer to the destination buffer, performing
1836  * any necessary format conversion, color keying and stretching
1837  * using a point filter.
1838  */
1839 void point_filter_argb_pixels(const BYTE *src, UINT src_row_pitch, UINT src_slice_pitch, const struct volume *src_size,
1840  const struct pixel_format_desc *src_format, BYTE *dst, UINT dst_row_pitch, UINT dst_slice_pitch,
1841  const struct volume *dst_size, const struct pixel_format_desc *dst_format, D3DCOLOR color_key,
1842  const PALETTEENTRY *palette)
1843 {
1844  struct argb_conversion_info conv_info, ck_conv_info;
1845  const struct pixel_format_desc *ck_format = NULL;
1846  DWORD channels[4];
1847  UINT x, y, z;
1848 
1849  TRACE("src %p, src_row_pitch %u, src_slice_pitch %u, src_size %p, src_format %p, dst %p, "
1850  "dst_row_pitch %u, dst_slice_pitch %u, dst_size %p, dst_format %p, color_key 0x%08x, palette %p.\n",
1851  src, src_row_pitch, src_slice_pitch, src_size, src_format, dst, dst_row_pitch, dst_slice_pitch, dst_size,
1853 
1854  ZeroMemory(channels, sizeof(channels));
1855  init_argb_conversion_info(src_format, dst_format, &conv_info);
1856 
1857  if (color_key)
1858  {
1859  /* Color keys are always represented in D3DFMT_A8R8G8B8 format. */
1860  ck_format = get_format_info(D3DFMT_A8R8G8B8);
1861  init_argb_conversion_info(src_format, ck_format, &ck_conv_info);
1862  }
1863 
1864  for (z = 0; z < dst_size->depth; z++)
1865  {
1866  BYTE *dst_slice_ptr = dst + z * dst_slice_pitch;
1867  const BYTE *src_slice_ptr = src + src_slice_pitch * (z * src_size->depth / dst_size->depth);
1868 
1869  for (y = 0; y < dst_size->height; y++)
1870  {
1871  BYTE *dst_ptr = dst_slice_ptr + y * dst_row_pitch;
1872  const BYTE *src_row_ptr = src_slice_ptr + src_row_pitch * (y * src_size->height / dst_size->height);
1873 
1874  for (x = 0; x < dst_size->width; x++)
1875  {
1876  const BYTE *src_ptr = src_row_ptr + (x * src_size->width / dst_size->width) * src_format->bytes_per_pixel;
1877 
1878  if (!src_format->to_rgba && !dst_format->from_rgba
1879  && src_format->type == dst_format->type
1880  && src_format->bytes_per_pixel <= 4 && dst_format->bytes_per_pixel <= 4)
1881  {
1882  DWORD val;
1883 
1884  get_relevant_argb_components(&conv_info, src_ptr, channels);
1885  val = make_argb_color(&conv_info, channels);
1886 
1887  if (color_key)
1888  {
1889  DWORD ck_pixel;
1890 
1891  get_relevant_argb_components(&ck_conv_info, src_ptr, channels);
1892  ck_pixel = make_argb_color(&ck_conv_info, channels);
1893  if (ck_pixel == color_key)
1894  val &= ~conv_info.destmask[0];
1895  }
1896  memcpy(dst_ptr, &val, dst_format->bytes_per_pixel);
1897  }
1898  else
1899  {
1900  struct vec4 color, tmp;
1901 
1902  format_to_vec4(src_format, src_ptr, &color);
1903  if (src_format->to_rgba)
1904  src_format->to_rgba(&color, &tmp, palette);
1905  else
1906  tmp = color;
1907 
1908  if (ck_format)
1909  {
1910  DWORD ck_pixel;
1911 
1912  format_from_vec4(ck_format, &tmp, (BYTE *)&ck_pixel);
1913  if (ck_pixel == color_key)
1914  tmp.w = 0.0f;
1915  }
1916 
1917  if (dst_format->from_rgba)
1918  dst_format->from_rgba(&tmp, &color);
1919  else
1920  color = tmp;
1921 
1922  format_from_vec4(dst_format, &color, dst_ptr);
1923  }
1924 
1925  dst_ptr += dst_format->bytes_per_pixel;
1926  }
1927  }
1928  }
1929 }
1930 
1931 /************************************************************
1932  * D3DXLoadSurfaceFromMemory
1933  *
1934  * Loads data from a given memory chunk into a surface,
1935  * applying any of the specified filters.
1936  *
1937  * PARAMS
1938  * pDestSurface [I] pointer to the surface
1939  * pDestPalette [I] palette to use
1940  * pDestRect [I] to be filled area of the surface
1941  * pSrcMemory [I] pointer to the source data
1942  * SrcFormat [I] format of the source pixel data
1943  * SrcPitch [I] number of bytes in a row
1944  * pSrcPalette [I] palette used in the source image
1945  * pSrcRect [I] area of the source data to load
1946  * dwFilter [I] filter to apply on stretching
1947  * Colorkey [I] colorkey
1948  *
1949  * RETURNS
1950  * Success: D3D_OK, if we successfully load the pixel data into our surface or
1951  * if pSrcMemory is NULL but the other parameters are valid
1952  * Failure: D3DERR_INVALIDCALL, if pDestSurface, SrcPitch or pSrcRect is NULL or
1953  * if SrcFormat is an invalid format (other than D3DFMT_UNKNOWN) or
1954  * if DestRect is invalid
1955  * D3DXERR_INVALIDDATA, if we fail to lock pDestSurface
1956  * E_FAIL, if SrcFormat is D3DFMT_UNKNOWN or the dimensions of pSrcRect are invalid
1957  *
1958  * NOTES
1959  * pSrcRect specifies the dimensions of the source data;
1960  * negative values for pSrcRect are allowed as we're only looking at the width and height anyway.
1961  *
1962  */
1963 HRESULT WINAPI D3DXLoadSurfaceFromMemory(IDirect3DSurface9 *dst_surface,
1964  const PALETTEENTRY *dst_palette, const RECT *dst_rect, const void *src_memory,
1965  D3DFORMAT src_format, UINT src_pitch, const PALETTEENTRY *src_palette, const RECT *src_rect,
1967 {
1968  const struct pixel_format_desc *srcformatdesc, *destformatdesc;
1969  struct volume src_size, dst_size, dst_size_aligned;
1970  RECT dst_rect_temp, dst_rect_aligned;
1971  IDirect3DSurface9 *surface;
1972  D3DSURFACE_DESC surfdesc;
1973  D3DLOCKED_RECT lockrect;
1974  HRESULT hr;
1975 
1976  TRACE("(%p, %p, %s, %p, %#x, %u, %p, %s, %#x, 0x%08x)\n",
1977  dst_surface, dst_palette, wine_dbgstr_rect(dst_rect), src_memory, src_format,
1978  src_pitch, src_palette, wine_dbgstr_rect(src_rect), filter, color_key);
1979 
1980  if (!dst_surface || !src_memory || !src_rect)
1981  {
1982  WARN("Invalid argument specified.\n");
1983  return D3DERR_INVALIDCALL;
1984  }
1985  if (src_format == D3DFMT_UNKNOWN
1986  || src_rect->left >= src_rect->right
1987  || src_rect->top >= src_rect->bottom)
1988  {
1989  WARN("Invalid src_format or src_rect.\n");
1990  return E_FAIL;
1991  }
1992 
1993  srcformatdesc = get_format_info(src_format);
1994  if (srcformatdesc->type == FORMAT_UNKNOWN)
1995  {
1996  FIXME("Unsupported format %#x.\n", src_format);
1997  return E_NOTIMPL;
1998  }
1999 
2000  src_size.width = src_rect->right - src_rect->left;
2001  src_size.height = src_rect->bottom - src_rect->top;
2002  src_size.depth = 1;
2003 
2004  IDirect3DSurface9_GetDesc(dst_surface, &surfdesc);
2005  destformatdesc = get_format_info(surfdesc.Format);
2006  if (!dst_rect)
2007  {
2008  dst_rect = &dst_rect_temp;
2009  dst_rect_temp.left = 0;
2010  dst_rect_temp.top = 0;
2011  dst_rect_temp.right = surfdesc.Width;
2012  dst_rect_temp.bottom = surfdesc.Height;
2013  }
2014  else
2015  {
2016  if (dst_rect->left > dst_rect->right || dst_rect->right > surfdesc.Width
2017  || dst_rect->top > dst_rect->bottom || dst_rect->bottom > surfdesc.Height
2018  || dst_rect->left < 0 || dst_rect->top < 0)
2019  {
2020  WARN("Invalid dst_rect specified.\n");
2021  return D3DERR_INVALIDCALL;
2022  }
2023  if (dst_rect->left == dst_rect->right || dst_rect->top == dst_rect->bottom)
2024  {
2025  WARN("Empty dst_rect specified.\n");
2026  return D3D_OK;
2027  }
2028  }
2029 
2030  dst_rect_aligned = *dst_rect;
2031  if (dst_rect_aligned.left & (destformatdesc->block_width - 1))
2032  dst_rect_aligned.left = dst_rect_aligned.left & ~(destformatdesc->block_width - 1);
2033  if (dst_rect_aligned.top & (destformatdesc->block_height - 1))
2034  dst_rect_aligned.top = dst_rect_aligned.top & ~(destformatdesc->block_height - 1);
2035  if (dst_rect_aligned.right & (destformatdesc->block_width - 1) && dst_rect_aligned.right != surfdesc.Width)
2036  dst_rect_aligned.right = min((dst_rect_aligned.right + destformatdesc->block_width - 1)
2037  & ~(destformatdesc->block_width - 1), surfdesc.Width);
2038  if (dst_rect_aligned.bottom & (destformatdesc->block_height - 1) && dst_rect_aligned.bottom != surfdesc.Height)
2039  dst_rect_aligned.bottom = min((dst_rect_aligned.bottom + destformatdesc->block_height - 1)
2040  & ~(destformatdesc->block_height - 1), surfdesc.Height);
2041 
2042  dst_size.width = dst_rect->right - dst_rect->left;
2043  dst_size.height = dst_rect->bottom - dst_rect->top;
2044  dst_size.depth = 1;
2045  dst_size_aligned.width = dst_rect_aligned.right - dst_rect_aligned.left;
2046  dst_size_aligned.height = dst_rect_aligned.bottom - dst_rect_aligned.top;
2047  dst_size_aligned.depth = 1;
2048 
2049  if (filter == D3DX_DEFAULT)
2051 
2052  if (FAILED(hr = lock_surface(dst_surface, &dst_rect_aligned, &lockrect, &surface, TRUE)))
2053  return hr;
2054 
2055  src_memory = (BYTE *)src_memory + src_rect->top / srcformatdesc->block_height * src_pitch
2056  + src_rect->left / srcformatdesc->block_width * srcformatdesc->block_byte_count;
2057 
2058  if (src_format == surfdesc.Format
2059  && dst_size.width == src_size.width
2060  && dst_size.height == src_size.height
2061  && color_key == 0
2062  && !(src_rect->left & (srcformatdesc->block_width - 1))
2063  && !(src_rect->top & (srcformatdesc->block_height - 1))
2064  && !(dst_rect->left & (destformatdesc->block_width - 1))
2065  && !(dst_rect->top & (destformatdesc->block_height - 1)))
2066  {
2067  TRACE("Simple copy.\n");
2068  copy_pixels(src_memory, src_pitch, 0, lockrect.pBits, lockrect.Pitch, 0,
2069  &src_size, srcformatdesc);
2070  }
2071  else /* Stretching or format conversion. */
2072  {
2073  const struct pixel_format_desc *dst_format;
2074  DWORD *src_uncompressed = NULL;
2075  BYTE *dst_uncompressed = NULL;
2076  unsigned int dst_pitch;
2077  BYTE *dst_mem;
2078 
2079  if (!is_conversion_from_supported(srcformatdesc)
2080  || !is_conversion_to_supported(destformatdesc))
2081  {
2082  FIXME("Unsupported format conversion %#x -> %#x.\n", src_format, surfdesc.Format);
2083  unlock_surface(dst_surface, &dst_rect_aligned, surface, FALSE);
2084  return E_NOTIMPL;
2085  }
2086 
2087  if (srcformatdesc->type == FORMAT_DXT)
2088  {
2089  void (*fetch_dxt_texel)(int srcRowStride, const BYTE *pixdata,
2090  int i, int j, void *texel);
2091  unsigned int x, y;
2092 
2093  src_pitch = src_pitch * srcformatdesc->block_width / srcformatdesc->block_byte_count;
2094 
2095  src_uncompressed = heap_alloc(src_size.width * src_size.height * sizeof(DWORD));
2096  if (!src_uncompressed)
2097  {
2098  unlock_surface(dst_surface, &dst_rect_aligned, surface, FALSE);
2099  return E_OUTOFMEMORY;
2100  }
2101 
2102  switch(src_format)
2103  {
2104  case D3DFMT_DXT1:
2105  fetch_dxt_texel = fetch_2d_texel_rgba_dxt1;
2106  break;
2107  case D3DFMT_DXT2:
2108  case D3DFMT_DXT3:
2109  fetch_dxt_texel = fetch_2d_texel_rgba_dxt3;
2110  break;
2111  case D3DFMT_DXT4:
2112  case D3DFMT_DXT5:
2113  fetch_dxt_texel = fetch_2d_texel_rgba_dxt5;
2114  break;
2115  default:
2116  FIXME("Unexpected compressed texture format %u.\n", src_format);
2117  fetch_dxt_texel = NULL;
2118  }
2119 
2120  TRACE("Uncompressing DXTn surface.\n");
2121  for (y = 0; y < src_size.height; ++y)
2122  {
2123  DWORD *ptr = &src_uncompressed[y * src_size.width];
2124  for (x = 0; x < src_size.width; ++x)
2125  {
2126  fetch_dxt_texel(src_pitch, src_memory, x + src_rect->left, y + src_rect->top, ptr);
2127  ++ptr;
2128  }
2129  }
2130  src_memory = src_uncompressed;
2131  src_pitch = src_size.width * sizeof(DWORD);
2132  srcformatdesc = get_format_info(D3DFMT_A8B8G8R8);
2133  }
2134 
2135  if (destformatdesc->type == FORMAT_DXT)
2136  {
2137  BOOL dst_misaligned = dst_rect->left != dst_rect_aligned.left
2138  || dst_rect->top != dst_rect_aligned.top
2139  || dst_rect->right != dst_rect_aligned.right
2140  || dst_rect->bottom != dst_rect_aligned.bottom;
2141 
2142  dst_uncompressed = HeapAlloc(GetProcessHeap(), dst_misaligned ? HEAP_ZERO_MEMORY : 0,
2143  dst_size_aligned.width * dst_size_aligned.height * sizeof(DWORD));
2144  if (!dst_uncompressed)
2145  {
2146  heap_free(src_uncompressed);
2147  unlock_surface(dst_surface, &dst_rect_aligned, surface, FALSE);
2148  return E_OUTOFMEMORY;
2149  }
2150  dst_pitch = dst_size_aligned.width * sizeof(DWORD);
2152  dst_mem = dst_uncompressed + (dst_rect->top - dst_rect_aligned.top) * dst_pitch
2153  + (dst_rect->left - dst_rect_aligned.left) * sizeof(DWORD);
2154  }
2155  else
2156  {
2157  dst_mem = lockrect.pBits;
2158  dst_pitch = lockrect.Pitch;
2159  dst_format = destformatdesc;
2160  }
2161 
2162  if ((filter & 0xf) == D3DX_FILTER_NONE)
2163  {
2164  convert_argb_pixels(src_memory, src_pitch, 0, &src_size, srcformatdesc,
2165  dst_mem, dst_pitch, 0, &dst_size, dst_format, color_key, src_palette);
2166  }
2167  else /* if ((filter & 0xf) == D3DX_FILTER_POINT) */
2168  {
2169  if ((filter & 0xf) != D3DX_FILTER_POINT)
2170  FIXME("Unhandled filter %#x.\n", filter);
2171 
2172  /* Always apply a point filter until D3DX_FILTER_LINEAR,
2173  * D3DX_FILTER_TRIANGLE and D3DX_FILTER_BOX are implemented. */
2174  point_filter_argb_pixels(src_memory, src_pitch, 0, &src_size, srcformatdesc,
2175  dst_mem, dst_pitch, 0, &dst_size, dst_format, color_key, src_palette);
2176  }
2177 
2178  heap_free(src_uncompressed);
2179 
2180  if (dst_uncompressed)
2181  {
2182  GLenum gl_format = 0;
2183 
2184  TRACE("Compressing DXTn surface.\n");
2185  switch(surfdesc.Format)
2186  {
2187  case D3DFMT_DXT1:
2189  break;
2190  case D3DFMT_DXT2:
2191  case D3DFMT_DXT3:
2193  break;
2194  case D3DFMT_DXT4:
2195  case D3DFMT_DXT5:
2197  break;
2198  default:
2199  ERR("Unexpected destination compressed format %u.\n", surfdesc.Format);
2200  }
2201  tx_compress_dxtn(4, dst_size_aligned.width, dst_size_aligned.height,
2202  dst_uncompressed, gl_format, lockrect.pBits,
2203  lockrect.Pitch * destformatdesc->block_width / destformatdesc->block_byte_count);
2204  heap_free(dst_uncompressed);
2205  }
2206  }
2207 
2208  return unlock_surface(dst_surface, &dst_rect_aligned, surface, TRUE);
2209 }
2210 
2211 /************************************************************
2212  * D3DXLoadSurfaceFromSurface
2213  *
2214  * Copies the contents from one surface to another, performing any required
2215  * format conversion, resizing or filtering.
2216  *
2217  * PARAMS
2218  * pDestSurface [I] pointer to the destination surface
2219  * pDestPalette [I] palette to use
2220  * pDestRect [I] to be filled area of the surface
2221  * pSrcSurface [I] pointer to the source surface
2222  * pSrcPalette [I] palette used for the source surface
2223  * pSrcRect [I] area of the source data to load
2224  * dwFilter [I] filter to apply on resizing
2225  * Colorkey [I] any ARGB value or 0 to disable color-keying
2226  *
2227  * RETURNS
2228  * Success: D3D_OK
2229  * Failure: D3DERR_INVALIDCALL, if pDestSurface or pSrcSurface is NULL
2230  * D3DXERR_INVALIDDATA, if one of the surfaces is not lockable
2231  *
2232  */
2233 HRESULT WINAPI D3DXLoadSurfaceFromSurface(IDirect3DSurface9 *dst_surface,
2234  const PALETTEENTRY *dst_palette, const RECT *dst_rect, IDirect3DSurface9 *src_surface,
2235  const PALETTEENTRY *src_palette, const RECT *src_rect, DWORD filter, D3DCOLOR color_key)
2236 {
2237  const struct pixel_format_desc *src_format_desc, *dst_format_desc;
2238  D3DSURFACE_DESC src_desc, dst_desc;
2239  struct volume src_size, dst_size;
2240  IDirect3DSurface9 *temp_surface;
2241  D3DTEXTUREFILTERTYPE d3d_filter;
2242  IDirect3DDevice9 *device;
2244  RECT dst_rect_temp;
2245  HRESULT hr;
2246  RECT s;
2247 
2248  TRACE("dst_surface %p, dst_palette %p, dst_rect %s, src_surface %p, "
2249  "src_palette %p, src_rect %s, filter %#x, color_key 0x%08x.\n",
2250  dst_surface, dst_palette, wine_dbgstr_rect(dst_rect), src_surface,
2251  src_palette, wine_dbgstr_rect(src_rect), filter, color_key);
2252 
2253  if (!dst_surface || !src_surface)
2254  return D3DERR_INVALIDCALL;
2255 
2256  IDirect3DSurface9_GetDesc(src_surface, &src_desc);
2257  src_format_desc = get_format_info(src_desc.Format);
2258  if (!src_rect)
2259  {
2260  SetRect(&s, 0, 0, src_desc.Width, src_desc.Height);
2261  src_rect = &s;
2262  }
2263  else if (src_rect->left == src_rect->right || src_rect->top == src_rect->bottom)
2264  {
2265  WARN("Empty src_rect specified.\n");
2266  return filter == D3DX_FILTER_NONE ? D3D_OK : E_FAIL;
2267  }
2268  else if (src_rect->left > src_rect->right || src_rect->right > src_desc.Width
2269  || src_rect->left < 0 || src_rect->left > src_desc.Width
2270  || src_rect->top > src_rect->bottom || src_rect->bottom > src_desc.Height
2271  || src_rect->top < 0 || src_rect->top > src_desc.Height)
2272  {
2273  WARN("Invalid src_rect specified.\n");
2274  return D3DERR_INVALIDCALL;
2275  }
2276 
2277  src_size.width = src_rect->right - src_rect->left;
2278  src_size.height = src_rect->bottom - src_rect->top;
2279  src_size.depth = 1;
2280 
2281  IDirect3DSurface9_GetDesc(dst_surface, &dst_desc);
2282  dst_format_desc = get_format_info(dst_desc.Format);
2283  if (!dst_rect)
2284  {
2285  SetRect(&dst_rect_temp, 0, 0, dst_desc.Width, dst_desc.Height);
2286  dst_rect = &dst_rect_temp;
2287  }
2288  else if (dst_rect->left == dst_rect->right || dst_rect->top == dst_rect->bottom)
2289  {
2290  WARN("Empty dst_rect specified.\n");
2291  return filter == D3DX_FILTER_NONE ? D3D_OK : E_FAIL;
2292  }
2293  else if (dst_rect->left > dst_rect->right || dst_rect->right > dst_desc.Width
2294  || dst_rect->left < 0 || dst_rect->left > dst_desc.Width
2295  || dst_rect->top > dst_rect->bottom || dst_rect->bottom > dst_desc.Height
2296  || dst_rect->top < 0 || dst_rect->top > dst_desc.Height)
2297  {
2298  WARN("Invalid dst_rect specified.\n");
2299  return D3DERR_INVALIDCALL;
2300  }
2301 
2302  dst_size.width = dst_rect->right - dst_rect->left;
2303  dst_size.height = dst_rect->bottom - dst_rect->top;
2304  dst_size.depth = 1;
2305 
2306  if (!dst_palette && !src_palette && !color_key)
2307  {
2308  if (src_desc.Format == dst_desc.Format
2309  && dst_size.width == src_size.width
2310  && dst_size.height == src_size.height
2311  && color_key == 0
2312  && !(src_rect->left & (src_format_desc->block_width - 1))
2313  && !(src_rect->top & (src_format_desc->block_height - 1))
2314  && !(dst_rect->left & (dst_format_desc->block_width - 1))
2315  && !(dst_rect->top & (dst_format_desc->block_height - 1)))
2316  {
2317  d3d_filter = D3DTEXF_NONE;
2318  }
2319  else
2320  {
2321  switch (filter)
2322  {
2323  case D3DX_FILTER_NONE:
2324  d3d_filter = D3DTEXF_NONE;
2325  break;
2326 
2327  case D3DX_FILTER_POINT:
2328  d3d_filter = D3DTEXF_POINT;
2329  break;
2330 
2331  case D3DX_FILTER_LINEAR:
2332  d3d_filter = D3DTEXF_LINEAR;
2333  break;
2334 
2335  default:
2336  d3d_filter = D3DTEXF_FORCE_DWORD;
2337  break;
2338  }
2339  }
2340 
2341  if (d3d_filter != D3DTEXF_FORCE_DWORD)
2342  {
2343  IDirect3DSurface9_GetDevice(src_surface, &device);
2344  hr = IDirect3DDevice9_StretchRect(device, src_surface, src_rect, dst_surface, dst_rect, d3d_filter);
2346  if (SUCCEEDED(hr))
2347  return D3D_OK;
2348  }
2349  }
2350 
2351  if (FAILED(lock_surface(src_surface, NULL, &lock, &temp_surface, FALSE)))
2352  return D3DXERR_INVALIDDATA;
2353 
2354  hr = D3DXLoadSurfaceFromMemory(dst_surface, dst_palette, dst_rect, lock.pBits,
2355  src_desc.Format, lock.Pitch, src_palette, src_rect, filter, color_key);
2356 
2357  if (FAILED(unlock_surface(src_surface, NULL, temp_surface, FALSE)))
2358  return D3DXERR_INVALIDDATA;
2359 
2360  return hr;
2361 }
2362 
2363 
2364 HRESULT WINAPI D3DXSaveSurfaceToFileA(const char *dst_filename, D3DXIMAGE_FILEFORMAT file_format,
2365  IDirect3DSurface9 *src_surface, const PALETTEENTRY *src_palette, const RECT *src_rect)
2366 {
2367  int len;
2368  WCHAR *filename;
2369  HRESULT hr;
2371 
2372  TRACE("(%s, %#x, %p, %p, %s): relay\n",
2373  wine_dbgstr_a(dst_filename), file_format, src_surface, src_palette, wine_dbgstr_rect(src_rect));
2374 
2375  if (!dst_filename) return D3DERR_INVALIDCALL;
2376 
2377  len = MultiByteToWideChar(CP_ACP, 0, dst_filename, -1, NULL, 0);
2378  filename = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2379  if (!filename) return E_OUTOFMEMORY;
2380  MultiByteToWideChar(CP_ACP, 0, dst_filename, -1, filename, len);
2381 
2382  hr = D3DXSaveSurfaceToFileInMemory(&buffer, file_format, src_surface, src_palette, src_rect);
2383  if (SUCCEEDED(hr))
2384  {
2387  }
2388 
2390  return hr;
2391 }
2392 
2394  IDirect3DSurface9 *src_surface, const PALETTEENTRY *src_palette, const RECT *src_rect)
2395 {
2396  HRESULT hr;
2398 
2399  TRACE("(%s, %#x, %p, %p, %s): relay\n",
2400  wine_dbgstr_w(dst_filename), file_format, src_surface, src_palette, wine_dbgstr_rect(src_rect));
2401 
2402  if (!dst_filename) return D3DERR_INVALIDCALL;
2403 
2404  hr = D3DXSaveSurfaceToFileInMemory(&buffer, file_format, src_surface, src_palette, src_rect);
2405  if (SUCCEEDED(hr))
2406  {
2407  hr = write_buffer_to_file(dst_filename, buffer);
2409  }
2410 
2411  return hr;
2412 }
2413 
2415  IDirect3DSurface9 *src_surface, const PALETTEENTRY *src_palette, const RECT *src_rect)
2416 {
2417  IWICBitmapEncoder *encoder = NULL;
2418  IWICBitmapFrameEncode *frame = NULL;
2419  IPropertyBag2 *encoder_options = NULL;
2420  IStream *stream = NULL;
2421  HRESULT hr;
2422  const GUID *container_format;
2423  const GUID *pixel_format_guid;
2424  WICPixelFormatGUID wic_pixel_format;
2426  D3DFORMAT d3d_pixel_format;
2427  D3DSURFACE_DESC src_surface_desc;
2428  IDirect3DSurface9 *temp_surface;
2429  D3DLOCKED_RECT locked_rect;
2430  int width, height;
2431  STATSTG stream_stats;
2432  HGLOBAL stream_hglobal;
2434  DWORD size;
2435 
2436  TRACE("dst_buffer %p, file_format %#x, src_surface %p, src_palette %p, src_rect %s.\n",
2437  dst_buffer, file_format, src_surface, src_palette, wine_dbgstr_rect(src_rect));
2438 
2439  if (!dst_buffer || !src_surface) return D3DERR_INVALIDCALL;
2440 
2441  if (src_palette)
2442  {
2443  FIXME("Saving surfaces with palettized pixel formats is not implemented yet\n");
2444  return D3DERR_INVALIDCALL;
2445  }
2446 
2447  switch (file_format)
2448  {
2449  case D3DXIFF_BMP:
2450  case D3DXIFF_DIB:
2451  container_format = &GUID_ContainerFormatBmp;
2452  break;
2453  case D3DXIFF_PNG:
2454  container_format = &GUID_ContainerFormatPng;
2455  break;
2456  case D3DXIFF_JPG:
2457  container_format = &GUID_ContainerFormatJpeg;
2458  break;
2459  case D3DXIFF_DDS:
2460  return save_dds_surface_to_memory(dst_buffer, src_surface, src_rect);
2461  case D3DXIFF_HDR:
2462  case D3DXIFF_PFM:
2463  case D3DXIFF_TGA:
2464  case D3DXIFF_PPM:
2465  FIXME("File format %#x is not supported yet\n", file_format);
2466  return E_NOTIMPL;
2467  default:
2468  return D3DERR_INVALIDCALL;
2469  }
2470 
2471  IDirect3DSurface9_GetDesc(src_surface, &src_surface_desc);
2472  if (src_rect)
2473  {
2474  if (src_rect->left == src_rect->right || src_rect->top == src_rect->bottom)
2475  {
2476  WARN("Invalid rectangle with 0 area\n");
2477  return D3DXCreateBuffer(64, dst_buffer);
2478  }
2479  if (src_rect->left < 0 || src_rect->top < 0)
2480  return D3DERR_INVALIDCALL;
2481  if (src_rect->left > src_rect->right || src_rect->top > src_rect->bottom)
2482  return D3DERR_INVALIDCALL;
2483  if (src_rect->right > src_surface_desc.Width || src_rect->bottom > src_surface_desc.Height)
2484  return D3DERR_INVALIDCALL;
2485 
2486  width = src_rect->right - src_rect->left;
2487  height = src_rect->bottom - src_rect->top;
2488  }
2489  else
2490  {
2491  width = src_surface_desc.Width;
2492  height = src_surface_desc.Height;
2493  }
2494 
2495  hr = WICCreateImagingFactory_Proxy(WINCODEC_SDK_VERSION, &factory);
2496  if (FAILED(hr)) goto cleanup_err;
2497 
2498  hr = IWICImagingFactory_CreateEncoder(factory, container_format, NULL, &encoder);
2499  IWICImagingFactory_Release(factory);
2500  if (FAILED(hr)) goto cleanup_err;
2501 
2503  if (FAILED(hr)) goto cleanup_err;
2504 
2505  hr = IWICBitmapEncoder_Initialize(encoder, stream, WICBitmapEncoderNoCache);
2506  if (FAILED(hr)) goto cleanup_err;
2507 
2508  hr = IWICBitmapEncoder_CreateNewFrame(encoder, &frame, &encoder_options);
2509  if (FAILED(hr)) goto cleanup_err;
2510 
2511  hr = IWICBitmapFrameEncode_Initialize(frame, encoder_options);
2512  if (FAILED(hr)) goto cleanup_err;
2513 
2514  hr = IWICBitmapFrameEncode_SetSize(frame, width, height);
2515  if (FAILED(hr)) goto cleanup_err;
2516 
2517  pixel_format_guid = d3dformat_to_wic_guid(src_surface_desc.Format);
2518  if (!pixel_format_guid)
2519  {
2520  FIXME("Pixel format %#x is not supported yet\n", src_surface_desc.Format);
2521  hr = E_NOTIMPL;
2522  goto cleanup;
2523  }
2524 
2525  memcpy(&wic_pixel_format, pixel_format_guid, sizeof(GUID));
2526  hr = IWICBitmapFrameEncode_SetPixelFormat(frame, &wic_pixel_format);
2527  d3d_pixel_format = wic_guid_to_d3dformat(&wic_pixel_format);
2528  if (SUCCEEDED(hr) && d3d_pixel_format != D3DFMT_UNKNOWN)
2529  {
2530  TRACE("Using pixel format %s %#x\n", debugstr_guid(&wic_pixel_format), d3d_pixel_format);
2531  if (src_surface_desc.Format == d3d_pixel_format) /* Simple copy */
2532  {
2533  if (FAILED(hr = lock_surface(src_surface, src_rect, &locked_rect, &temp_surface, FALSE)))
2534  goto cleanup;
2535 
2536  IWICBitmapFrameEncode_WritePixels(frame, height,
2537  locked_rect.Pitch, height * locked_rect.Pitch, locked_rect.pBits);
2538  unlock_surface(src_surface, src_rect, temp_surface, FALSE);
2539  }
2540  else /* Pixel format conversion */
2541  {
2542  const struct pixel_format_desc *src_format_desc, *dst_format_desc;
2543  struct volume size;
2544  DWORD dst_pitch;
2545  void *dst_data;
2546 
2547  src_format_desc = get_format_info(src_surface_desc.Format);
2548  dst_format_desc = get_format_info(d3d_pixel_format);
2549  if (!is_conversion_from_supported(src_format_desc)
2550  || !is_conversion_to_supported(dst_format_desc))
2551  {
2552  FIXME("Unsupported format conversion %#x -> %#x.\n",
2553  src_surface_desc.Format, d3d_pixel_format);
2554  hr = E_NOTIMPL;
2555  goto cleanup;
2556  }
2557 
2558  size.width = width;
2559  size.height = height;
2560  size.depth = 1;
2561  dst_pitch = width * dst_format_desc->bytes_per_pixel;
2562  dst_data = HeapAlloc(GetProcessHeap(), 0, dst_pitch * height);
2563  if (!dst_data)
2564  {
2565  hr = E_OUTOFMEMORY;
2566  goto cleanup;
2567  }
2568  if (FAILED(hr = lock_surface(src_surface, src_rect, &locked_rect, &temp_surface, FALSE)))
2569  {
2570  HeapFree(GetProcessHeap(), 0, dst_data);
2571  goto cleanup;
2572  }
2573  convert_argb_pixels(locked_rect.pBits, locked_rect.Pitch, 0, &size, src_format_desc,
2574  dst_data, dst_pitch, 0, &size, dst_format_desc, 0, NULL);
2575  unlock_surface(src_surface, src_rect, temp_surface, FALSE);
2576 
2577  IWICBitmapFrameEncode_WritePixels(frame, height, dst_pitch, dst_pitch * height, dst_data);
2578  HeapFree(GetProcessHeap(), 0, dst_data);
2579  }
2580 
2581  hr = IWICBitmapFrameEncode_Commit(frame);
2582  if (SUCCEEDED(hr)) hr = IWICBitmapEncoder_Commit(encoder);
2583  }
2584  else WARN("Unsupported pixel format %#x\n", src_surface_desc.Format);
2585 
2586  /* copy data from stream to ID3DXBuffer */
2587  hr = IStream_Stat(stream, &stream_stats, STATFLAG_NONAME);
2588  if (FAILED(hr)) goto cleanup_err;
2589 
2590  if (stream_stats.cbSize.u.HighPart != 0)
2591  {
2593  goto cleanup;
2594  }
2595  size = stream_stats.cbSize.u.LowPart;
2596 
2597  /* Remove BMP header for DIB */
2598  if (file_format == D3DXIFF_DIB)
2599  size -= sizeof(BITMAPFILEHEADER);
2600 
2602  if (FAILED(hr)) goto cleanup;
2603 
2604  hr = GetHGlobalFromStream(stream, &stream_hglobal);
2605  if (SUCCEEDED(hr))
2606  {
2607  void *buffer_pointer = ID3DXBuffer_GetBufferPointer(buffer);
2608  void *stream_data = GlobalLock(stream_hglobal);
2609  /* Remove BMP header for DIB */
2610  if (file_format == D3DXIFF_DIB)
2611  stream_data = (void*)((BYTE*)stream_data + sizeof(BITMAPFILEHEADER));
2612  memcpy(buffer_pointer, stream_data, size);
2613  GlobalUnlock(stream_hglobal);
2614  *dst_buffer = buffer;
2615  }
2617 
2618 cleanup_err:
2619  if (FAILED(hr) && hr != E_OUTOFMEMORY)
2621 
2622 cleanup:
2623  if (stream) IStream_Release(stream);
2624 
2625  if (frame) IWICBitmapFrameEncode_Release(frame);
2626  if (encoder_options) IPropertyBag2_Release(encoder_options);
2627 
2628  if (encoder) IWICBitmapEncoder_Release(encoder);
2629 
2630  return hr;
2631 }
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
#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
Definition: glext.h:3491
DWORD amask
Definition: surface.c:189
#define IDirect3DSurface9_Release(p)
Definition: d3d9.h:622
HRESULT save_dds_texture_to_memory(ID3DXBuffer **dst_buffer, IDirect3DBaseTexture9 *src_texture, const PALETTEENTRY *src_palette)
Definition: surface.c:672
void fetch_2d_texel_rgba_dxt5(GLint srcRowStride, const GLubyte *pixdata, GLint i, GLint j, GLvoid *texel)
UINT width
Definition: d3dx9_private.h:43
GLint level
Definition: gl.h:1546
GLint GLint GLsizei width
Definition: gl.h:1546
#define max(a, b)
Definition: svc.c:63
#define shift
Definition: input.c:1756
HRESULT WINAPI GetHGlobalFromStream(IStream *pstm, HGLOBAL *phglobal)
static const GUID * d3dformat_to_wic_guid(D3DFORMAT format)
Definition: surface.c:70
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
static unsigned int file_size
Definition: regtests2xml.c:47
#define DDS_CAPS
Definition: surface.c:84
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:1497
long y
Definition: polytest.cpp:48
rwlock_t lock
Definition: tcpcore.h:1163
DWORD miplevels
Definition: surface.c:143
static D3DFORMAT dds_bump_luminance_to_d3dformat(const struct dds_pixel_format *pixel_format)
Definition: surface.c:378
const char int int int static __inline const char * wine_dbgstr_a(const char *s)
Definition: debug.h:186
HRESULT hr
Definition: shlfolder.c:183
static const struct @236 wic_pixel_formats[]
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:2233
static const char * dst_format
Definition: dib.c:1133
long x
Definition: polytest.cpp:48
D3DFORMAT Format
Definition: d3d8types.h:1170
#define IDirect3DCubeTexture9_GetLevelCount(p)
Definition: d3d9.h:932
DWORD caps2
Definition: surface.c:147
#define TRUE
Definition: types.h:120
#define IDirect3DTexture9_GetSurfaceLevel(p, a, b)
Definition: d3d9.h:1033
char * wine_dbgstr_w(const wchar_t *wstr)
Definition: atltest.h:87
#define DDS_PF_FOURCC
Definition: surface.c:114
#define CP_ACP
Definition: compat.h:109
GLuint GLuint GLsizei count
Definition: gl.h:1545
#define WARN(fmt,...)
Definition: debug.h:112
#define IDirect3DVolumeTexture9_GetLevelCount(p)
Definition: d3d9.h:1122
HRSRC WINAPI FindResourceA(HMODULE hModule, LPCSTR name, LPCSTR type)
Definition: res.c:155
HRESULT WINAPI D3DXCreateBuffer(DWORD size, ID3DXBuffer **buffer)
Definition: core.c:131
#define D3DX_FILTER_NONE
Definition: d3dx9tex.h:27
DWORD caps4
Definition: surface.c:149
#define DDS_CAPS_TEXTURE
Definition: surface.c:95
#define DDS_CAPS2_VOLUME
Definition: surface.c:109
LONG top
Definition: windef.h:307
#define D3DERR_INVALIDCALL
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:1443
#define D3DX_FILTER_LINEAR
Definition: d3dx9tex.h:29
#define ZeroMemory
Definition: winbase.h:1664
GLuint buffer
Definition: glext.h:5915
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
#define IDirect3DSurface9_GetDevice(p, a)
Definition: d3d9.h:624
int This channels
Definition: rdpsnd_libao.c:37
HRESULT WINAPI CreateStreamOnHGlobal(HGLOBAL hGlobal, BOOL fDeleteOnRelease, LPSTREAM *ppstm)
static D3DFORMAT dds_alpha_to_d3dformat(const struct dds_pixel_format *pixel_format)
Definition: surface.c:348
DWORD flags
Definition: surface.c:138
const struct pixel_format_desc * srcformat
Definition: surface.c:1531
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:1416
#define IDirect3DDevice9_CreateRenderTarget(p, a, b, c, d, e, f, g, h)
Definition: d3d9.h:1535
#define IDirect3DTexture9_GetLevelCount(p)
Definition: d3d9.h:1027
LONG left
Definition: windef.h:306
D3DFORMAT format
Definition: surface.c:190
void(* to_rgba)(const struct vec4 *src, struct vec4 *dst, const PALETTEENTRY *palette)
Definition: d3dx9_private.h:68
enum _D3DXIMAGE_FILEFORMAT D3DXIMAGE_FILEFORMAT
#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
Definition: glext.h:3490
if(dx==0 &&dy==0)
Definition: linetemp.h:174
const char * filename
Definition: ioapi.h:135
LONG right
Definition: windef.h:308
#define E_FAIL
Definition: ddrawi.h:102
DWORD width
Definition: surface.c:140
D3DRESOURCETYPE ResourceType
Definition: d3dx9tex.h:83
#define DWORD
Definition: nt_native.h:44
#define DDS_PF_BUMPDUDV
Definition: surface.c:120
#define BI_BITFIELDS
Definition: mmreg.h:507
DWORD caps3
Definition: surface.c:148
& rect
Definition: startmenu.cpp:1413
HRSRC WINAPI FindResourceW(HINSTANCE hModule, LPCWSTR name, LPCWSTR type)
Definition: res.c:176
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl.h:1546
static void * heap_alloc(size_t len)
Definition: appwiz.h:65
static HRESULT get_surface(D3DRESOURCETYPE type, struct IDirect3DBaseTexture9 *tex, int face, UINT level, struct IDirect3DSurface9 **surf)
Definition: surface.c:657
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:1731
FxDevice * device
#define IDirect3DDevice9_CreateOffscreenPlainSurface(p, a, b, c, d, e, f)
Definition: d3d9.h:1543
#define write
Definition: acwin.h:97
UINT MipLevels
Definition: d3dx9tex.h:81
void tx_compress_dxtn(GLint srccomps, GLint width, GLint height, const GLubyte *srcPixData, GLenum destFormat, GLubyte *dest, GLint dstRowStride)
const GUID * guid
GLenum GLint GLuint mask
Definition: glext.h:6028
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define FALSE
Definition: types.h:117
UINT Back
Definition: d3d8types.h:1016
const GUID * wic_guid
Definition: surface.c:43
unsigned int BOOL
Definition: ntddk_ex.h:94
Definition: main.c:438
GLuint color
Definition: glext.h:6243
Definition: devices.h:37
DWORD height
Definition: surface.c:139
DWORD destshift[4]
Definition: surface.c:1533
static const WCHAR desc[]
Definition: protectdata.c:36
if SUCCEEDED(hr)
#define debugstr_w
Definition: kernel32.h:32
static D3DFORMAT dds_rgb_to_d3dformat(const struct dds_pixel_format *pixel_format)
Definition: surface.c:303
HRESULT load_resource_into_memory(HMODULE module, HRSRC resinfo, void **buffer, DWORD *length) DECLSPEC_HIDDEN
Definition: util.c:170
#define FIXME(fmt,...)
Definition: debug.h:111
#define D3DX_DEFAULT
Definition: d3dx9.h:24
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
#define DDS_PIXELFORMAT
Definition: surface.c:88
DWORD biCompression
Definition: amvideo.idl:35
static PVOID ptr
Definition: dispmode.c:27
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:1469
#define D3DX_FILTER_TRIANGLE
Definition: d3dx9tex.h:30
static const struct @237 rgb_pixel_formats[]
static BOOL is_conversion_from_supported(const struct pixel_format_desc *format)
Definition: d3dx9_private.h:79
GLdouble GLdouble z
Definition: glext.h:5874
DWORD size
Definition: surface.c:137
#define IDirect3DDevice9_Release(p)
Definition: d3d9.h:1508
UINT height
Definition: d3dx9_private.h:44
HRESULT write_buffer_to_file(const WCHAR *filename, ID3DXBuffer *buffer) DECLSPEC_HIDDEN
Definition: util.c:186
DWORD signature
Definition: surface.c:136
struct ID3DXBuffer ID3DXBuffer
Definition: d3dx8core.h:51
static SIZE_T datasize
Definition: asm.c:30
enum _D3DFORMAT D3DFORMAT
INT Height
Definition: wincodec.idl:301
#define debugstr_guid
Definition: kernel32.h:35
UINT Bottom
Definition: d3d8types.h:1014
BOOL process_channel[4]
Definition: surface.c:1535
static D3DFORMAT wic_guid_to_d3dformat(const GUID *guid)
Definition: surface.c:57
#define IDirect3DBaseTexture9_GetType(p)
Definition: d3d9.h:844
GLuint GLfloat * val
Definition: glext.h:7180
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
HRESULT WINAPI WICCreateImagingFactory_Proxy(UINT, IWICImagingFactory **)
Definition: proxy.c:651
DEFINE_GUID(GUID_WineContainerFormatTga, 0x0c44fda1, 0xa5c5, 0x4298, 0x96, 0x85, 0x47, 0x3f, 0xc1, 0x7c, 0xd3, 0x22)
GLfloat f
Definition: glext.h:7540
float float_16_to_32(const unsigned short in) DECLSPEC_HIDDEN
Definition: math.c:2203
D3DFORMAT d3dformat
Definition: surface.c:44
D3DXIMAGE_FILEFORMAT ImageFileFormat
Definition: d3dx9tex.h:84
#define TRACE(s)
Definition: solgame.cpp:4
UINT depth
Definition: d3dx9_private.h:45
GLsizeiptr size
Definition: glext.h:5919
static D3DFORMAT dds_fourcc_to_d3dformat(DWORD fourcc)
Definition: surface.c:153
#define GetProcessHeap()
Definition: compat.h:595
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
ULONG RGBQUAD
Definition: precomp.h:50
DWORD reserved2
Definition: surface.c:150
__wchar_t WCHAR
Definition: xmlstorage.h:180
D3DFORMAT Format
Definition: d3dx9tex.h:82
UINT Top
Definition: d3d8types.h:1012
#define DDS_CAPS2_CUBEMAP_ALL_FACES
Definition: surface.c:106
#define debugstr_a
Definition: kernel32.h:31
GLenum GLuint texture
Definition: glext.h:6295
LONG HRESULT
Definition: typedefs.h:79
GLintptr offset
Definition: glext.h:5920
#define DDS_PF_BUMPLUMINANCE
Definition: surface.c:119
UINT Left
Definition: d3d8types.h:1011
HRESULT load_texture_from_dds(IDirect3DTexture9 *texture, const void *src_data, const PALETTEENTRY *palette, DWORD filter, D3DCOLOR color_key, const D3DXIMAGE_INFO *src_info, unsigned int skip_levels, unsigned int *loaded_miplevels)
Definition: surface.c:737
DWORD reserved[11]
Definition: surface.c:144
#define WINAPI
Definition: msvc.h:6
static HRESULT calculate_dds_surface_size(D3DFORMAT format, UINT width, UINT height, UINT *pitch, UINT *size)
Definition: surface.c:452
const GLubyte * c
Definition: glext.h:8905
const char * wine_dbgstr_rect(const RECT *rect)
int strncmp(const char *String1, const char *String2, ACPI_SIZE Count)
Definition: utclib.c:534
#define CopyMemory
Definition: winbase.h:1662
enum format_type type
Definition: d3dx9_private.h:66
static FILE * out
Definition: regtests2xml.c:44
HRESULT WINAPI D3DXGetImageInfoFromFileA(const char *file, D3DXIMAGE_INFO *info)
Definition: surface.c:1135
unsigned long DWORD
Definition: ntddk_ex.h:95
WORD face[3]
Definition: mesh.c:4747
static BOOL convert_dib_to_bmp(const void **data, unsigned int *size)
Definition: surface.c:899
HRESULT lock_surface(IDirect3DSurface9 *surface, const RECT *surface_rect, D3DLOCKED_RECT *lock, IDirect3DSurface9 **temp_surface, BOOL write)
Definition: surface.c:209
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
#define RT_RCDATA
Definition: pedump.c:372
float w
Definition: d3dx9_private.h:38
HRESULT map_view_of_file(const WCHAR *filename, void **buffer, DWORD *length) DECLSPEC_HIDDEN
Definition: util.c:120
HRESULT WINAPI D3DXGetImageInfoFromFileW(const WCHAR *file, D3DXIMAGE_INFO *info)
Definition: surface.c:1155
GLint GLint GLsizei GLsizei GLsizei depth
Definition: gl.h:1546
HRESULT WINAPI D3DXSaveSurfaceToFileInMemory(ID3DXBuffer **dst_buffer, D3DXIMAGE_FILEFORMAT file_format, IDirect3DSurface9 *src_surface, const PALETTEENTRY *src_palette, const RECT *src_rect)
Definition: surface.c:2414
LPVOID NTAPI GlobalLock(HGLOBAL hMem)
Definition: heapmem.c:755
Definition: parse.h:22
GLuint GLuint stream
Definition: glext.h:7522
#define IDirect3DCubeTexture9_GetCubeMapSurface(p, a, b, c)
Definition: d3d9.h:938
#define IDirect3DVolume9_Release(p)
Definition: d3d9.h:383
HRESULT load_volume_texture_from_dds(IDirect3DVolumeTexture9 *volume_texture, const void *src_data, const PALETTEENTRY *palette, DWORD filter, DWORD color_key, const D3DXIMAGE_INFO *src_info)
Definition: surface.c:847
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum GLsizei len
Definition: glext.h:6722
DWORD pitch_or_linear_size
Definition: surface.c:141
GLdouble s
Definition: gl.h:2039
GLenum src
Definition: glext.h:6340
unsigned int GLenum
Definition: gl.h:150
static UINT calculate_dds_file_size(D3DFORMAT format, UINT width, UINT height, UINT depth, UINT miplevels, UINT faces)
Definition: surface.c:475
#define IDirect3DSurface9_GetDesc(p, a)
Definition: d3d9.h:634
unsigned char BYTE
Definition: xxhash.c:193
static HPALETTE palette
Definition: clipboard.c:1345
GLint GLint GLsizei GLsizei height
Definition: gl.h:1546
#define DDS_PF_LUMINANCE
Definition: surface.c:118
#define ERR(fmt,...)
Definition: debug.h:110
static D3DFORMAT dds_luminance_to_d3dformat(const struct dds_pixel_format *pixel_format)
Definition: surface.c:326
static void format_from_vec4(const struct pixel_format_desc *format, const struct vec4 *src, BYTE *dst)
Definition: surface.c:1650
WINE_DEFAULT_DEBUG_CHANNEL(d3d8)
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:1539
BOOL WINAPI SetRect(_Out_ LPRECT, _In_ int, _In_ int, _In_ int, _In_ int)
#define D3D_OK
Definition: d3d.h:106
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:1963
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:2364
#define D3DX_FILTER_DITHER
Definition: d3dx9tex.h:36
const GLdouble * v
Definition: gl.h:2040
GLuint in
Definition: glext.h:9616
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
#define IDirect3DDevice9_UpdateSurface(p, a, b, c, d)
Definition: d3d9.h:1537
#define DDS_PF_RGB
Definition: surface.c:116
static float(__cdecl *square_half_float)(float x
#define byte(x, n)
Definition: tomcrypt.h:118
HRESULT WINAPI D3DXLoadVolumeFromMemory(IDirect3DVolume9 *dst_volume, const PALETTEENTRY *dst_palette, const D3DBOX *dst_box, const void *src_memory, D3DFORMAT src_format, UINT src_row_pitch, UINT src_slice_pitch, const PALETTEENTRY *src_palette, const D3DBOX *src_box, DWORD filter, D3DCOLOR color_key)
Definition: volume.c:87
#define ARRAY_SIZE(a)
Definition: main.h:24
#define ID3DXBuffer_Release(p)
Definition: d3dx9core.h:83
UINT Front
Definition: d3d8types.h:1015
struct tagBITMAPFILEHEADER BITMAPFILEHEADER
#define DDS_WIDTH
Definition: surface.c:86
#define E_NOTIMPL
Definition: ddrawi.h:99
GLint GLint GLsizei GLsizei GLsizei GLint GLenum GLenum const GLvoid * pixels
Definition: gl.h:1546
GLenum GLenum dst
Definition: glext.h:6340
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
static D3DFORMAT dds_indexed_to_d3dformat(const struct dds_pixel_format *pixel_format)
Definition: surface.c:357
#define DDS_PF_ALPHA
Definition: surface.c:112
#define min(a, b)
Definition: monoChain.cc:55
void fetch_2d_texel_rgba_dxt1(GLint srcRowStride, const GLubyte *pixdata, GLint i, GLint j, GLvoid *texel)
unsigned int UINT
Definition: ndis.h:50
#define NULL
Definition: types.h:112
BOOL WINAPI IsEqualGUID(REFGUID rguid1, REFGUID rguid2)
Definition: compobj.c:4112
BOOL NTAPI GlobalUnlock(HGLOBAL hMem)
Definition: heapmem.c:1190
struct dds_pixel_format pixel_format
Definition: surface.c:145
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
static const BYTE dib[]
Definition: ole2.c:201
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
static HRESULT load_surface_from_dds(IDirect3DSurface9 *dst_surface, const PALETTEENTRY *dst_palette, const RECT *dst_rect, const void *src_data, const RECT *src_rect, DWORD filter, D3DCOLOR color_key, const D3DXIMAGE_INFO *src_info)
Definition: surface.c:568
HRESULT unlock_surface(IDirect3DSurface9 *surface, const RECT *surface_rect, IDirect3DSurface9 *temp_surface, BOOL update)
Definition: surface.c:267
static BOOL is_conversion_to_supported(const struct pixel_format_desc *format)
Definition: d3dx9_private.h:87
#define MultiByteToWideChar
Definition: compat.h:110
HRESULT WINAPI D3DXGetImageInfoFromResourceA(HMODULE module, const char *resource, D3DXIMAGE_INFO *info)
Definition: surface.c:1184
static D3DFORMAT dds_pixel_format_to_d3dformat(const struct dds_pixel_format *pixel_format)
Definition: surface.c:389
static HRESULT get_image_info_from_dds(const void *buffer, UINT length, D3DXIMAGE_INFO *info)
Definition: surface.c:512
#define IDirect3DSurface9_UnlockRect(p)
Definition: d3d9.h:636
static unsigned short float_32_to_16(const float *in)
Definition: surface.c:1062
enum _D3DTEXTUREFILTERTYPE D3DTEXTUREFILTERTYPE
#define DDS_CAPS2_CUBEMAP_NEGATIVEZ
Definition: surface.c:105
INT Width
Definition: wincodec.idl:300
#define IDirect3DVolumeTexture9_GetVolumeLevel(p, a, b)
Definition: d3d9.h:1128
static D3DFORMAT dds_bump_to_d3dformat(const struct dds_pixel_format *pixel_format)
Definition: surface.c:366
UINT Right
Definition: d3d8types.h:1013
#define c
Definition: ke_i.h:80
#define DDS_HEIGHT
Definition: surface.c:85
unsigned int ULONG
Definition: retypes.h:1
#define D3DX_FILTER_POINT
Definition: d3dx9tex.h:28
static ClassFactoryImpl factory
Definition: ole_server.c:234
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:1839
HRESULT WINAPI D3DXGetImageInfoFromFileInMemory(const void *data, UINT datasize, D3DXIMAGE_INFO *info)
Definition: surface.c:985
LONG bottom
Definition: windef.h:309
static void get_relevant_argb_components(const struct argb_conversion_info *info, const BYTE *col, DWORD *out)
Definition: surface.c:1572
char * cleanup(char *str)
Definition: wpickclick.c:99
DWORD depth
Definition: surface.c:142
const struct pixel_format_desc * get_format_info(D3DFORMAT format) DECLSPEC_HIDDEN
Definition: util.c:217
DWORD bpp
Definition: surface.c:185
#define DDS_CAPS2_CUBEMAP
Definition: surface.c:99
HRESULT load_cube_texture_from_dds(IDirect3DCubeTexture9 *cube_texture, const void *src_data, const PALETTEENTRY *palette, DWORD filter, DWORD color_key, const D3DXIMAGE_INFO *src_info)
Definition: surface.c:794
static HRESULT d3dformat_to_dds_pixel_format(struct dds_pixel_format *pixel_format, D3DFORMAT d3dformat)
Definition: surface.c:417
const struct pixel_format_desc * destformat
Definition: surface.c:1532
static void format_to_vec4(const struct pixel_format_desc *format, const BYTE *src, struct vec4 *dst)
Definition: surface.c:1620
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
#define IDirect3DSurface9_LockRect(p, a, b, c)
Definition: d3d9.h:635
#define DDS_CAPS2_CUBEMAP_POSITIVEX
Definition: surface.c:100
#define RT_BITMAP
Definition: pedump.c:364
static HRESULT save_dds_surface_to_memory(ID3DXBuffer **dst_buffer, IDirect3DSurface9 *src_surface, const RECT *src_rect)
Definition: surface.c:587
DWORD caps
Definition: surface.c:146
#define UnmapViewOfFile
Definition: compat.h:605
#define D3DLOCK_READONLY
Definition: d3d8types.h:69
static const char stream_data[]
Definition: mlang.c:2327
#define memset(x, y, z)
Definition: compat.h:39
#define MAKEFOURCC(ch0, ch1, ch2, ch3)
Definition: dmdls.h:24
HRESULT WINAPI D3DXGetImageInfoFromResourceW(HMODULE module, const WCHAR *resource, D3DXIMAGE_INFO *info)
Definition: surface.c:1203
UINT32 WICColor
Definition: wincodec.idl:312
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:2393
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:1700
static const unsigned char pixdata[]
Definition: surface.c:101
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
Definition: glext.h:7005
#define IDirect3DDevice9_StretchRect(p, a, b, c, d, e)
Definition: d3d9.h:1541
#define HeapFree(x, y, z)
Definition: compat.h:594
static DWORD make_argb_color(const struct argb_conversion_info *info, const DWORD *in)
Definition: surface.c:1602
struct CFHEADER header
Definition: fdi.c:101
#define ID3DXBuffer_GetBufferPointer(p)
Definition: d3dx9core.h:85
enum _D3DRESOURCETYPE D3DRESOURCETYPE
GLenum GLuint GLint GLenum face
Definition: glext.h:7025
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:1245
#define DDS_PF_ALPHA_ONLY
Definition: surface.c:113
#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
Definition: glext.h:3492
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
static BOOL heap_free(void *mem)
Definition: appwiz.h:75
#define DDS_PF_INDEXED
Definition: surface.c:115
Definition: fci.c:126
HRESULT load_volume_from_dds(IDirect3DVolume9 *dst_volume, const PALETTEENTRY *dst_palette, const D3DBOX *dst_box, const void *src_data, const D3DBOX *src_box, DWORD filter, D3DCOLOR color_key, const D3DXIMAGE_INFO *src_info)
Definition: surface.c:719
void fetch_2d_texel_rgba_dxt3(GLint srcRowStride, const GLubyte *pixdata, GLint i, GLint j, GLvoid *texel)