2016-06-24 15:24:58 +02:00
|
|
|
#include <cstdio>
|
|
|
|
#include <cstdlib>
|
|
|
|
#include <cstring>
|
|
|
|
#include <cassert>
|
|
|
|
|
|
|
|
#include "../rwbase.h"
|
|
|
|
#include "../rwplg.h"
|
|
|
|
#include "../rwpipeline.h"
|
|
|
|
#include "../rwobjects.h"
|
|
|
|
#include "../rwengine.h"
|
|
|
|
#include "rwd3d.h"
|
|
|
|
|
|
|
|
namespace rw {
|
|
|
|
namespace d3d {
|
|
|
|
|
|
|
|
bool32 isP8supported = 1;
|
|
|
|
|
2017-08-09 10:57:32 +02:00
|
|
|
#ifndef RW_D3D9
|
2016-06-24 15:24:58 +02:00
|
|
|
#define MAKEFOURCC(ch0, ch1, ch2, ch3) \
|
|
|
|
((uint32)(uint8)(ch0) | ((uint32)(uint8)(ch1) << 8) | \
|
|
|
|
((uint32)(uint8)(ch2) << 16) | ((uint32)(uint8)(ch3) << 24 ))
|
|
|
|
enum {
|
|
|
|
D3DFMT_UNKNOWN = 0,
|
|
|
|
|
|
|
|
D3DFMT_R8G8B8 = 20,
|
|
|
|
D3DFMT_A8R8G8B8 = 21,
|
|
|
|
D3DFMT_X8R8G8B8 = 22,
|
|
|
|
D3DFMT_R5G6B5 = 23,
|
|
|
|
D3DFMT_X1R5G5B5 = 24,
|
|
|
|
D3DFMT_A1R5G5B5 = 25,
|
|
|
|
D3DFMT_A4R4G4B4 = 26,
|
|
|
|
D3DFMT_R3G3B2 = 27,
|
|
|
|
D3DFMT_A8 = 28,
|
|
|
|
D3DFMT_A8R3G3B2 = 29,
|
|
|
|
D3DFMT_X4R4G4B4 = 30,
|
|
|
|
D3DFMT_A2B10G10R10 = 31,
|
|
|
|
D3DFMT_A8B8G8R8 = 32,
|
|
|
|
D3DFMT_X8B8G8R8 = 33,
|
|
|
|
D3DFMT_G16R16 = 34,
|
|
|
|
D3DFMT_A2R10G10B10 = 35,
|
|
|
|
D3DFMT_A16B16G16R16 = 36,
|
|
|
|
|
|
|
|
D3DFMT_A8P8 = 40,
|
|
|
|
D3DFMT_P8 = 41,
|
|
|
|
|
|
|
|
D3DFMT_L8 = 50,
|
|
|
|
D3DFMT_A8L8 = 51,
|
|
|
|
D3DFMT_A4L4 = 52,
|
|
|
|
|
|
|
|
D3DFMT_V8U8 = 60,
|
|
|
|
D3DFMT_L6V5U5 = 61,
|
|
|
|
D3DFMT_X8L8V8U8 = 62,
|
|
|
|
D3DFMT_Q8W8V8U8 = 63,
|
|
|
|
D3DFMT_V16U16 = 64,
|
|
|
|
D3DFMT_A2W10V10U10 = 67,
|
|
|
|
|
|
|
|
D3DFMT_UYVY = MAKEFOURCC('U', 'Y', 'V', 'Y'),
|
|
|
|
D3DFMT_R8G8_B8G8 = MAKEFOURCC('R', 'G', 'B', 'G'),
|
|
|
|
D3DFMT_YUY2 = MAKEFOURCC('Y', 'U', 'Y', '2'),
|
|
|
|
D3DFMT_G8R8_G8B8 = MAKEFOURCC('G', 'R', 'G', 'B'),
|
|
|
|
D3DFMT_DXT1 = MAKEFOURCC('D', 'X', 'T', '1'),
|
|
|
|
D3DFMT_DXT2 = MAKEFOURCC('D', 'X', 'T', '2'),
|
|
|
|
D3DFMT_DXT3 = MAKEFOURCC('D', 'X', 'T', '3'),
|
|
|
|
D3DFMT_DXT4 = MAKEFOURCC('D', 'X', 'T', '4'),
|
|
|
|
D3DFMT_DXT5 = MAKEFOURCC('D', 'X', 'T', '5'),
|
|
|
|
|
|
|
|
D3DFMT_D16_LOCKABLE = 70,
|
|
|
|
D3DFMT_D32 = 71,
|
|
|
|
D3DFMT_D15S1 = 73,
|
|
|
|
D3DFMT_D24S8 = 75,
|
|
|
|
D3DFMT_D24X8 = 77,
|
|
|
|
D3DFMT_D24X4S4 = 79,
|
|
|
|
D3DFMT_D16 = 80,
|
|
|
|
|
|
|
|
D3DFMT_D32F_LOCKABLE = 82,
|
|
|
|
D3DFMT_D24FS8 = 83,
|
|
|
|
|
|
|
|
// d3d9ex only
|
|
|
|
/* Z-Stencil formats valid for CPU access */
|
|
|
|
D3DFMT_D32_LOCKABLE = 84,
|
|
|
|
D3DFMT_S8_LOCKABLE = 85,
|
|
|
|
|
|
|
|
D3DFMT_L16 = 81,
|
|
|
|
|
|
|
|
D3DFMT_VERTEXDATA =100,
|
|
|
|
D3DFMT_INDEX16 =101,
|
|
|
|
D3DFMT_INDEX32 =102,
|
|
|
|
|
|
|
|
D3DFMT_Q16W16V16U16 =110,
|
|
|
|
|
|
|
|
D3DFMT_MULTI2_ARGB8 = MAKEFOURCC('M','E','T','1'),
|
|
|
|
|
|
|
|
// Floating point surface formats
|
|
|
|
|
|
|
|
// s10e5 formats (16-bits per channel)
|
|
|
|
D3DFMT_R16F = 111,
|
|
|
|
D3DFMT_G16R16F = 112,
|
|
|
|
D3DFMT_A16B16G16R16F = 113,
|
|
|
|
|
|
|
|
// IEEE s23e8 formats (32-bits per channel)
|
|
|
|
D3DFMT_R32F = 114,
|
|
|
|
D3DFMT_G32R32F = 115,
|
|
|
|
D3DFMT_A32B32G32R32F = 116,
|
|
|
|
|
|
|
|
D3DFMT_CxV8U8 = 117,
|
|
|
|
|
|
|
|
// d3d9ex only
|
|
|
|
// Monochrome 1 bit per pixel format
|
|
|
|
D3DFMT_A1 = 118,
|
|
|
|
// 2.8 biased fixed point
|
|
|
|
D3DFMT_A2B10G10R10_XR_BIAS = 119,
|
|
|
|
// Binary format indicating that the data has no inherent type
|
|
|
|
D3DFMT_BINARYBUFFER = 199,
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// stolen from d3d8to9
|
|
|
|
static uint32
|
|
|
|
calculateTextureSize(uint32 width, uint32 height, uint32 depth, uint32 format)
|
|
|
|
{
|
|
|
|
#define D3DFMT_W11V11U10 65
|
|
|
|
switch(format){
|
|
|
|
default:
|
|
|
|
case D3DFMT_UNKNOWN:
|
|
|
|
return 0;
|
|
|
|
case D3DFMT_R3G3B2:
|
|
|
|
case D3DFMT_A8:
|
|
|
|
case D3DFMT_P8:
|
|
|
|
case D3DFMT_L8:
|
|
|
|
case D3DFMT_A4L4:
|
|
|
|
return width * height * depth;
|
|
|
|
case D3DFMT_R5G6B5:
|
|
|
|
case D3DFMT_X1R5G5B5:
|
|
|
|
case D3DFMT_A1R5G5B5:
|
|
|
|
case D3DFMT_A4R4G4B4:
|
|
|
|
case D3DFMT_A8R3G3B2:
|
|
|
|
case D3DFMT_X4R4G4B4:
|
|
|
|
case D3DFMT_A8P8:
|
|
|
|
case D3DFMT_A8L8:
|
|
|
|
case D3DFMT_V8U8:
|
|
|
|
case D3DFMT_L6V5U5:
|
|
|
|
case D3DFMT_D16_LOCKABLE:
|
|
|
|
case D3DFMT_D15S1:
|
|
|
|
case D3DFMT_D16:
|
|
|
|
case D3DFMT_UYVY:
|
|
|
|
case D3DFMT_YUY2:
|
|
|
|
return width * 2 * height * depth;
|
|
|
|
case D3DFMT_R8G8B8:
|
|
|
|
return width * 3 * height * depth;
|
|
|
|
case D3DFMT_A8R8G8B8:
|
|
|
|
case D3DFMT_X8R8G8B8:
|
|
|
|
case D3DFMT_A2B10G10R10:
|
|
|
|
case D3DFMT_A8B8G8R8:
|
|
|
|
case D3DFMT_X8B8G8R8:
|
|
|
|
case D3DFMT_G16R16:
|
|
|
|
case D3DFMT_X8L8V8U8:
|
|
|
|
case D3DFMT_Q8W8V8U8:
|
|
|
|
case D3DFMT_V16U16:
|
|
|
|
case D3DFMT_W11V11U10:
|
|
|
|
case D3DFMT_A2W10V10U10:
|
|
|
|
case D3DFMT_D32:
|
|
|
|
case D3DFMT_D24S8:
|
|
|
|
case D3DFMT_D24X8:
|
|
|
|
case D3DFMT_D24X4S4:
|
|
|
|
return width * 4 * height * depth;
|
|
|
|
case D3DFMT_DXT1:
|
|
|
|
assert(depth <= 1);
|
|
|
|
return ((width + 3) >> 2) * ((height + 3) >> 2) * 8;
|
|
|
|
case D3DFMT_DXT2:
|
|
|
|
case D3DFMT_DXT3:
|
|
|
|
case D3DFMT_DXT4:
|
|
|
|
case D3DFMT_DXT5:
|
|
|
|
assert(depth <= 1);
|
|
|
|
return ((width + 3) >> 2) * ((height + 3) >> 2) * 16;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int vertFormatMap[] = {
|
|
|
|
-1, VERT_FLOAT2, VERT_FLOAT3, -1, VERT_ARGB
|
|
|
|
};
|
|
|
|
|
|
|
|
void*
|
|
|
|
createIndexBuffer(uint32 length)
|
|
|
|
{
|
|
|
|
#ifdef RW_D3D9
|
|
|
|
IDirect3DIndexBuffer9 *ibuf;
|
2017-08-09 10:57:32 +02:00
|
|
|
d3ddevice->CreateIndexBuffer(length, D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_MANAGED, &ibuf, 0);
|
2016-06-24 15:24:58 +02:00
|
|
|
return ibuf;
|
|
|
|
#else
|
2017-08-25 14:06:53 +02:00
|
|
|
return rwNewT(uint8, length, MEMDUR_EVENT | ID_DRIVER);
|
2016-06-24 15:24:58 +02:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
uint16*
|
|
|
|
lockIndices(void *indexBuffer, uint32 offset, uint32 size, uint32 flags)
|
|
|
|
{
|
|
|
|
if(indexBuffer == nil)
|
|
|
|
return nil;
|
|
|
|
#ifdef RW_D3D9
|
|
|
|
uint16 *indices;
|
|
|
|
IDirect3DIndexBuffer9 *ibuf = (IDirect3DIndexBuffer9*)indexBuffer;
|
|
|
|
ibuf->Lock(offset, size, (void**)&indices, flags);
|
|
|
|
return indices;
|
|
|
|
#else
|
|
|
|
(void)offset;
|
|
|
|
(void)size;
|
|
|
|
(void)flags;
|
|
|
|
return (uint16*)indexBuffer;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
unlockIndices(void *indexBuffer)
|
|
|
|
{
|
|
|
|
if(indexBuffer == nil)
|
|
|
|
return;
|
|
|
|
#ifdef RW_D3D9
|
|
|
|
IDirect3DIndexBuffer9 *ibuf = (IDirect3DIndexBuffer9*)indexBuffer;
|
|
|
|
ibuf->Unlock();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void*
|
|
|
|
createVertexBuffer(uint32 length, uint32 fvf, int32 pool)
|
|
|
|
{
|
|
|
|
#ifdef RW_D3D9
|
|
|
|
IDirect3DVertexBuffer9 *vbuf;
|
2017-08-09 10:57:32 +02:00
|
|
|
d3ddevice->CreateVertexBuffer(length, D3DUSAGE_WRITEONLY, fvf, (D3DPOOL)pool, &vbuf, 0);
|
2016-06-24 15:24:58 +02:00
|
|
|
return vbuf;
|
|
|
|
#else
|
|
|
|
(void)fvf;
|
|
|
|
(void)pool;
|
2017-08-25 14:06:53 +02:00
|
|
|
return rwNewT(uint8, length, MEMDUR_EVENT | ID_DRIVER);
|
2016-06-24 15:24:58 +02:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8*
|
|
|
|
lockVertices(void *vertexBuffer, uint32 offset, uint32 size, uint32 flags)
|
|
|
|
{
|
|
|
|
if(vertexBuffer == nil)
|
|
|
|
return nil;
|
|
|
|
#ifdef RW_D3D9
|
|
|
|
uint8 *verts;
|
|
|
|
IDirect3DVertexBuffer9 *vertbuf = (IDirect3DVertexBuffer9*)vertexBuffer;
|
|
|
|
vertbuf->Lock(offset, size, (void**)&verts, flags);
|
|
|
|
return verts;
|
|
|
|
#else
|
|
|
|
(void)offset;
|
|
|
|
(void)size;
|
|
|
|
(void)flags;
|
|
|
|
return (uint8*)vertexBuffer;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
unlockVertices(void *vertexBuffer)
|
|
|
|
{
|
|
|
|
if(vertexBuffer == nil)
|
|
|
|
return;
|
|
|
|
#ifdef RW_D3D9
|
|
|
|
IDirect3DVertexBuffer9 *vertbuf = (IDirect3DVertexBuffer9*)vertexBuffer;
|
|
|
|
vertbuf->Unlock();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void*
|
|
|
|
createTexture(int32 width, int32 height, int32 numlevels, uint32 format)
|
|
|
|
{
|
|
|
|
#ifdef RW_D3D9
|
|
|
|
IDirect3DTexture9 *tex;
|
2017-08-09 10:57:32 +02:00
|
|
|
d3ddevice->CreateTexture(width, height, numlevels, 0,
|
2016-06-24 15:24:58 +02:00
|
|
|
(D3DFORMAT)format, D3DPOOL_MANAGED, &tex, nil);
|
|
|
|
return tex;
|
|
|
|
#else
|
|
|
|
int32 w = width;
|
|
|
|
int32 h = height;
|
|
|
|
int32 size = 0;
|
|
|
|
for(int32 i = 0; i < numlevels; i++){
|
|
|
|
size += calculateTextureSize(w, h, 1, format);
|
|
|
|
w /= 2;
|
|
|
|
if(w == 0) w = 1;
|
|
|
|
h /= 2;
|
|
|
|
if(h == 0) h = 1;
|
|
|
|
}
|
2017-08-25 14:06:53 +02:00
|
|
|
uint8 *data = (uint8*)rwNew(sizeof(RasterLevels)+sizeof(RasterLevels::Level)*(numlevels-1)+size,
|
|
|
|
MEMDUR_EVENT | ID_DRIVER);
|
2016-06-24 15:24:58 +02:00
|
|
|
RasterLevels *levels = (RasterLevels*)data;
|
|
|
|
data += sizeof(RasterLevels)+sizeof(RasterLevels::Level)*(numlevels-1);
|
|
|
|
levels->numlevels = numlevels;
|
|
|
|
levels->format = format;
|
|
|
|
w = width;
|
|
|
|
h = height;
|
|
|
|
for(int32 i = 0; i < numlevels; i++){
|
|
|
|
levels->levels[i].width = w;
|
|
|
|
levels->levels[i].height = h;
|
|
|
|
levels->levels[i].data = data;
|
|
|
|
levels->levels[i].size = calculateTextureSize(w, h, 1, format);
|
|
|
|
data += levels->levels[i].size;
|
|
|
|
w /= 2;
|
|
|
|
if(w == 0) w = 1;
|
|
|
|
h /= 2;
|
|
|
|
if(h == 0) h = 1;
|
|
|
|
}
|
|
|
|
return levels;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8*
|
|
|
|
lockTexture(void *texture, int32 level)
|
|
|
|
{
|
|
|
|
#ifdef RW_D3D9
|
|
|
|
IDirect3DTexture9 *tex = (IDirect3DTexture9*)texture;
|
|
|
|
D3DLOCKED_RECT lr;
|
|
|
|
tex->LockRect(level, &lr, 0, 0);
|
|
|
|
return (uint8*)lr.pBits;
|
|
|
|
#else
|
|
|
|
RasterLevels *levels = (RasterLevels*)texture;
|
|
|
|
return levels->levels[level].data;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
unlockTexture(void *texture, int32 level)
|
|
|
|
{
|
|
|
|
(void)texture;
|
|
|
|
(void)level;
|
|
|
|
#ifdef RW_D3D9
|
|
|
|
IDirect3DTexture9 *tex = (IDirect3DTexture9*)texture;
|
|
|
|
tex->UnlockRect(level);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
deleteObject(void *object)
|
|
|
|
{
|
|
|
|
if(object == nil)
|
|
|
|
return;
|
|
|
|
#ifdef RW_D3D9
|
|
|
|
IUnknown *unk = (IUnknown*)object;
|
|
|
|
unk->Release();
|
|
|
|
#else
|
2017-08-25 14:06:53 +02:00
|
|
|
rwFree(object);
|
2016-06-24 15:24:58 +02:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
// Native Raster
|
|
|
|
|
|
|
|
int32 nativeRasterOffset;
|
|
|
|
|
2016-06-27 21:59:35 +02:00
|
|
|
void
|
2016-06-24 15:24:58 +02:00
|
|
|
rasterCreate(Raster *raster)
|
|
|
|
{
|
|
|
|
static uint32 formatMap[] = {
|
|
|
|
0,
|
|
|
|
D3DFMT_A1R5G5B5,
|
|
|
|
D3DFMT_R5G6B5,
|
|
|
|
D3DFMT_A4R4G4B4,
|
|
|
|
D3DFMT_L8,
|
|
|
|
D3DFMT_A8R8G8B8,
|
|
|
|
D3DFMT_X8R8G8B8,
|
|
|
|
0, 0, 0,
|
|
|
|
D3DFMT_X1R5G5B5,
|
|
|
|
0, 0, 0, 0, 0
|
|
|
|
};
|
|
|
|
static bool32 alphaMap[] = {
|
|
|
|
0,
|
|
|
|
1,
|
|
|
|
0,
|
|
|
|
1,
|
|
|
|
0,
|
|
|
|
1,
|
|
|
|
0,
|
|
|
|
0, 0, 0,
|
|
|
|
0,
|
|
|
|
0, 0, 0, 0, 0
|
|
|
|
};
|
2017-12-31 10:50:49 +01:00
|
|
|
|
|
|
|
D3dRaster *natras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset);
|
2016-06-24 15:24:58 +02:00
|
|
|
uint32 format;
|
2017-12-31 10:50:49 +01:00
|
|
|
int32 levels;
|
|
|
|
|
|
|
|
// Dummy to use as subraster
|
|
|
|
if(raster->width == 0 || raster->height == 0){
|
|
|
|
raster->flags |= Raster::DONTALLOCATE;
|
|
|
|
raster->stride = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch(raster->type){
|
|
|
|
case Raster::NORMAL:
|
|
|
|
case Raster::TEXTURE:
|
|
|
|
if(raster->flags & Raster::DONTALLOCATE)
|
|
|
|
return;
|
|
|
|
if(raster->format & (Raster::PAL4 | Raster::PAL8)){
|
|
|
|
format = D3DFMT_P8;
|
|
|
|
natras->palette = (uint8*)rwNew(4*256, MEMDUR_EVENT | ID_DRIVER);
|
|
|
|
}else
|
|
|
|
format = formatMap[(raster->format >> 8) & 0xF];
|
|
|
|
natras->format = format;
|
|
|
|
natras->hasAlpha = alphaMap[(raster->format >> 8) & 0xF];
|
|
|
|
levels = Raster::calculateNumLevels(raster->width, raster->height);
|
|
|
|
natras->texture = createTexture(raster->width, raster->height,
|
|
|
|
raster->format & Raster::MIPMAP ? levels : 1,
|
|
|
|
format);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case Raster::ZBUFFER:
|
|
|
|
raster->flags |= Raster::DONTALLOCATE;
|
|
|
|
// TODO
|
|
|
|
break;
|
|
|
|
case Raster::CAMERA:
|
|
|
|
// TODO: get stuff from video mode
|
|
|
|
raster->flags |= Raster::DONTALLOCATE;
|
|
|
|
raster->originalWidth = raster->width;
|
|
|
|
raster->originalHeight = raster->height;
|
|
|
|
raster->stride = 0;
|
|
|
|
raster->pixels = nil;
|
|
|
|
break;
|
|
|
|
case Raster::CAMERATEXTURE:
|
|
|
|
raster->flags |= Raster::DONTALLOCATE;
|
|
|
|
// TODO
|
|
|
|
break;
|
|
|
|
}
|
2016-06-24 15:24:58 +02:00
|
|
|
}
|
|
|
|
|
2016-06-27 21:59:35 +02:00
|
|
|
uint8*
|
2016-06-24 15:24:58 +02:00
|
|
|
rasterLock(Raster *raster, int32 level)
|
|
|
|
{
|
|
|
|
D3dRaster *natras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset);
|
|
|
|
return lockTexture(natras->texture, level);
|
|
|
|
}
|
|
|
|
|
2016-06-27 21:59:35 +02:00
|
|
|
void
|
2016-06-24 15:24:58 +02:00
|
|
|
rasterUnlock(Raster *raster, int32 level)
|
|
|
|
{
|
|
|
|
D3dRaster *natras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset);
|
|
|
|
unlockTexture(natras->texture, level);
|
|
|
|
}
|
|
|
|
|
2016-06-27 21:59:35 +02:00
|
|
|
int32
|
2016-06-24 15:24:58 +02:00
|
|
|
rasterNumLevels(Raster *raster)
|
|
|
|
{
|
|
|
|
D3dRaster *natras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset);
|
|
|
|
#ifdef RW_D3D9
|
|
|
|
IDirect3DTexture9 *tex = (IDirect3DTexture9*)natras->texture;
|
|
|
|
return tex->GetLevelCount();
|
|
|
|
#else
|
|
|
|
RasterLevels *levels = (RasterLevels*)natras->texture;
|
|
|
|
return levels->numlevels;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2016-06-27 21:59:35 +02:00
|
|
|
void
|
2016-06-24 15:24:58 +02:00
|
|
|
rasterFromImage(Raster *raster, Image *image)
|
|
|
|
{
|
2017-11-15 19:23:50 +01:00
|
|
|
// Unpalettize image if necessary but don't change original
|
|
|
|
Image *truecolimg = nil;
|
|
|
|
if(image->depth <= 8 && !isP8supported){
|
|
|
|
truecolimg = Image::create(image->width, image->height, image->depth);
|
|
|
|
truecolimg->pixels = image->pixels;
|
|
|
|
truecolimg->palette = image->palette;
|
|
|
|
truecolimg->unindex();
|
|
|
|
image = truecolimg;
|
|
|
|
}
|
|
|
|
|
2016-06-24 15:24:58 +02:00
|
|
|
int32 format;
|
|
|
|
D3dRaster *natras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset);
|
|
|
|
switch(image->depth){
|
|
|
|
case 32:
|
|
|
|
format = image->hasAlpha() ? Raster::C8888 : Raster::C888;
|
|
|
|
break;
|
|
|
|
case 24:
|
|
|
|
format = Raster::C888;
|
|
|
|
break;
|
|
|
|
case 16:
|
|
|
|
format = Raster::C1555;
|
|
|
|
break;
|
|
|
|
case 8:
|
|
|
|
format = Raster::PAL8 | Raster::C8888;
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
format = Raster::PAL4 | Raster::C8888;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
2016-07-15 11:55:52 +02:00
|
|
|
format |= Raster::TEXTURE;
|
2016-06-24 15:24:58 +02:00
|
|
|
|
|
|
|
raster->type = format & 0x7;
|
|
|
|
raster->flags = format & 0xF8;
|
|
|
|
raster->format = format & 0xFF00;
|
|
|
|
rasterCreate(raster);
|
|
|
|
|
|
|
|
uint8 *in, *out;
|
|
|
|
int pallength = 0;
|
|
|
|
if(raster->format & Raster::PAL4)
|
|
|
|
pallength = 16;
|
|
|
|
else if(raster->format & Raster::PAL8)
|
|
|
|
pallength = 256;
|
|
|
|
if(pallength){
|
|
|
|
in = image->palette;
|
|
|
|
out = (uint8*)natras->palette;
|
|
|
|
for(int32 i = 0; i < pallength; i++){
|
2016-07-19 18:40:10 +02:00
|
|
|
out[0] = in[0];
|
2016-06-24 15:24:58 +02:00
|
|
|
out[1] = in[1];
|
2016-07-19 18:40:10 +02:00
|
|
|
out[2] = in[2];
|
2016-06-24 15:24:58 +02:00
|
|
|
out[3] = in[3];
|
|
|
|
in += 4;
|
|
|
|
out += 4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int32 inc = image->depth/8;
|
|
|
|
in = image->pixels;
|
|
|
|
out = raster->lock(0);
|
|
|
|
if(pallength)
|
|
|
|
memcpy(out, in, raster->width*raster->height);
|
|
|
|
else
|
|
|
|
// TODO: stride
|
|
|
|
for(int32 y = 0; y < image->height; y++)
|
|
|
|
for(int32 x = 0; x < image->width; x++)
|
|
|
|
switch(raster->format & 0xF00){
|
|
|
|
case Raster::C8888:
|
|
|
|
out[0] = in[2];
|
|
|
|
out[1] = in[1];
|
|
|
|
out[2] = in[0];
|
|
|
|
out[3] = in[3];
|
|
|
|
in += inc;
|
|
|
|
out += 4;
|
|
|
|
break;
|
|
|
|
case Raster::C888:
|
|
|
|
out[0] = in[2];
|
|
|
|
out[1] = in[1];
|
|
|
|
out[2] = in[0];
|
|
|
|
out[3] = 0xFF;
|
|
|
|
in += inc;
|
|
|
|
out += 4;
|
|
|
|
break;
|
|
|
|
case Raster::C1555:
|
|
|
|
out[0] = in[0];
|
|
|
|
out[1] = in[1];
|
|
|
|
in += 2;
|
|
|
|
out += 2;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
raster->unlock(0);
|
2017-11-15 19:23:50 +01:00
|
|
|
|
|
|
|
if(truecolimg)
|
|
|
|
truecolimg->destroy();
|
2016-06-24 15:24:58 +02:00
|
|
|
}
|
|
|
|
|
2016-07-15 11:55:52 +02:00
|
|
|
Image*
|
|
|
|
rasterToImage(Raster *raster)
|
|
|
|
{
|
|
|
|
int32 depth;
|
|
|
|
Image *image;
|
|
|
|
D3dRaster *natras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset);
|
2017-09-16 23:19:54 +02:00
|
|
|
if(natras->customFormat){
|
2016-07-19 23:37:37 +02:00
|
|
|
image = Image::create(raster->width, raster->height, 32);
|
|
|
|
image->allocate();
|
|
|
|
uint8 *pix = raster->lock(0);
|
|
|
|
switch(natras->format){
|
|
|
|
case D3DFMT_DXT1:
|
|
|
|
image->setPixelsDXT(1, pix);
|
|
|
|
if((raster->format & 0xF00) == Raster::C555)
|
|
|
|
image->removeMask();
|
|
|
|
break;
|
|
|
|
case D3DFMT_DXT3:
|
|
|
|
image->setPixelsDXT(3, pix);
|
|
|
|
break;
|
|
|
|
case D3DFMT_DXT5:
|
|
|
|
image->setPixelsDXT(5, pix);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
raster->unlock(0);
|
|
|
|
image->destroy();
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
raster->unlock(0);
|
|
|
|
return image;
|
|
|
|
}
|
2016-07-15 11:55:52 +02:00
|
|
|
switch(raster->format & 0xF00){
|
|
|
|
case Raster::C1555:
|
|
|
|
depth = 16;
|
|
|
|
break;
|
|
|
|
case Raster::C8888:
|
|
|
|
depth = 32;
|
|
|
|
break;
|
|
|
|
case Raster::C888:
|
|
|
|
depth = 24;
|
|
|
|
break;
|
|
|
|
case Raster::C555:
|
|
|
|
depth = 16;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
case Raster::C565:
|
|
|
|
case Raster::C4444:
|
|
|
|
case Raster::LUM8:
|
|
|
|
assert(0 && "unsupported raster format");
|
|
|
|
}
|
|
|
|
int32 pallength = 0;
|
|
|
|
if((raster->format & Raster::PAL4) == Raster::PAL4){
|
|
|
|
depth = 4;
|
|
|
|
pallength = 16;
|
2016-07-19 18:40:10 +02:00
|
|
|
}else if((raster->format & Raster::PAL8) == Raster::PAL8){
|
2016-07-15 11:55:52 +02:00
|
|
|
depth = 8;
|
|
|
|
pallength = 256;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8 *in, *out;
|
|
|
|
image = Image::create(raster->width, raster->height, depth);
|
|
|
|
image->allocate();
|
|
|
|
|
|
|
|
if(pallength){
|
|
|
|
out = image->palette;
|
|
|
|
in = (uint8*)natras->palette;
|
|
|
|
for(int32 i = 0; i < pallength; i++){
|
2016-07-19 18:40:10 +02:00
|
|
|
out[0] = in[0];
|
2016-07-15 11:55:52 +02:00
|
|
|
out[1] = in[1];
|
2016-07-19 18:40:10 +02:00
|
|
|
out[2] = in[2];
|
2016-07-15 11:55:52 +02:00
|
|
|
out[3] = in[3];
|
|
|
|
in += 4;
|
|
|
|
out += 4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
out = image->pixels;
|
|
|
|
in = raster->lock(0);
|
|
|
|
if(pallength)
|
|
|
|
memcpy(out, in, raster->width*raster->height);
|
|
|
|
else
|
|
|
|
// TODO: stride
|
|
|
|
for(int32 y = 0; y < image->height; y++)
|
|
|
|
for(int32 x = 0; x < image->width; x++)
|
|
|
|
switch(raster->format & 0xF00){
|
|
|
|
case Raster::C8888:
|
|
|
|
out[0] = in[2];
|
|
|
|
out[1] = in[1];
|
|
|
|
out[2] = in[0];
|
|
|
|
out[3] = in[3];
|
|
|
|
in += 4;
|
|
|
|
out += 4;
|
|
|
|
break;
|
|
|
|
case Raster::C888:
|
|
|
|
out[0] = in[2];
|
|
|
|
out[1] = in[1];
|
|
|
|
out[2] = in[0];
|
|
|
|
in += 4;
|
|
|
|
out += 3;
|
|
|
|
break;
|
|
|
|
case Raster::C1555:
|
|
|
|
out[0] = in[0];
|
|
|
|
out[1] = in[1];
|
|
|
|
in += 2;
|
|
|
|
out += 2;
|
|
|
|
break;
|
|
|
|
case Raster::C555:
|
|
|
|
out[0] = in[0];
|
|
|
|
out[1] = in[1] | 0x80;
|
|
|
|
in += 2;
|
|
|
|
out += 2;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
raster->unlock(0);
|
|
|
|
|
|
|
|
return image;
|
|
|
|
}
|
|
|
|
|
2016-06-24 15:24:58 +02:00
|
|
|
int32
|
|
|
|
getLevelSize(Raster *raster, int32 level)
|
|
|
|
{
|
|
|
|
D3dRaster *ras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset);
|
|
|
|
#ifdef RW_D3D9
|
|
|
|
IDirect3DTexture9 *tex = (IDirect3DTexture9*)ras->texture;
|
|
|
|
D3DSURFACE_DESC desc;
|
|
|
|
tex->GetLevelDesc(level, &desc);
|
|
|
|
return calculateTextureSize(desc.Width, desc.Height, 1, desc.Format);
|
|
|
|
#else
|
|
|
|
RasterLevels *levels = (RasterLevels*)ras->texture;
|
|
|
|
return levels->levels[level].size;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
allocateDXT(Raster *raster, int32 dxt, int32 numLevels, bool32 hasAlpha)
|
|
|
|
{
|
|
|
|
static uint32 dxtMap[] = {
|
|
|
|
0x31545844, // DXT1
|
|
|
|
0x32545844, // DXT2
|
|
|
|
0x33545844, // DXT3
|
|
|
|
0x34545844, // DXT4
|
|
|
|
0x35545844, // DXT5
|
|
|
|
};
|
|
|
|
D3dRaster *ras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset);
|
|
|
|
ras->format = dxtMap[dxt-1];
|
|
|
|
ras->hasAlpha = hasAlpha;
|
|
|
|
ras->texture = createTexture(raster->width, raster->height,
|
|
|
|
raster->format & Raster::MIPMAP ? numLevels : 1,
|
|
|
|
ras->format);
|
2017-12-31 10:50:49 +01:00
|
|
|
raster->flags &= ~Raster::DONTALLOCATE;
|
2016-06-24 15:24:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
setPalette(Raster *raster, void *palette, int32 size)
|
|
|
|
{
|
|
|
|
D3dRaster *ras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset);
|
|
|
|
memcpy(ras->palette, palette, 4*size);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
setTexels(Raster *raster, void *texels, int32 level)
|
|
|
|
{
|
|
|
|
uint8 *dst = raster->lock(level);
|
|
|
|
memcpy(dst, texels, getLevelSize(raster, level));
|
|
|
|
raster->unlock(level);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void*
|
|
|
|
createNativeRaster(void *object, int32 offset, int32)
|
|
|
|
{
|
|
|
|
D3dRaster *raster = PLUGINOFFSET(D3dRaster, object, offset);
|
|
|
|
raster->texture = nil;
|
|
|
|
raster->palette = nil;
|
|
|
|
raster->format = 0;
|
|
|
|
raster->hasAlpha = 0;
|
|
|
|
raster->customFormat = 0;
|
|
|
|
return object;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void*
|
|
|
|
destroyNativeRaster(void *object, int32 offset, int32)
|
|
|
|
{
|
|
|
|
// TODO:
|
|
|
|
(void)offset;
|
|
|
|
return object;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void*
|
|
|
|
copyNativeRaster(void *dst, void *, int32 offset, int32)
|
|
|
|
{
|
|
|
|
D3dRaster *raster = PLUGINOFFSET(D3dRaster, dst, offset);
|
|
|
|
raster->texture = nil;
|
|
|
|
raster->palette = nil;
|
|
|
|
raster->format = 0;
|
|
|
|
raster->hasAlpha = 0;
|
|
|
|
raster->customFormat = 0;
|
|
|
|
return dst;
|
|
|
|
}
|
|
|
|
|
2016-06-25 23:14:18 +02:00
|
|
|
void
|
|
|
|
registerNativeRaster(void)
|
|
|
|
{
|
|
|
|
nativeRasterOffset = Raster::registerPlugin(sizeof(D3dRaster),
|
|
|
|
ID_RASTERD3D9,
|
2016-06-29 12:53:02 +02:00
|
|
|
createNativeRaster,
|
|
|
|
destroyNativeRaster,
|
|
|
|
copyNativeRaster);
|
2016-06-25 23:14:18 +02:00
|
|
|
}
|
|
|
|
|
2016-06-24 15:24:58 +02:00
|
|
|
}
|
|
|
|
}
|