xref: /reactos/dll/directx/wine/d3drm/texture.c (revision 7eead935)
1 /*
2  * Implementation of IDirect3DRMTextureX interfaces
3  *
4  * Copyright 2012 Christian Costa
5  * Copyright 2016 Aaryaman Vasishta
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21 
22 #include "config.h"
23 #include "wine/port.h"
24 
25 #include "d3drm_private.h"
26 
27 WINE_DEFAULT_DEBUG_CHANNEL(d3drm);
28 
29 static inline struct d3drm_texture *impl_from_IDirect3DRMTexture(IDirect3DRMTexture *iface)
30 {
31     return CONTAINING_RECORD(iface, struct d3drm_texture, IDirect3DRMTexture_iface);
32 }
33 
34 static inline struct d3drm_texture *impl_from_IDirect3DRMTexture2(IDirect3DRMTexture2 *iface)
35 {
36     return CONTAINING_RECORD(iface, struct d3drm_texture, IDirect3DRMTexture2_iface);
37 }
38 
39 static inline struct d3drm_texture *impl_from_IDirect3DRMTexture3(IDirect3DRMTexture3 *iface)
40 {
41     return CONTAINING_RECORD(iface, struct d3drm_texture, IDirect3DRMTexture3_iface);
42 }
43 
44 static void d3drm_texture_destroy(struct d3drm_texture *texture)
45 {
46     TRACE("texture %p is being destroyed.\n", texture);
47 
48     d3drm_object_cleanup((IDirect3DRMObject*)&texture->IDirect3DRMTexture_iface, &texture->obj);
49     if (texture->image || texture->surface)
50         IDirect3DRM_Release(texture->d3drm);
51     if (texture->surface)
52         IDirectDrawSurface_Release(texture->surface);
53     heap_free(texture);
54 }
55 
56 static BOOL d3drm_validate_image(D3DRMIMAGE *image)
57 {
58     if (!image
59             || !image->red_mask
60             || !image->green_mask
61             || !image->blue_mask
62             || !image->buffer1
63             || !(image->rgb || (image->palette && image->palette_size)))
64     {
65         return FALSE;
66     }
67 
68     return TRUE;
69 }
70 
71 static BOOL d3drm_image_palettise(D3DRMIMAGE *image, unsigned char *src_data,
72         SIZE_T w, SIZE_T h, BOOL flip)
73 {
74     unsigned char *dst_data, *src_ptr, *dst_ptr;
75     SIZE_T src_pitch, dst_pitch, i, x, y;
76     D3DRMPALETTEENTRY *palette, *entry;
77     unsigned int colour_count = 0;
78 
79     if (w > (~(SIZE_T)0 - 3) / h)
80         return FALSE;
81 
82     src_pitch = flip ? -w * 3 : w * 3;
83     dst_pitch = (w + 3) & ~3;
84 
85     if (!(dst_data = heap_alloc(dst_pitch * h)))
86     {
87         WARN("Failed to allocate image buffer.\n");
88         return FALSE;
89     }
90     memset(dst_data, 0xff, dst_pitch * h);
91 
92     if (!(palette = heap_alloc(256 * sizeof(*palette))))
93     {
94         WARN("Failed to allocate palette.\n");
95         heap_free(dst_data);
96         return FALSE;
97     }
98 
99     src_ptr = flip ? &src_data[(h - 1) * w * 3] : src_data;
100     dst_ptr = dst_data;
101 
102     for (y = 0; y < h; ++y)
103     {
104         for (x = 0; x < w; ++x)
105         {
106             for (i = 0; i < colour_count; ++i)
107             {
108                 entry = &palette[i];
109                 if (entry->red == src_ptr[x * 3 + 0]
110                         && entry->green == src_ptr[x * 3 + 1]
111                         && entry->blue == src_ptr[x * 3 + 2])
112                     break;
113             }
114 
115             if (i == colour_count)
116             {
117                 if (colour_count == 256)
118                 {
119                     heap_free(dst_data);
120                     heap_free(palette);
121                     return FALSE;
122                 }
123 
124                 entry = &palette[colour_count++];
125                 entry->red = src_ptr[x * 3 + 0];
126                 entry->green = src_ptr[x * 3 + 1];
127                 entry->blue = src_ptr[x * 3 + 2];
128                 entry->flags = D3DRMPALETTE_READONLY;
129             }
130 
131             dst_ptr[x] = i;
132         }
133 
134         src_ptr += src_pitch;
135         dst_ptr += dst_pitch;
136     }
137 
138     image->depth = 8;
139     image->rgb = 0;
140     image->bytes_per_line = dst_pitch;
141     image->buffer1 = dst_data;
142     image->red_mask = 0xff;
143     image->green_mask = 0xff;
144     image->blue_mask = 0xff;
145     image->palette_size = colour_count;
146     if (!(image->palette = heap_realloc(palette, colour_count * sizeof(*palette))))
147         image->palette = palette;
148 
149     return TRUE;
150 }
151 
152 static HRESULT d3drm_image_load_32(D3DRMIMAGE *image, unsigned char *src_data,
153         LONGLONG src_data_size, SIZE_T w, SIZE_T h, BOOL flip)
154 {
155     unsigned char *dst_data, *src_ptr, *dst_ptr;
156     SIZE_T src_pitch, dst_pitch, x, y;
157 
158     if (d3drm_image_palettise(image, src_data, w, h, flip))
159         return D3DRM_OK;
160 
161     if (w > (~(SIZE_T)0 / 4) / h)
162         return D3DRMERR_BADALLOC;
163 
164     src_pitch = flip ? -w * 3 : w * 3;
165     dst_pitch = w * 4;
166 
167     if (!(dst_data = heap_alloc(dst_pitch * h)))
168     {
169         WARN("Failed to allocate image buffer.\n");
170         return D3DRMERR_BADALLOC;
171     }
172 
173     src_ptr = flip ? &src_data[(h - 1) * w * 3] : src_data;
174     dst_ptr = dst_data;
175 
176     for (y = 0; y < h; ++y)
177     {
178         for (x = 0; x < w; ++x)
179         {
180             dst_ptr[x * 4 + 0] = src_ptr[x * 3 + 0];
181             dst_ptr[x * 4 + 1] = src_ptr[x * 3 + 1];
182             dst_ptr[x * 4 + 2] = src_ptr[x * 3 + 2];
183             dst_ptr[x * 4 + 3] = 0xff;
184         }
185 
186         src_ptr += src_pitch;
187         dst_ptr += dst_pitch;
188     }
189 
190     image->depth = 32;
191     image->rgb = 1;
192     image->bytes_per_line = dst_pitch;
193     image->buffer1 = dst_data;
194     image->red_mask = 0xff0000;
195     image->green_mask = 0x00ff00;
196     image->blue_mask = 0x0000ff;
197     image->palette_size = 0;
198     image->palette = NULL;
199 
200     return D3DRM_OK;
201 }
202 
203 static HRESULT d3drm_image_load_8(D3DRMIMAGE *image, const RGBQUAD *palette,
204         unsigned char *src_data, LONGLONG src_data_size, SIZE_T w, SIZE_T h, BOOL flip)
205 {
206     unsigned char *dst_data;
207     SIZE_T i;
208 
209     if (w > ~(SIZE_T)0 / h)
210         return D3DRMERR_BADALLOC;
211 
212     if (!(dst_data = heap_alloc(w * h)))
213     {
214         WARN("Failed to allocate image buffer.\n");
215         return D3DRMERR_BADALLOC;
216     }
217 
218     if (!(image->palette = heap_alloc(256 * sizeof(*image->palette))))
219     {
220         WARN("Failed to allocate palette.\n");
221         heap_free(dst_data);
222         return D3DRMERR_BADALLOC;
223     }
224 
225     memcpy(image->palette, palette, 256 * sizeof(*image->palette));
226     for (i = 0; i < 256; ++i)
227     {
228         image->palette[i].flags = D3DRMPALETTE_READONLY;
229     }
230 
231     if (flip)
232     {
233         for (i = 0; i < h; ++i)
234         {
235             memcpy(&dst_data[i * w], &src_data[(h - 1 - i) * w], w);
236         }
237     }
238     else
239     {
240         memcpy(dst_data, src_data, w * h);
241     }
242 
243     image->depth = 8;
244     image->rgb = 0;
245     image->bytes_per_line = w;
246     image->buffer1 = dst_data;
247     image->red_mask = 0xff;
248     image->green_mask = 0xff;
249     image->blue_mask = 0xff;
250     image->palette_size = 256;
251 
252     return D3DRM_OK;
253 }
254 
255 static void CDECL destroy_image_callback(IDirect3DRMObject *obj, void *arg)
256 {
257     D3DRMIMAGE *image = arg;
258 
259     TRACE("texture object %p, image %p.\n", obj, image);
260 
261     heap_free(image->buffer1);
262     heap_free(image);
263 }
264 
265 static HRESULT d3drm_texture_load(struct d3drm_texture *texture,
266         const char *path, BOOL flip, D3DRMIMAGE **image_out)
267 {
268     BITMAPFILEHEADER *header;
269     unsigned int w, h, bpp;
270     HANDLE file, mapping;
271     LARGE_INTEGER size;
272     D3DRMIMAGE *image;
273     BITMAPINFO *info;
274     LONGLONG rem;
275     HRESULT hr;
276 
277     if ((file = CreateFileA(path, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
278         return D3DRMERR_BADOBJECT;
279 
280     mapping = CreateFileMappingW(file, NULL, PAGE_READONLY, 0, 0, NULL);
281     CloseHandle(file);
282     if (!mapping || mapping == INVALID_HANDLE_VALUE)
283         return D3DRMERR_BADVALUE;
284 
285     if (!GetFileSizeEx(mapping, &size))
286     {
287         CloseHandle(mapping);
288         return D3DRMERR_BADVALUE;
289     }
290     rem = size.QuadPart;
291 
292     header = MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0);
293     CloseHandle(mapping);
294     if (!header)
295         return D3DRMERR_BADVALUE;
296 
297     hr = D3DRMERR_BADALLOC;
298     if (!(image = heap_alloc_zero(sizeof(*image))))
299         goto fail;
300 
301     hr = D3DRMERR_BADFILE;
302     if (rem < sizeof(*header) || header->bfType != 0x4d42 /* BM */)
303         goto fail;
304     rem -= sizeof(*header);
305 
306     info = (BITMAPINFO *)&header[1];
307     /* Only allow version 1 DIB's (BITMAPINFOHEADER) to be loaded. */
308     if (rem < sizeof(info->bmiHeader) || info->bmiHeader.biSize != sizeof(info->bmiHeader))
309         goto fail;
310     rem -= sizeof(info->bmiHeader);
311 
312     w = info->bmiHeader.biWidth;
313     h = abs(info->bmiHeader.biHeight);
314     bpp = info->bmiHeader.biBitCount == 24 ? 32 : info->bmiHeader.biBitCount;
315     if (bpp != 8 && bpp != 32)
316         goto fail;
317 
318     image->width = w;
319     image->height = h;
320     image->aspectx = 1;
321     image->aspecty = 1;
322     if (bpp == 8)
323     {
324         rem -= 256 * sizeof(*info->bmiColors);
325         if (w > rem / h)
326             goto fail;
327         hr = d3drm_image_load_8(image, info->bmiColors, (unsigned char *)&info->bmiColors[256], rem, w, h, flip);
328     }
329     else
330     {
331         if (w > (rem / 3) / h)
332             goto fail;
333         hr = d3drm_image_load_32(image, (unsigned char *)&info->bmiColors, rem, w, h, flip);
334     }
335     if (FAILED(hr))
336         goto fail;
337 
338     /* Use an internal destroy callback to destroy the image struct. */
339     hr = IDirect3DRMObject_AddDestroyCallback(&texture->IDirect3DRMTexture3_iface, destroy_image_callback, image);
340 
341     *image_out = image;
342 
343     UnmapViewOfFile(header);
344 
345     return hr;
346 
347 fail:
348     heap_free(image);
349     UnmapViewOfFile(header);
350 
351     return hr;
352 }
353 
354 static HRESULT WINAPI d3drm_texture1_QueryInterface(IDirect3DRMTexture *iface, REFIID riid, void **out)
355 {
356     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture(iface);
357 
358     TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
359 
360     return IDirect3DRMTexture3_QueryInterface(&texture->IDirect3DRMTexture3_iface, riid, out);
361 }
362 
363 static ULONG WINAPI d3drm_texture1_AddRef(IDirect3DRMTexture *iface)
364 {
365     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture(iface);
366 
367     TRACE("iface %p.\n", iface);
368 
369     return IDirect3DRMTexture3_AddRef(&texture->IDirect3DRMTexture3_iface);
370 }
371 
372 static ULONG WINAPI d3drm_texture1_Release(IDirect3DRMTexture *iface)
373 {
374     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture(iface);
375 
376     TRACE("iface %p.\n", iface);
377 
378     return IDirect3DRMTexture3_Release(&texture->IDirect3DRMTexture3_iface);
379 }
380 
381 static HRESULT WINAPI d3drm_texture1_Clone(IDirect3DRMTexture *iface,
382         IUnknown *outer, REFIID iid, void **out)
383 {
384     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture(iface);
385 
386     TRACE("iface %p, outer %p, iid %s, out %p.\n", iface, outer, debugstr_guid(iid), out);
387 
388     return IDirect3DRMTexture3_Clone(&texture->IDirect3DRMTexture3_iface, outer, iid, out);
389 }
390 
391 static HRESULT WINAPI d3drm_texture1_AddDestroyCallback(IDirect3DRMTexture *iface,
392         D3DRMOBJECTCALLBACK cb, void *ctx)
393 {
394     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture(iface);
395 
396     TRACE("iface %p, cb %p, ctx %p\n", iface, cb, ctx);
397 
398     return IDirect3DRMTexture3_AddDestroyCallback(&texture->IDirect3DRMTexture3_iface, cb, ctx);
399 }
400 
401 static HRESULT WINAPI d3drm_texture1_DeleteDestroyCallback(IDirect3DRMTexture *iface,
402         D3DRMOBJECTCALLBACK cb, void *ctx)
403 {
404     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture(iface);
405 
406     TRACE("iface %p, cb %p, ctx %p\n", iface, cb, ctx);
407 
408     return IDirect3DRMTexture3_DeleteDestroyCallback(&texture->IDirect3DRMTexture3_iface, cb, ctx);
409 }
410 
411 static HRESULT WINAPI d3drm_texture1_SetAppData(IDirect3DRMTexture *iface, DWORD data)
412 {
413     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture(iface);
414 
415     TRACE("iface %p, data %#x.\n", iface, data);
416 
417     return IDirect3DRMTexture3_SetAppData(&texture->IDirect3DRMTexture3_iface, data);
418 }
419 
420 static DWORD WINAPI d3drm_texture1_GetAppData(IDirect3DRMTexture *iface)
421 {
422     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture(iface);
423 
424     TRACE("iface %p.\n", iface);
425 
426     return IDirect3DRMTexture3_GetAppData(&texture->IDirect3DRMTexture3_iface);
427 }
428 
429 static HRESULT WINAPI d3drm_texture1_SetName(IDirect3DRMTexture *iface, const char *name)
430 {
431     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture(iface);
432 
433     TRACE("iface %p, name %s.\n", iface, debugstr_a(name));
434 
435     return IDirect3DRMTexture3_SetName(&texture->IDirect3DRMTexture3_iface, name);
436 }
437 
438 static HRESULT WINAPI d3drm_texture1_GetName(IDirect3DRMTexture *iface, DWORD *size, char *name)
439 {
440     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture(iface);
441 
442     TRACE("iface %p, size %p, name %p.\n", iface, size, name);
443 
444     return IDirect3DRMTexture3_GetName(&texture->IDirect3DRMTexture3_iface, size, name);
445 }
446 
447 static HRESULT WINAPI d3drm_texture1_GetClassName(IDirect3DRMTexture *iface, DWORD *size, char *name)
448 {
449     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture(iface);
450 
451     TRACE("iface %p, size %p, name %p.\n", iface, size, name);
452 
453     return IDirect3DRMTexture3_GetClassName(&texture->IDirect3DRMTexture3_iface, size, name);
454 }
455 
456 static HRESULT WINAPI d3drm_texture1_InitFromFile(IDirect3DRMTexture *iface, const char *filename)
457 {
458     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture(iface);
459     D3DRMIMAGE *image;
460     HRESULT hr;
461 
462     TRACE("iface %p, filename %s.\n", iface, debugstr_a(filename));
463 
464     if (FAILED(hr = d3drm_texture_load(texture, filename, FALSE, &image)))
465         return hr;
466 
467     return IDirect3DRMTexture3_InitFromImage(&texture->IDirect3DRMTexture3_iface, image);
468 }
469 
470 static HRESULT WINAPI d3drm_texture1_InitFromSurface(IDirect3DRMTexture *iface,
471         IDirectDrawSurface *surface)
472 {
473     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture(iface);
474 
475     TRACE("iface %p, surface %p.\n", iface, surface);
476 
477     return IDirect3DRMTexture3_InitFromSurface(&texture->IDirect3DRMTexture3_iface, surface);
478 }
479 
480 static HRESULT WINAPI d3drm_texture1_InitFromResource(IDirect3DRMTexture *iface, HRSRC resource)
481 {
482     FIXME("iface %p, resource %p stub!\n", iface, resource);
483 
484     return E_NOTIMPL;
485 }
486 
487 static HRESULT WINAPI d3drm_texture1_Changed(IDirect3DRMTexture *iface, BOOL pixels, BOOL palette)
488 {
489     FIXME("iface %p, pixels %#x, palette %#x stub!\n", iface, pixels, palette);
490 
491     return E_NOTIMPL;
492 }
493 
494 static HRESULT WINAPI d3drm_texture1_SetColors(IDirect3DRMTexture *iface, DWORD max_colors)
495 {
496     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture(iface);
497 
498     TRACE("iface %p, max_colors %u.\n", iface, max_colors);
499 
500     return IDirect3DRMTexture3_SetColors(&texture->IDirect3DRMTexture3_iface, max_colors);
501 }
502 
503 static HRESULT WINAPI d3drm_texture1_SetShades(IDirect3DRMTexture *iface, DWORD max_shades)
504 {
505     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture(iface);
506 
507     TRACE("iface %p, max_shades %u.\n", iface, max_shades);
508 
509     return IDirect3DRMTexture3_SetShades(&texture->IDirect3DRMTexture3_iface, max_shades);
510 }
511 
512 static HRESULT WINAPI d3drm_texture1_SetDecalSize(IDirect3DRMTexture *iface, D3DVALUE width, D3DVALUE height)
513 {
514     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture(iface);
515 
516     TRACE("iface %p, width %.8e, height %.8e.\n", iface, width, height);
517 
518     return IDirect3DRMTexture3_SetDecalSize(&texture->IDirect3DRMTexture3_iface, width, height);
519 }
520 
521 static HRESULT WINAPI d3drm_texture1_SetDecalOrigin(IDirect3DRMTexture *iface, LONG x, LONG y)
522 {
523     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture(iface);
524 
525     TRACE("iface %p, x %d, y %d.\n", iface, x, y);
526 
527     return IDirect3DRMTexture3_SetDecalOrigin(&texture->IDirect3DRMTexture3_iface, x, y);
528 }
529 
530 static HRESULT WINAPI d3drm_texture1_SetDecalScale(IDirect3DRMTexture *iface, DWORD scale)
531 {
532     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture(iface);
533 
534     TRACE("iface %p, scale %u.\n", iface, scale);
535 
536     return IDirect3DRMTexture3_SetDecalScale(&texture->IDirect3DRMTexture3_iface, scale);
537 }
538 
539 static HRESULT WINAPI d3drm_texture1_SetDecalTransparency(IDirect3DRMTexture *iface, BOOL transparency)
540 {
541     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture(iface);
542 
543     TRACE("iface %p, transparency %#x.\n", iface, transparency);
544 
545     return IDirect3DRMTexture3_SetDecalTransparency(&texture->IDirect3DRMTexture3_iface, transparency);
546 }
547 
548 static HRESULT WINAPI d3drm_texture1_SetDecalTransparentColor(IDirect3DRMTexture *iface, D3DCOLOR color)
549 {
550     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture(iface);
551 
552     TRACE("iface %p, color 0x%08x.\n", iface, color);
553 
554     return IDirect3DRMTexture3_SetDecalTransparentColor(&texture->IDirect3DRMTexture3_iface, color);
555 }
556 
557 static HRESULT WINAPI d3drm_texture1_GetDecalSize(IDirect3DRMTexture *iface, D3DVALUE *width, D3DVALUE *height)
558 {
559     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture(iface);
560 
561     TRACE("iface %p, width %p, height %p.\n", iface, width, height);
562 
563     return IDirect3DRMTexture3_GetDecalSize(&texture->IDirect3DRMTexture3_iface, width, height);
564 }
565 
566 static HRESULT WINAPI d3drm_texture1_GetDecalOrigin(IDirect3DRMTexture *iface, LONG *x, LONG *y)
567 {
568     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture(iface);
569 
570     TRACE("iface %p, x %p, y %p.\n", iface, x, y);
571 
572     return IDirect3DRMTexture3_GetDecalOrigin(&texture->IDirect3DRMTexture3_iface, x, y);
573 }
574 
575 static D3DRMIMAGE * WINAPI d3drm_texture1_GetImage(IDirect3DRMTexture *iface)
576 {
577     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture(iface);
578 
579     TRACE("iface %p.\n", iface);
580 
581     return IDirect3DRMTexture3_GetImage(&texture->IDirect3DRMTexture3_iface);
582 }
583 
584 static DWORD WINAPI d3drm_texture1_GetShades(IDirect3DRMTexture *iface)
585 {
586     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture(iface);
587 
588     TRACE("iface %p.\n", iface);
589 
590     return IDirect3DRMTexture3_GetShades(&texture->IDirect3DRMTexture3_iface);
591 }
592 
593 static DWORD WINAPI d3drm_texture1_GetColors(IDirect3DRMTexture *iface)
594 {
595     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture(iface);
596 
597     TRACE("iface %p.\n", iface);
598 
599     return IDirect3DRMTexture3_GetColors(&texture->IDirect3DRMTexture3_iface);
600 }
601 
602 static DWORD WINAPI d3drm_texture1_GetDecalScale(IDirect3DRMTexture *iface)
603 {
604     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture(iface);
605 
606     TRACE("iface %p.\n", iface);
607 
608     return IDirect3DRMTexture3_GetDecalScale(&texture->IDirect3DRMTexture3_iface);
609 }
610 
611 static BOOL WINAPI d3drm_texture1_GetDecalTransparency(IDirect3DRMTexture *iface)
612 {
613     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture(iface);
614 
615     TRACE("iface %p.\n", iface);
616 
617     return IDirect3DRMTexture3_GetDecalTransparency(&texture->IDirect3DRMTexture3_iface);
618 }
619 
620 static D3DCOLOR WINAPI d3drm_texture1_GetDecalTransparentColor(IDirect3DRMTexture *iface)
621 {
622     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture(iface);
623 
624     TRACE("iface %p.\n", iface);
625 
626     return IDirect3DRMTexture3_GetDecalTransparentColor(&texture->IDirect3DRMTexture3_iface);
627 }
628 
629 static const struct IDirect3DRMTextureVtbl d3drm_texture1_vtbl =
630 {
631     d3drm_texture1_QueryInterface,
632     d3drm_texture1_AddRef,
633     d3drm_texture1_Release,
634     d3drm_texture1_Clone,
635     d3drm_texture1_AddDestroyCallback,
636     d3drm_texture1_DeleteDestroyCallback,
637     d3drm_texture1_SetAppData,
638     d3drm_texture1_GetAppData,
639     d3drm_texture1_SetName,
640     d3drm_texture1_GetName,
641     d3drm_texture1_GetClassName,
642     d3drm_texture1_InitFromFile,
643     d3drm_texture1_InitFromSurface,
644     d3drm_texture1_InitFromResource,
645     d3drm_texture1_Changed,
646     d3drm_texture1_SetColors,
647     d3drm_texture1_SetShades,
648     d3drm_texture1_SetDecalSize,
649     d3drm_texture1_SetDecalOrigin,
650     d3drm_texture1_SetDecalScale,
651     d3drm_texture1_SetDecalTransparency,
652     d3drm_texture1_SetDecalTransparentColor,
653     d3drm_texture1_GetDecalSize,
654     d3drm_texture1_GetDecalOrigin,
655     d3drm_texture1_GetImage,
656     d3drm_texture1_GetShades,
657     d3drm_texture1_GetColors,
658     d3drm_texture1_GetDecalScale,
659     d3drm_texture1_GetDecalTransparency,
660     d3drm_texture1_GetDecalTransparentColor,
661 };
662 
663 static HRESULT WINAPI d3drm_texture2_QueryInterface(IDirect3DRMTexture2 *iface, REFIID riid, void **out)
664 {
665     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture2(iface);
666 
667     TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
668 
669     return IDirect3DRMTexture3_QueryInterface(&texture->IDirect3DRMTexture3_iface, riid, out);
670 }
671 
672 static ULONG WINAPI d3drm_texture2_AddRef(IDirect3DRMTexture2 *iface)
673 {
674     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture2(iface);
675 
676     TRACE("iface %p.\n", iface);
677 
678     return IDirect3DRMTexture3_AddRef(&texture->IDirect3DRMTexture3_iface);
679 }
680 
681 static ULONG WINAPI d3drm_texture2_Release(IDirect3DRMTexture2 *iface)
682 {
683     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture2(iface);
684 
685     TRACE("iface %p.\n", iface);
686 
687     return IDirect3DRMTexture3_Release(&texture->IDirect3DRMTexture3_iface);
688 }
689 
690 static HRESULT WINAPI d3drm_texture2_Clone(IDirect3DRMTexture2 *iface,
691         IUnknown *outer, REFIID iid, void **out)
692 {
693     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture2(iface);
694 
695     TRACE("iface %p, outer %p, iid %s, out %p.\n", iface, outer, debugstr_guid(iid), out);
696 
697     return IDirect3DRMTexture3_Clone(&texture->IDirect3DRMTexture3_iface, outer, iid, out);
698 }
699 
700 static HRESULT WINAPI d3drm_texture2_AddDestroyCallback(IDirect3DRMTexture2 *iface,
701         D3DRMOBJECTCALLBACK cb, void *ctx)
702 {
703     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture2(iface);
704 
705     TRACE("iface %p, cb %p, ctx %p\n", iface, cb, ctx);
706 
707     return IDirect3DRMTexture3_AddDestroyCallback(&texture->IDirect3DRMTexture3_iface, cb, ctx);
708 }
709 
710 static HRESULT WINAPI d3drm_texture2_DeleteDestroyCallback(IDirect3DRMTexture2 *iface,
711         D3DRMOBJECTCALLBACK cb, void *ctx)
712 {
713     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture2(iface);
714 
715     TRACE("iface %p, cb %p, ctx %p\n", iface, cb, ctx);
716 
717     return IDirect3DRMTexture3_DeleteDestroyCallback(&texture->IDirect3DRMTexture3_iface, cb, ctx);
718 }
719 
720 static HRESULT WINAPI d3drm_texture2_SetAppData(IDirect3DRMTexture2 *iface, DWORD data)
721 {
722     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture2(iface);
723 
724     TRACE("iface %p, data %#x.\n", iface, data);
725 
726     return IDirect3DRMTexture3_SetAppData(&texture->IDirect3DRMTexture3_iface, data);
727 }
728 
729 static DWORD WINAPI d3drm_texture2_GetAppData(IDirect3DRMTexture2 *iface)
730 {
731     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture2(iface);
732 
733     TRACE("iface %p.\n", iface);
734 
735     return IDirect3DRMTexture3_GetAppData(&texture->IDirect3DRMTexture3_iface);
736 }
737 
738 static HRESULT WINAPI d3drm_texture2_SetName(IDirect3DRMTexture2 *iface, const char *name)
739 {
740     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture2(iface);
741 
742     TRACE("iface %p, name %s.\n", iface, debugstr_a(name));
743 
744     return IDirect3DRMTexture3_SetName(&texture->IDirect3DRMTexture3_iface, name);
745 }
746 
747 static HRESULT WINAPI d3drm_texture2_GetName(IDirect3DRMTexture2 *iface, DWORD *size, char *name)
748 {
749     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture2(iface);
750 
751     TRACE("iface %p, size %p, name %p.\n", iface, size, name);
752 
753     return IDirect3DRMTexture3_GetName(&texture->IDirect3DRMTexture3_iface, size, name);
754 }
755 
756 static HRESULT WINAPI d3drm_texture2_GetClassName(IDirect3DRMTexture2 *iface, DWORD *size, char *name)
757 {
758     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture2(iface);
759 
760     TRACE("iface %p, size %p, name %p.\n", iface, size, name);
761 
762     return IDirect3DRMTexture3_GetClassName(&texture->IDirect3DRMTexture3_iface, size, name);
763 }
764 
765 static HRESULT WINAPI d3drm_texture2_InitFromFile(IDirect3DRMTexture2 *iface, const char *filename)
766 {
767     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture2(iface);
768 
769     TRACE("iface %p, filename %s.\n", iface, debugstr_a(filename));
770 
771     return IDirect3DRMTexture3_InitFromFile(&texture->IDirect3DRMTexture3_iface, filename);
772 }
773 
774 static HRESULT WINAPI d3drm_texture2_InitFromSurface(IDirect3DRMTexture2 *iface,
775         IDirectDrawSurface *surface)
776 {
777     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture2(iface);
778 
779     TRACE("iface %p, surface %p.\n", iface, surface);
780 
781     return IDirect3DRMTexture3_InitFromSurface(&texture->IDirect3DRMTexture3_iface, surface);
782 }
783 
784 static HRESULT WINAPI d3drm_texture2_InitFromResource(IDirect3DRMTexture2 *iface, HRSRC resource)
785 {
786     FIXME("iface %p, resource %p stub!\n", iface, resource);
787 
788     return E_NOTIMPL;
789 }
790 
791 static HRESULT WINAPI d3drm_texture2_Changed(IDirect3DRMTexture2 *iface, BOOL pixels, BOOL palette)
792 {
793     FIXME("iface %p, pixels %#x, palette %#x stub!\n", iface, pixels, palette);
794 
795     return E_NOTIMPL;
796 }
797 
798 static HRESULT WINAPI d3drm_texture2_SetColors(IDirect3DRMTexture2 *iface, DWORD max_colors)
799 {
800     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture2(iface);
801 
802     TRACE("iface %p, max_colors %u.\n", iface, max_colors);
803 
804     return IDirect3DRMTexture3_SetColors(&texture->IDirect3DRMTexture3_iface, max_colors);
805 }
806 
807 static HRESULT WINAPI d3drm_texture2_SetShades(IDirect3DRMTexture2 *iface, DWORD max_shades)
808 {
809     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture2(iface);
810 
811     TRACE("iface %p, max_shades %u.\n", iface, max_shades);
812 
813     return IDirect3DRMTexture3_SetShades(&texture->IDirect3DRMTexture3_iface, max_shades);
814 }
815 
816 static HRESULT WINAPI d3drm_texture2_SetDecalSize(IDirect3DRMTexture2 *iface, D3DVALUE width, D3DVALUE height)
817 {
818     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture2(iface);
819 
820     TRACE("iface %p, width %.8e, height %.8e.\n", iface, width, height);
821 
822     return IDirect3DRMTexture3_SetDecalSize(&texture->IDirect3DRMTexture3_iface, width, height);
823 }
824 
825 static HRESULT WINAPI d3drm_texture2_SetDecalOrigin(IDirect3DRMTexture2 *iface, LONG x, LONG y)
826 {
827     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture2(iface);
828 
829     TRACE("iface %p, x %d, y %d.\n", iface, x, y);
830 
831     return IDirect3DRMTexture3_SetDecalOrigin(&texture->IDirect3DRMTexture3_iface, x, y);
832 }
833 
834 static HRESULT WINAPI d3drm_texture2_SetDecalScale(IDirect3DRMTexture2 *iface, DWORD scale)
835 {
836     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture2(iface);
837 
838     TRACE("iface %p, scale %u.\n", iface, scale);
839 
840     return IDirect3DRMTexture3_SetDecalScale(&texture->IDirect3DRMTexture3_iface, scale);
841 }
842 
843 static HRESULT WINAPI d3drm_texture2_SetDecalTransparency(IDirect3DRMTexture2 *iface, BOOL transparency)
844 {
845     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture2(iface);
846 
847     TRACE("iface %p, transparency %#x.\n", iface, transparency);
848 
849     return IDirect3DRMTexture3_SetDecalTransparency(&texture->IDirect3DRMTexture3_iface, transparency);
850 }
851 
852 static HRESULT WINAPI d3drm_texture2_SetDecalTransparentColor(IDirect3DRMTexture2 *iface, D3DCOLOR color)
853 {
854     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture2(iface);
855 
856     TRACE("iface %p, color 0x%08x.\n", iface, color);
857 
858     return IDirect3DRMTexture3_SetDecalTransparentColor(&texture->IDirect3DRMTexture3_iface, color);
859 }
860 
861 static HRESULT WINAPI d3drm_texture2_GetDecalSize(IDirect3DRMTexture2 *iface, D3DVALUE *width, D3DVALUE *height)
862 {
863     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture2(iface);
864 
865     TRACE("iface %p, width %p, height %p.\n", iface, width, height);
866 
867     return IDirect3DRMTexture3_GetDecalSize(&texture->IDirect3DRMTexture3_iface, width, height);
868 }
869 
870 static HRESULT WINAPI d3drm_texture2_GetDecalOrigin(IDirect3DRMTexture2 *iface, LONG *x, LONG *y)
871 {
872     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture2(iface);
873 
874     TRACE("iface %p, x %p, y %p.\n", iface, x, y);
875 
876     return IDirect3DRMTexture3_GetDecalOrigin(&texture->IDirect3DRMTexture3_iface, x, y);
877 }
878 
879 static D3DRMIMAGE * WINAPI d3drm_texture2_GetImage(IDirect3DRMTexture2 *iface)
880 {
881     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture2(iface);
882 
883     TRACE("iface %p.\n", iface);
884 
885     return IDirect3DRMTexture3_GetImage(&texture->IDirect3DRMTexture3_iface);
886 }
887 
888 static DWORD WINAPI d3drm_texture2_GetShades(IDirect3DRMTexture2 *iface)
889 {
890     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture2(iface);
891 
892     TRACE("iface %p.\n", iface);
893 
894     return IDirect3DRMTexture3_GetShades(&texture->IDirect3DRMTexture3_iface);
895 }
896 
897 static DWORD WINAPI d3drm_texture2_GetColors(IDirect3DRMTexture2 *iface)
898 {
899     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture2(iface);
900 
901     TRACE("iface %p.\n", iface);
902 
903     return IDirect3DRMTexture3_GetColors(&texture->IDirect3DRMTexture3_iface);
904 }
905 
906 static DWORD WINAPI d3drm_texture2_GetDecalScale(IDirect3DRMTexture2 *iface)
907 {
908     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture2(iface);
909 
910     TRACE("iface %p.\n", iface);
911 
912     return IDirect3DRMTexture3_GetDecalScale(&texture->IDirect3DRMTexture3_iface);
913 }
914 
915 static BOOL WINAPI d3drm_texture2_GetDecalTransparency(IDirect3DRMTexture2 *iface)
916 {
917     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture2(iface);
918 
919     TRACE("iface %p.\n", iface);
920 
921     return IDirect3DRMTexture3_GetDecalTransparency(&texture->IDirect3DRMTexture3_iface);
922 }
923 
924 static D3DCOLOR WINAPI d3drm_texture2_GetDecalTransparentColor(IDirect3DRMTexture2 *iface)
925 {
926     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture2(iface);
927 
928     TRACE("iface %p.\n", iface);
929 
930     return IDirect3DRMTexture3_GetDecalTransparentColor(&texture->IDirect3DRMTexture3_iface);
931 }
932 
933 static HRESULT WINAPI d3drm_texture2_InitFromImage(IDirect3DRMTexture2 *iface, D3DRMIMAGE *image)
934 {
935     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture2(iface);
936 
937     TRACE("iface %p, image %p.\n", iface, image);
938 
939     return IDirect3DRMTexture3_InitFromImage(&texture->IDirect3DRMTexture3_iface, image);
940 }
941 
942 static HRESULT WINAPI d3drm_texture2_InitFromResource2(IDirect3DRMTexture2 *iface,
943         HMODULE module, const char *name, const char *type)
944 {
945     FIXME("iface %p, module %p, name %s, type %s stub!\n",
946             iface, module, debugstr_a(name), debugstr_a(type));
947 
948     return E_NOTIMPL;
949 }
950 
951 static HRESULT WINAPI d3drm_texture2_GenerateMIPMap(IDirect3DRMTexture2 *iface, DWORD flags)
952 {
953     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture2(iface);
954 
955     TRACE("iface %p, flags %#x.\n", iface, flags);
956 
957     return IDirect3DRMTexture3_GenerateMIPMap(&texture->IDirect3DRMTexture3_iface, flags);
958 }
959 
960 static const struct IDirect3DRMTexture2Vtbl d3drm_texture2_vtbl =
961 {
962     d3drm_texture2_QueryInterface,
963     d3drm_texture2_AddRef,
964     d3drm_texture2_Release,
965     d3drm_texture2_Clone,
966     d3drm_texture2_AddDestroyCallback,
967     d3drm_texture2_DeleteDestroyCallback,
968     d3drm_texture2_SetAppData,
969     d3drm_texture2_GetAppData,
970     d3drm_texture2_SetName,
971     d3drm_texture2_GetName,
972     d3drm_texture2_GetClassName,
973     d3drm_texture2_InitFromFile,
974     d3drm_texture2_InitFromSurface,
975     d3drm_texture2_InitFromResource,
976     d3drm_texture2_Changed,
977     d3drm_texture2_SetColors,
978     d3drm_texture2_SetShades,
979     d3drm_texture2_SetDecalSize,
980     d3drm_texture2_SetDecalOrigin,
981     d3drm_texture2_SetDecalScale,
982     d3drm_texture2_SetDecalTransparency,
983     d3drm_texture2_SetDecalTransparentColor,
984     d3drm_texture2_GetDecalSize,
985     d3drm_texture2_GetDecalOrigin,
986     d3drm_texture2_GetImage,
987     d3drm_texture2_GetShades,
988     d3drm_texture2_GetColors,
989     d3drm_texture2_GetDecalScale,
990     d3drm_texture2_GetDecalTransparency,
991     d3drm_texture2_GetDecalTransparentColor,
992     d3drm_texture2_InitFromImage,
993     d3drm_texture2_InitFromResource2,
994     d3drm_texture2_GenerateMIPMap,
995 };
996 
997 static HRESULT WINAPI d3drm_texture3_QueryInterface(IDirect3DRMTexture3 *iface, REFIID riid, void **out)
998 {
999     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture3(iface);
1000 
1001     TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
1002 
1003     if (IsEqualGUID(riid, &IID_IDirect3DRMTexture)
1004             || IsEqualGUID(riid, &IID_IDirect3DRMVisual)
1005             || IsEqualGUID(riid, &IID_IDirect3DRMObject)
1006             || IsEqualGUID(riid, &IID_IUnknown))
1007     {
1008         *out = &texture->IDirect3DRMTexture_iface;
1009     }
1010     else if (IsEqualGUID(riid, &IID_IDirect3DRMTexture2))
1011     {
1012         *out = &texture->IDirect3DRMTexture2_iface;
1013     }
1014     else if (IsEqualGUID(riid, &IID_IDirect3DRMTexture3))
1015     {
1016         *out = &texture->IDirect3DRMTexture3_iface;
1017     }
1018     else
1019     {
1020         *out = NULL;
1021         WARN("%s not implemented, returning CLASS_E_CLASSNOTAVAILABLE.\n", debugstr_guid(riid));
1022         return CLASS_E_CLASSNOTAVAILABLE;
1023     }
1024 
1025     IUnknown_AddRef((IUnknown *)*out);
1026     return S_OK;
1027 }
1028 
1029 static ULONG WINAPI d3drm_texture3_AddRef(IDirect3DRMTexture3 *iface)
1030 {
1031     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture3(iface);
1032     ULONG refcount = InterlockedIncrement(&texture->obj.ref);
1033 
1034     TRACE("%p increasing refcount to %u.\n", iface, refcount);
1035 
1036     return refcount;
1037 }
1038 
1039 static ULONG WINAPI d3drm_texture3_Release(IDirect3DRMTexture3 *iface)
1040 {
1041     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture3(iface);
1042     ULONG refcount = InterlockedDecrement(&texture->obj.ref);
1043 
1044     TRACE("%p decreasing refcount to %u.\n", iface, refcount);
1045 
1046     if (!refcount)
1047         d3drm_texture_destroy(texture);
1048 
1049     return refcount;
1050 }
1051 
1052 static HRESULT WINAPI d3drm_texture3_Clone(IDirect3DRMTexture3 *iface,
1053         IUnknown *outer, REFIID iid, void **out)
1054 {
1055     FIXME("iface %p, outer %p, iid %s, out %p stub!\n", iface, outer, debugstr_guid(iid), out);
1056 
1057     return E_NOTIMPL;
1058 }
1059 
1060 static HRESULT WINAPI d3drm_texture3_AddDestroyCallback(IDirect3DRMTexture3 *iface,
1061         D3DRMOBJECTCALLBACK cb, void *ctx)
1062 {
1063     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture3(iface);
1064 
1065     TRACE("iface %p, cb %p, ctx %p\n", iface, cb, ctx);
1066 
1067     return d3drm_object_add_destroy_callback(&texture->obj, cb, ctx);
1068 }
1069 
1070 static HRESULT WINAPI d3drm_texture3_DeleteDestroyCallback(IDirect3DRMTexture3 *iface,
1071         D3DRMOBJECTCALLBACK cb, void *ctx)
1072 {
1073     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture3(iface);
1074 
1075     TRACE("iface %p, cb %p, ctx %p\n", iface, cb, ctx);
1076 
1077     return d3drm_object_delete_destroy_callback(&texture->obj, cb, ctx);
1078 }
1079 
1080 static HRESULT WINAPI d3drm_texture3_SetAppData(IDirect3DRMTexture3 *iface, DWORD data)
1081 {
1082     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture3(iface);
1083 
1084     TRACE("iface %p, data %#x.\n", iface, data);
1085 
1086     texture->obj.appdata = data;
1087 
1088     return D3DRM_OK;
1089 }
1090 
1091 static DWORD WINAPI d3drm_texture3_GetAppData(IDirect3DRMTexture3 *iface)
1092 {
1093     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture3(iface);
1094 
1095     TRACE("iface %p.\n", iface);
1096 
1097     return texture->obj.appdata;
1098 }
1099 
1100 static HRESULT WINAPI d3drm_texture3_SetName(IDirect3DRMTexture3 *iface, const char *name)
1101 {
1102     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture3(iface);
1103 
1104     TRACE("iface %p, name %s.\n", iface, debugstr_a(name));
1105 
1106     return d3drm_object_set_name(&texture->obj, name);
1107 }
1108 
1109 static HRESULT WINAPI d3drm_texture3_GetName(IDirect3DRMTexture3 *iface, DWORD *size, char *name)
1110 {
1111     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture3(iface);
1112 
1113     TRACE("iface %p, size %p, name %p.\n", iface, size, name);
1114 
1115     return d3drm_object_get_name(&texture->obj, size, name);
1116 }
1117 
1118 static HRESULT WINAPI d3drm_texture3_GetClassName(IDirect3DRMTexture3 *iface, DWORD *size, char *name)
1119 {
1120     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture3(iface);
1121 
1122     TRACE("iface %p, size %p, name %p.\n", iface, size, name);
1123 
1124     return d3drm_object_get_class_name(&texture->obj, size, name);
1125 }
1126 
1127 static HRESULT WINAPI d3drm_texture3_InitFromFile(IDirect3DRMTexture3 *iface, const char *filename)
1128 {
1129     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture3(iface);
1130     D3DRMIMAGE *image;
1131     HRESULT hr;
1132 
1133     TRACE("iface %p, filename %s.\n", iface, debugstr_a(filename));
1134 
1135     if (FAILED(hr = d3drm_texture_load(texture, filename, TRUE, &image)))
1136         return hr;
1137 
1138     return IDirect3DRMTexture3_InitFromImage(iface, image);
1139 }
1140 
1141 static HRESULT WINAPI d3drm_texture3_InitFromSurface(IDirect3DRMTexture3 *iface,
1142         IDirectDrawSurface *surface)
1143 {
1144     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture3(iface);
1145 
1146     TRACE("iface %p, surface %p.\n", iface, surface);
1147 
1148     if (!surface)
1149         return D3DRMERR_BADOBJECT;
1150 
1151     /* d3drm intentionally leaks a reference to IDirect3DRM here if texture has already been initialized. */
1152     IDirect3DRM_AddRef(texture->d3drm);
1153 
1154     if (texture->image || texture->surface)
1155         return D3DRMERR_BADOBJECT;
1156 
1157     texture->surface = surface;
1158     IDirectDrawSurface_AddRef(texture->surface);
1159     return D3DRM_OK;
1160 }
1161 
1162 static HRESULT WINAPI d3drm_texture3_InitFromResource(IDirect3DRMTexture3 *iface, HRSRC resource)
1163 {
1164     FIXME("iface %p, resource %p stub!\n", iface, resource);
1165 
1166     return E_NOTIMPL;
1167 }
1168 
1169 static HRESULT WINAPI d3drm_texture3_Changed(IDirect3DRMTexture3 *iface,
1170         DWORD flags, DWORD rect_count, RECT *rects)
1171 {
1172     FIXME("iface %p, flags %#x, rect_count %u, rects %p stub!\n", iface, flags, rect_count, rects);
1173 
1174     return E_NOTIMPL;
1175 }
1176 
1177 static HRESULT WINAPI d3drm_texture3_SetColors(IDirect3DRMTexture3 *iface, DWORD max_colors)
1178 {
1179     FIXME("iface %p, max_colors %u stub!\n", iface, max_colors);
1180 
1181     return E_NOTIMPL;
1182 }
1183 
1184 static HRESULT WINAPI d3drm_texture3_SetShades(IDirect3DRMTexture3 *iface, DWORD max_shades)
1185 {
1186     FIXME("iface %p, max_shades %u stub!\n", iface, max_shades);
1187 
1188     return E_NOTIMPL;
1189 }
1190 
1191 static HRESULT WINAPI d3drm_texture3_SetDecalSize(IDirect3DRMTexture3 *iface, D3DVALUE width, D3DVALUE height)
1192 {
1193     FIXME("iface %p, width %.8e, height %.8e stub!\n", iface, width, height);
1194 
1195     return E_NOTIMPL;
1196 }
1197 
1198 static HRESULT WINAPI d3drm_texture3_SetDecalOrigin(IDirect3DRMTexture3 *iface, LONG x, LONG y)
1199 {
1200     FIXME("iface %p, x %d, y %d stub!\n", iface, x, y);
1201 
1202     return E_NOTIMPL;
1203 }
1204 
1205 static HRESULT WINAPI d3drm_texture3_SetDecalScale(IDirect3DRMTexture3 *iface, DWORD scale)
1206 {
1207     FIXME("iface %p, scale %u stub!\n", iface, scale);
1208 
1209     return E_NOTIMPL;
1210 }
1211 
1212 static HRESULT WINAPI d3drm_texture3_SetDecalTransparency(IDirect3DRMTexture3 *iface, BOOL transparency)
1213 {
1214     FIXME("iface %p, transparency %#x stub!\n", iface, transparency);
1215 
1216     return E_NOTIMPL;
1217 }
1218 
1219 static HRESULT WINAPI d3drm_texture3_SetDecalTransparentColor(IDirect3DRMTexture3 *iface, D3DCOLOR color)
1220 {
1221     FIXME("iface %p, color 0x%08x stub!\n", iface, color);
1222 
1223     return E_NOTIMPL;
1224 }
1225 
1226 static HRESULT WINAPI d3drm_texture3_GetDecalSize(IDirect3DRMTexture3 *iface, D3DVALUE *width, D3DVALUE *height)
1227 {
1228     FIXME("iface %p, width %p, height %p stub!\n", iface, width, height);
1229 
1230     return E_NOTIMPL;
1231 }
1232 
1233 static HRESULT WINAPI d3drm_texture3_GetDecalOrigin(IDirect3DRMTexture3 *iface, LONG *x, LONG *y)
1234 {
1235     FIXME("iface %p, x %p, y %p stub!\n", iface, x, y);
1236 
1237     return E_NOTIMPL;
1238 }
1239 
1240 static D3DRMIMAGE * WINAPI d3drm_texture3_GetImage(IDirect3DRMTexture3 *iface)
1241 {
1242     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture3(iface);
1243 
1244     TRACE("iface %p.\n", iface);
1245 
1246     return texture->image;
1247 }
1248 
1249 static DWORD WINAPI d3drm_texture3_GetShades(IDirect3DRMTexture3 *iface)
1250 {
1251     FIXME("iface %p stub!\n", iface);
1252 
1253     return 0;
1254 }
1255 
1256 static DWORD WINAPI d3drm_texture3_GetColors(IDirect3DRMTexture3 *iface)
1257 {
1258     FIXME("iface %p stub!\n", iface);
1259 
1260     return 0;
1261 }
1262 
1263 static DWORD WINAPI d3drm_texture3_GetDecalScale(IDirect3DRMTexture3 *iface)
1264 {
1265     FIXME("iface %p stub!\n", iface);
1266 
1267     return 0;
1268 }
1269 
1270 static BOOL WINAPI d3drm_texture3_GetDecalTransparency(IDirect3DRMTexture3 *iface)
1271 {
1272     FIXME("iface %p stub!\n", iface);
1273 
1274     return FALSE;
1275 }
1276 
1277 static D3DCOLOR WINAPI d3drm_texture3_GetDecalTransparentColor(IDirect3DRMTexture3 *iface)
1278 {
1279     FIXME("iface %p stub!\n", iface);
1280 
1281     return 0;
1282 }
1283 
1284 static HRESULT WINAPI d3drm_texture3_InitFromImage(IDirect3DRMTexture3 *iface, D3DRMIMAGE *image)
1285 {
1286     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture3(iface);
1287 
1288     TRACE("iface %p, image %p.\n", iface, image);
1289 
1290     if (!d3drm_validate_image(image))
1291         return D3DRMERR_BADOBJECT;
1292 
1293     /* d3drm intentionally leaks a reference to IDirect3DRM here if texture has already been initialized. */
1294     IDirect3DRM_AddRef(texture->d3drm);
1295 
1296     if (texture->image || texture->surface)
1297         return D3DRMERR_BADOBJECT;
1298 
1299     texture->image = image;
1300 
1301     return D3DRM_OK;
1302 }
1303 
1304 static HRESULT WINAPI d3drm_texture3_InitFromResource2(IDirect3DRMTexture3 *iface,
1305         HMODULE module, const char *name, const char *type)
1306 {
1307     FIXME("iface %p, module %p, name %s, type %s stub!\n",
1308             iface, module, debugstr_a(name), debugstr_a(type));
1309 
1310     return E_NOTIMPL;
1311 }
1312 
1313 static HRESULT WINAPI d3drm_texture3_GenerateMIPMap(IDirect3DRMTexture3 *iface, DWORD flags)
1314 {
1315     FIXME("iface %p, flags %#x stub!\n", iface, flags);
1316 
1317     return E_NOTIMPL;
1318 }
1319 
1320 static HRESULT WINAPI d3drm_texture3_GetSurface(IDirect3DRMTexture3 *iface,
1321         DWORD flags, IDirectDrawSurface **surface)
1322 {
1323     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture3(iface);
1324 
1325     TRACE("iface %p, flags %#x, surface %p.\n", iface, flags, surface);
1326 
1327     if (flags)
1328         FIXME("unexpected flags %#x.\n", flags);
1329 
1330     if (!surface)
1331         return D3DRMERR_BADVALUE;
1332 
1333     if (texture->image)
1334         return D3DRMERR_NOTCREATEDFROMDDS;
1335 
1336     *surface = texture->surface;
1337     IDirectDrawSurface_AddRef(*surface);
1338 
1339     return D3DRM_OK;
1340 }
1341 
1342 static HRESULT WINAPI d3drm_texture3_SetCacheOptions(IDirect3DRMTexture3 *iface, LONG importance, DWORD flags)
1343 {
1344     FIXME("iface %p, importance %d, flags %#x stub!\n", iface, importance, flags);
1345 
1346     return E_NOTIMPL;
1347 }
1348 
1349 static HRESULT WINAPI d3drm_texture3_GetCacheOptions(IDirect3DRMTexture3 *iface,
1350         LONG *importance, DWORD *flags)
1351 {
1352     FIXME("iface %p, importance %p, flags %p stub!\n", iface, importance, flags);
1353 
1354     return E_NOTIMPL;
1355 }
1356 
1357 static HRESULT WINAPI d3drm_texture3_SetDownsampleCallback(IDirect3DRMTexture3 *iface,
1358         D3DRMDOWNSAMPLECALLBACK cb, void *ctx)
1359 {
1360     FIXME("iface %p, cb %p, ctx %p stub!\n", iface, cb, ctx);
1361 
1362     return E_NOTIMPL;
1363 }
1364 
1365 static HRESULT WINAPI d3drm_texture3_SetValidationCallback(IDirect3DRMTexture3 *iface,
1366         D3DRMVALIDATIONCALLBACK cb, void *ctx)
1367 {
1368     FIXME("iface %p, cb %p, ctx %p stub!\n", iface, cb, ctx);
1369 
1370     return E_NOTIMPL;
1371 }
1372 
1373 static const struct IDirect3DRMTexture3Vtbl d3drm_texture3_vtbl =
1374 {
1375     d3drm_texture3_QueryInterface,
1376     d3drm_texture3_AddRef,
1377     d3drm_texture3_Release,
1378     d3drm_texture3_Clone,
1379     d3drm_texture3_AddDestroyCallback,
1380     d3drm_texture3_DeleteDestroyCallback,
1381     d3drm_texture3_SetAppData,
1382     d3drm_texture3_GetAppData,
1383     d3drm_texture3_SetName,
1384     d3drm_texture3_GetName,
1385     d3drm_texture3_GetClassName,
1386     d3drm_texture3_InitFromFile,
1387     d3drm_texture3_InitFromSurface,
1388     d3drm_texture3_InitFromResource,
1389     d3drm_texture3_Changed,
1390     d3drm_texture3_SetColors,
1391     d3drm_texture3_SetShades,
1392     d3drm_texture3_SetDecalSize,
1393     d3drm_texture3_SetDecalOrigin,
1394     d3drm_texture3_SetDecalScale,
1395     d3drm_texture3_SetDecalTransparency,
1396     d3drm_texture3_SetDecalTransparentColor,
1397     d3drm_texture3_GetDecalSize,
1398     d3drm_texture3_GetDecalOrigin,
1399     d3drm_texture3_GetImage,
1400     d3drm_texture3_GetShades,
1401     d3drm_texture3_GetColors,
1402     d3drm_texture3_GetDecalScale,
1403     d3drm_texture3_GetDecalTransparency,
1404     d3drm_texture3_GetDecalTransparentColor,
1405     d3drm_texture3_InitFromImage,
1406     d3drm_texture3_InitFromResource2,
1407     d3drm_texture3_GenerateMIPMap,
1408     d3drm_texture3_GetSurface,
1409     d3drm_texture3_SetCacheOptions,
1410     d3drm_texture3_GetCacheOptions,
1411     d3drm_texture3_SetDownsampleCallback,
1412     d3drm_texture3_SetValidationCallback,
1413 };
1414 
1415 HRESULT d3drm_texture_create(struct d3drm_texture **texture, IDirect3DRM *d3drm)
1416 {
1417     static const char classname[] = "Texture";
1418     struct d3drm_texture *object;
1419 
1420     TRACE("texture %p.\n", texture);
1421 
1422     if (!(object = heap_alloc_zero(sizeof(*object))))
1423         return E_OUTOFMEMORY;
1424 
1425     object->IDirect3DRMTexture_iface.lpVtbl = &d3drm_texture1_vtbl;
1426     object->IDirect3DRMTexture2_iface.lpVtbl = &d3drm_texture2_vtbl;
1427     object->IDirect3DRMTexture3_iface.lpVtbl = &d3drm_texture3_vtbl;
1428     object->d3drm = d3drm;
1429 
1430     d3drm_object_init(&object->obj, classname);
1431 
1432     *texture = object;
1433 
1434     return D3DRM_OK;
1435 }
1436