[PATCH 2/2] d3drm: Partially Implement IDirect3DRM*::LoadTexture(v2).

Aaryaman Vasishta jem456.vasishta at gmail.com
Sun Mar 20 13:24:43 CDT 2016


Currently it can load 8bpp and 24bpp textures. It can be extended to support 16bpp  as well. AFAIK there hasn't really been any use-case available as motivation to implement support for other formats.

The next plan is that once rendering implementation begins, texture data will be mapped onto faces, frames and meshes by using the data in D3DRMIMAGE struct internally in immediate mode calls.

As I'm still in my final year before graduating,  I am planning to apply for GSoC this summer in order to dedicate myself to implementing viewports, scenes and frames before getting  to get some basic drawing working without using native dll. I will be continuing my implementations from now itself.

Reviews will be highly appreciated :)

Cheers,
Aaryaman

Signed-off-by: Aaryaman Vasishta <jem456.vasishta at gmail.com>
---
 dlls/d3drm/Makefile.in     |   2 +-
 dlls/d3drm/d3drm.c         |  29 ++++--
 dlls/d3drm/d3drm_private.h |   8 ++
 dlls/d3drm/tests/d3drm.c   |  22 ++++-
 dlls/d3drm/texture.c       | 220 ++++++++++++++++++++++++++++++++++++++++++++-
 5 files changed, 267 insertions(+), 14 deletions(-)

diff --git a/dlls/d3drm/Makefile.in b/dlls/d3drm/Makefile.in
index 5db3494..c923e74 100644
--- a/dlls/d3drm/Makefile.in
+++ b/dlls/d3drm/Makefile.in
@@ -1,6 +1,6 @@
 MODULE    = d3drm.dll
 IMPORTLIB = d3drm
-IMPORTS   = dxguid uuid d3dxof ddraw
+IMPORTS   = dxguid uuid d3dxof ddraw gdi32
 
 C_SRCS = \
 	d3drm.c \
diff --git a/dlls/d3drm/d3drm.c b/dlls/d3drm/d3drm.c
index fe33315..9610bf9 100644
--- a/dlls/d3drm/d3drm.c
+++ b/dlls/d3drm/d3drm.c
@@ -414,11 +414,17 @@ static HRESULT WINAPI d3drm1_LoadTexture(IDirect3DRM *iface,
     struct d3drm_texture *object;
     HRESULT hr;
 
-    FIXME("iface %p, filename %s, texture %p stub!\n", iface, debugstr_a(filename), texture);
+    TRACE("iface %p, filename %s, texture %p\n", iface, debugstr_a(filename), texture);
 
     if (FAILED(hr = d3drm_texture_create(&object)))
         return hr;
 
+    if (FAILED(hr = d3drm_texture_load(object, iface, filename, FALSE)))
+    {
+        d3drm_texture_destroy(object);
+        return hr;
+    }
+
     *texture = &object->IDirect3DRMTexture_iface;
 
     return D3DRM_OK;
@@ -853,15 +859,19 @@ static HRESULT WINAPI d3drm2_CreateUserVisual(IDirect3DRM2 *iface,
 static HRESULT WINAPI d3drm2_LoadTexture(IDirect3DRM2 *iface,
         const char *filename, IDirect3DRMTexture2 **texture)
 {
-    struct d3drm_texture *object;
+    struct d3drm *d3drm = impl_from_IDirect3DRM2(iface);
+    IDirect3DRMTexture3 *texture3;
     HRESULT hr;
 
-    FIXME("iface %p, filename %s, texture %p stub!\n", iface, debugstr_a(filename), texture);
+    TRACE("iface %p, filename %s, texture %p.\n", iface, debugstr_a(filename), texture);
 
-    if (FAILED(hr = d3drm_texture_create(&object)))
+    if (FAILED(hr = IDirect3DRM3_LoadTexture(&d3drm->IDirect3DRM3_iface, filename, &texture3)))
         return hr;
 
-    *texture = &object->IDirect3DRMTexture2_iface;
+    hr = IDirect3DRMTexture3_QueryInterface(texture3, &IID_IDirect3DRMTexture2, (void**)texture);
+    IDirect3DRMTexture3_Release(texture3);
+    if (FAILED(hr))
+        return hr;
 
     return D3DRM_OK;
 }
@@ -1353,13 +1363,20 @@ static HRESULT WINAPI d3drm3_LoadTexture(IDirect3DRM3 *iface,
         const char *filename, IDirect3DRMTexture3 **texture)
 {
     struct d3drm_texture *object;
+    struct d3drm *d3drm = impl_from_IDirect3DRM3(iface);
     HRESULT hr;
 
-    FIXME("iface %p, filename %s, texture %p stub!\n", iface, debugstr_a(filename), texture);
+    TRACE("iface %p, filename %s, texture %p\n", iface, debugstr_a(filename), texture);
 
     if (FAILED(hr = d3drm_texture_create(&object)))
         return hr;
 
+    if (FAILED(hr = d3drm_texture_load(object, &d3drm->IDirect3DRM_iface, filename, TRUE)))
+    {
+        d3drm_texture_destroy(object);
+        return hr;
+    }
+
     *texture = &object->IDirect3DRMTexture3_iface;
 
     return D3DRM_OK;
diff --git a/dlls/d3drm/d3drm_private.h b/dlls/d3drm/d3drm_private.h
index 5452b36..3aeb794 100644
--- a/dlls/d3drm/d3drm_private.h
+++ b/dlls/d3drm/d3drm_private.h
@@ -39,6 +39,8 @@ struct d3drm_texture
     IDirect3DRMTexture IDirect3DRMTexture_iface;
     IDirect3DRMTexture2 IDirect3DRMTexture2_iface;
     IDirect3DRMTexture3 IDirect3DRMTexture3_iface;
+    IDirect3DRM *d3drm;
+    D3DRMIMAGE *image;
     LONG ref;
     DWORD app_data;
 };
@@ -74,6 +76,12 @@ HRESULT d3drm_device_init(struct d3drm_device *device, UINT version, IDirect3DRM
 
 HRESULT d3drm_device_set_ddraw_device_d3d(struct d3drm_device *device, IDirect3DRM *d3drm, IDirect3D *d3d, IDirect3DDevice *d3d_device) DECLSPEC_HIDDEN;
 
+void d3drm_texture_destroy(struct d3drm_texture *texture);
+
+HRESULT d3drm_texture_load(struct d3drm_texture *texture, IDirect3DRM *d3drm, const char *path, BOOL load_upside_down) DECLSPEC_HIDDEN;
+
+D3DRMIMAGE *d3drm_create_image(unsigned char *buffer, BITMAPINFO *info, BOOL palette, BOOL upside_down);
+
 struct d3drm_file_header
 {
     WORD major;
diff --git a/dlls/d3drm/tests/d3drm.c b/dlls/d3drm/tests/d3drm.c
index 8a125fc..2c6dfe9 100644
--- a/dlls/d3drm/tests/d3drm.c
+++ b/dlls/d3drm/tests/d3drm.c
@@ -4073,6 +4073,7 @@ static void test_load_texture(void)
     char *filename;
     HRESULT hr;
     BOOL ret;
+    ULONG ref1, ref2;
     int i;
 
     static const struct
@@ -4096,6 +4097,7 @@ static void test_load_texture(void)
     ok(SUCCEEDED(hr), "Failed to get IDirect3DRM2 interface, hr %#x.\n", hr);
     hr = IDirect3DRM_QueryInterface(d3drm1, &IID_IDirect3DRM3, (void **)&d3drm3);
     ok(SUCCEEDED(hr), "Failed to get IDirect3DRM3 interface, hr %#x.\n", hr);
+    ref1 = get_refcount((IUnknown *)d3drm1);
 
     for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
     {
@@ -4103,24 +4105,34 @@ static void test_load_texture(void)
 
         hr = IDirect3DRM_LoadTexture(d3drm1, filename, &texture1);
         ok(SUCCEEDED(hr), "Test %u: Failed to load texture, hr %#x.\n", i, hr);
+        ref2 = get_refcount((IUnknown *)d3drm1);
+        ok(ref2 > ref1, "expected ref2 > ref1, got ref1 = %u, ref2 = %u.\n", ref1, ref2);
         d3drm_img = IDirect3DRMTexture_GetImage(texture1);
-        todo_wine ok(!!d3drm_img, "Test %u: Failed to get image.\n", i);
+        ok(!!d3drm_img, "Test %u: Failed to get image.\n", i);
         if (d3drm_img)
             test_bitmap_data(i * 4, d3drm_img, FALSE, tests[i].w, tests[i].h, tests[i].palettized);
         IDirect3DRMTexture_Release(texture1);
+        ref2 = get_refcount((IUnknown *)d3drm1);
+        ok(ref1 == ref2, "expected ref1 == ref2, got ref1 = %u, ref2 = %u.\n", ref1, ref2);
 
         hr = IDirect3DRM2_LoadTexture(d3drm2, filename, &texture2);
         ok(SUCCEEDED(hr), "Test %u: Failed to load texture, hr %#x.\n", i, hr);
+        ref2 = get_refcount((IUnknown *)d3drm1);
+        ok(ref2 > ref1, "expected ref2 > ref1, got ref1 = %u, ref2 = %u.\n", ref1, ref2);
         d3drm_img = IDirect3DRMTexture2_GetImage(texture2);
-        todo_wine ok(!!d3drm_img, "Test %u: Failed to get image.\n", i);
+        ok(!!d3drm_img, "Test %u: Failed to get image.\n", i);
         if (d3drm_img)
             test_bitmap_data(i * 4 + 1, d3drm_img, TRUE, tests[i].w, tests[i].h, tests[i].palettized);
         IDirect3DRMTexture2_Release(texture2);
+        ref2 = get_refcount((IUnknown *)d3drm1);
+        ok(ref1 == ref2, "expected ref1 == ref2, got ref1 = %u, ref2 = %u.\n", ref1, ref2);
 
         hr = IDirect3DRM3_LoadTexture(d3drm3, filename, &texture3);
         ok(SUCCEEDED(hr), "Test %u: Failed to load texture, hr %#x.\n", i, hr);
+        ref2 = get_refcount((IUnknown *)d3drm1);
+        ok(ref2 > ref1, "expected ref2 > ref1, got ref1 = %u, ref2 = %u.\n", ref1, ref2);
         d3drm_img = IDirect3DRMTexture3_GetImage(texture3);
-        todo_wine ok(!!d3drm_img, "Test %u: Failed to get image.\n", i);
+        ok(!!d3drm_img, "Test %u: Failed to get image.\n", i);
         if (d3drm_img)
             test_bitmap_data(i * 4 + 2, d3drm_img, TRUE, tests[i].w, tests[i].h, tests[i].palettized);
         /* Test whether querying a version 1 texture from version 3 causes a
@@ -4128,11 +4140,13 @@ static void test_load_texture(void)
         hr = IDirect3DRMTexture3_QueryInterface(texture3, &IID_IDirect3DRMTexture, (void **)&texture1);
         ok(SUCCEEDED(hr), "Failed to get IDirect3DRMTexture interface, hr %#x.\n", hr);
         d3drm_img = IDirect3DRMTexture_GetImage(texture1);
-        todo_wine ok(!!d3drm_img, "Test %u: Failed to get image.\n", i);
+        ok(!!d3drm_img, "Test %u: Failed to get image.\n", i);
         if (d3drm_img)
             test_bitmap_data(i * 4 + 3, d3drm_img, TRUE, tests[i].w, tests[i].h, tests[i].palettized);
         IDirect3DRMTexture_Release(texture1);
         IDirect3DRMTexture3_Release(texture3);
+        ref2 = get_refcount((IUnknown *)d3drm1);
+        ok(ref1 == ref2, "expected ref1 == ref2, got ref1 = %u, ref2 = %u.\n", ref1, ref2);
 
         ret = DeleteFileA(filename);
         ok(ret, "Test %u: Failed to delete bitmap \"%s\".\n", i, filename);
diff --git a/dlls/d3drm/texture.c b/dlls/d3drm/texture.c
index 6a0adc5..c927e57 100644
--- a/dlls/d3drm/texture.c
+++ b/dlls/d3drm/texture.c
@@ -44,6 +44,218 @@ static inline struct d3drm_texture *impl_from_IDirect3DRMTexture3(IDirect3DRMTex
     return CONTAINING_RECORD(iface, struct d3drm_texture, IDirect3DRMTexture3_iface);
 }
 
+void d3drm_texture_destroy(struct d3drm_texture *texture)
+{
+    if (texture->image)
+    {
+        TRACE("Releasing attached members.\n");
+        HeapFree(GetProcessHeap(), 0, texture->image->buffer1);
+        if(texture->image->palette)
+            HeapFree(GetProcessHeap(), 0, texture->image->palette);
+        HeapFree(GetProcessHeap(), 0, texture->image);
+        IDirect3DRM_Release(texture->d3drm);
+    }
+    TRACE("Releasing texture.\n");
+    HeapFree(GetProcessHeap(), 0, texture);
+}
+
+HRESULT d3drm_texture_load(struct d3drm_texture *texture, IDirect3DRM *d3drm, const char *path, BOOL load_upside_down)
+{
+    BITMAPINFO *info;
+    BITMAPFILEHEADER *bmp_header;
+    unsigned char *buffer;
+    DWORD size;
+    HANDLE hfile, hmapping;
+
+    hfile = CreateFileA(path, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
+    if (hfile == INVALID_HANDLE_VALUE)
+        return D3DRMERR_BADFILE;
+
+    size = GetFileSize(hfile, NULL);
+    if (size == INVALID_FILE_SIZE)
+    {
+        DeleteObject(hfile);
+        return D3DRMERR_BADVALUE;
+    }
+
+    hmapping = CreateFileMappingA(hfile, NULL, PAGE_READONLY, 0, 0, NULL);
+    if (!hmapping)
+    {
+        DeleteObject(hfile);
+        return D3DRMERR_BADVALUE;
+    }
+
+    buffer = MapViewOfFile(hmapping, FILE_MAP_READ, 0, 0, 0);
+    if (buffer == NULL)
+    {
+        DeleteObject(hfile);
+        DeleteObject(hmapping);
+        return D3DRMERR_BADVALUE;
+    }
+
+    bmp_header = (BITMAPFILEHEADER *)buffer;
+    info = (BITMAPINFO *) (buffer + sizeof(*bmp_header));
+
+    if (info->bmiHeader.biBitCount == 8)
+        texture->image = d3drm_create_image(buffer + sizeof(BITMAPINFOHEADER) + sizeof(BITMAPFILEHEADER) + 256 * sizeof(RGBQUAD), info, TRUE, load_upside_down);
+    else
+        texture->image = d3drm_create_image(buffer + sizeof(BITMAPINFOHEADER) + sizeof(BITMAPFILEHEADER), info, FALSE, load_upside_down);
+
+    UnmapViewOfFile(buffer);
+    CloseHandle(hmapping);
+    CloseHandle(hfile);
+
+    texture->d3drm = d3drm;
+    IDirect3DRM_AddRef(d3drm);
+
+    return D3DRM_OK;
+}
+
+D3DRMIMAGE *d3drm_create_image(unsigned char *buffer, BITMAPINFO *info, BOOL palette, BOOL upside_down)
+{
+    D3DRMPALETTEENTRY *colors = (D3DRMPALETTEENTRY *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 257 * sizeof(*colors));
+    D3DRMIMAGE *image;
+    BOOL black_used = FALSE;
+    LONG w = info->bmiHeader.biWidth;
+    LONG h = abs(info->bmiHeader.biHeight);
+    int i, j, k;
+    unsigned int idx, buffer1_idx;
+    unsigned char *buffer1;
+    int bpp = info->bmiHeader.biBitCount == 24 ? 32 : info->bmiHeader.biBitCount;
+    int bpl = palette ? w : ((w + 3) & ~3) * bpp / 8;
+    int num_colors = 0;
+    struct colors_24bpp
+    {
+        BYTE red;
+        BYTE green;
+        BYTE blue;
+    } *color;
+    color = (struct colors_24bpp *)buffer;
+
+    image = (D3DRMIMAGE *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*image));
+    image->buffer1 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(unsigned char) * bpl * h);
+    buffer1 = image->buffer1;
+    memset(buffer1, 255, sizeof(unsigned char) * bpl * h);
+    if (!palette)
+    {
+
+        for (i = 0; i < h; i++)
+        {
+            for (j = 0; j < w; j++)
+            {
+                buffer1_idx = ((w + 3) & ~3) * i + j;
+                idx = upside_down ? (h - 1 - i) * w + j : i * w + j;
+                for (k = 0; k < 256; k++)
+                {
+                    if (color[idx].blue == colors[k].blue   &&
+                        color[idx].green == colors[k].green &&
+                        color[idx].red == colors[k].red)
+                    {
+                        if (color[idx].blue == 0 &&
+                            color[idx].green == 0 &&
+                            color[idx].red == 0 &&
+                            !black_used)
+                        {
+                            black_used = TRUE;
+                            colors[num_colors++].flags = D3DRMPALETTE_READONLY;
+                        }
+                        buffer1[buffer1_idx] = k;
+
+                        break;
+                    }
+                }
+                if (k == 256)
+                {
+                    buffer1[buffer1_idx] = num_colors;
+                    colors[num_colors].red = color[idx].red;
+                    colors[num_colors].green = color[idx].green;
+                    colors[num_colors].blue = color[idx].blue;
+                    colors[num_colors++].flags = D3DRMPALETTE_READONLY;
+                }
+                if (num_colors > 256)
+                {
+                    i = h;
+                    break;
+                }
+            }
+            memset(buffer1 + buffer1_idx + 1, 0, ((w + 3) & ~3) - w);
+
+        }
+
+        if (num_colors <= 256)
+        {
+            image->palette = (D3DRMPALETTEENTRY *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, num_colors * sizeof(*image->palette));
+            image->red_mask = 0xff;
+            image->green_mask = 0xff;
+            image->blue_mask = 0xff;
+            bpl = bpl / (bpp / 8);
+            memcpy(image->palette, colors, num_colors * sizeof(D3DRMPALETTEENTRY));
+            image->palette_size = num_colors;
+            palette = TRUE;
+        }
+        else
+        {
+            bpl = w * 4;
+            image->rgb = 1;
+            image->palette = NULL;
+            for (i = 0; i < h; ++i)
+            {
+                for (j = 0; j < w; ++j)
+                {
+                    unsigned char *ptr = &buffer1[i * bpl + j * 4];
+                    idx = upside_down ? (h - 1 - i) * w * 3 + j * 3 : i * w * 3 + j * 3;
+                    ptr[0] = buffer[idx];
+                    ptr[1] = buffer[idx + 1];
+                    ptr[2] = buffer[idx + 2];
+                    ptr[3] = 0xff;
+                }
+            }
+
+            image->red_mask = 0xff0000;
+            image->green_mask = 0x00ff00;
+            image->blue_mask = 0x0000ff;
+        }
+    }
+    else
+    {
+        image->palette = (D3DRMPALETTEENTRY *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 256 * sizeof(*image->palette));
+        memcpy(image->palette, info->bmiColors, 256 * sizeof(D3DRMPALETTEENTRY));
+        for (i = 0; i < 256; i++)
+        {
+            image->palette[i].flags = D3DRMPALETTE_READONLY;
+        }
+        if (upside_down)
+        {
+            for (i = 0; i < h; i++)
+            {
+                for (j = 0; j < w; j++)
+                {
+                    idx = (h - 1 - i) * bpl + j;
+                    buffer1[i * bpl + j] = buffer[idx];
+                }
+            }
+        }
+        else
+        {
+            memcpy(buffer1, buffer, bpl * h);
+        }
+        image->palette_size = 256;
+        image->red_mask = 0xff;
+        image->green_mask = 0xff;
+        image->blue_mask = 0xff;
+    }
+    image->width = w;
+    image->height = h;
+    image->aspectx = 1;
+    image->aspecty = 1;
+    image->alpha_mask = 0;
+    image->depth = palette ? 8 : bpp;
+    image->bytes_per_line = bpl;
+    HeapFree(GetProcessHeap(), 0, colors);
+
+    return image;
+}
+
 static HRESULT WINAPI d3drm_texture1_QueryInterface(IDirect3DRMTexture *iface, REFIID riid, void **out)
 {
     struct d3drm_texture *texture = impl_from_IDirect3DRMTexture(iface);
@@ -714,7 +926,7 @@ static ULONG WINAPI d3drm_texture3_Release(IDirect3DRMTexture3 *iface)
     TRACE("%p decreasing refcount to %u.\n", iface, refcount);
 
     if (!refcount)
-        HeapFree(GetProcessHeap(), 0, texture);
+        d3drm_texture_destroy(texture);
 
     return refcount;
 }
@@ -885,9 +1097,11 @@ static HRESULT WINAPI d3drm_texture3_GetDecalOrigin(IDirect3DRMTexture3 *iface,
 
 static D3DRMIMAGE * WINAPI d3drm_texture3_GetImage(IDirect3DRMTexture3 *iface)
 {
-    FIXME("iface %p stub!\n", iface);
+    struct d3drm_texture *texture = impl_from_IDirect3DRMTexture3(iface);
+
+    TRACE("iface %p\n", iface);
 
-    return NULL;
+    return texture->image;
 }
 
 static DWORD WINAPI d3drm_texture3_GetShades(IDirect3DRMTexture3 *iface)
-- 
2.3.2 (Apple Git-55)




More information about the wine-patches mailing list