ソースを参照

gpu: allow to specify the pixel format when creating a texture; the

internal format is then automatically deduced. Only a few 8-bit RGB
or RGBA formats are supported for now.
legacy
Sam Hocevar sam 12年前
コミット
26c945a31f
4個のファイルの変更113行の追加124行の削除
  1. +77
    -26
      src/gpu/texture.cpp
  2. +18
    -1
      src/gpu/texture.h
  3. +16
    -96
      src/tileset.cpp
  4. +2
    -1
      tutorial/11_fractal.cpp

+ 77
- 26
src/gpu/texture.cpp ファイルの表示

@@ -42,6 +42,7 @@ class TextureData
friend class Texture;

ivec2 m_size;
PixelFormat m_format;

#if defined USE_D3D9
IDirect3DTexture9 *m_tex;
@@ -49,6 +50,8 @@ class TextureData
D3DTexture *m_tex;
#else
GLuint m_texid;
GLint m_internal_format;
GLenum m_gl_format, m_gl_type;
#endif
};

@@ -57,37 +60,85 @@ class TextureData
// -----------------
//

/* FIXME: this is all hardcoded over the place */
#if __CELLOS_LV2__
static GLint const INTERNAL_FORMAT = GL_ARGB_SCE;
static GLenum const TEXTURE_FORMAT = GL_BGRA;
static GLenum const TEXTURE_TYPE = GL_UNSIGNED_INT_8_8_8_8_REV;
#elif defined __native_client__ || defined HAVE_GLES_2X
static GLint const INTERNAL_FORMAT = GL_RGBA;
static GLenum const TEXTURE_FORMAT = GL_RGBA;
static GLenum const TEXTURE_TYPE = GL_UNSIGNED_BYTE;
#elif !defined USE_D3D9 && !defined _XBOX
/* Seems efficient for little endian textures */
static GLint const INTERNAL_FORMAT = GL_RGBA;
static GLenum const TEXTURE_FORMAT = GL_BGRA;
static GLenum const TEXTURE_TYPE = GL_UNSIGNED_INT_8_8_8_8_REV;
#endif
#define GET_CLAMPED(array, index) \
array[std::max(0, std::min((int)(index), \
(int)sizeof(array) / (int)sizeof(*array)))]

Texture::Texture(ivec2 size)
Texture::Texture(ivec2 size, PixelFormat format)
: m_data(new TextureData)
{
m_data->m_size = size;
m_data->m_format = format;

#if defined USE_D3D9 || defined _XBOX
static int const d3d_formats[] =
{
/* Unknown */
D3DFMT_UNKNOWN,

/* R8G8B8 */
D3DFMT_R8G8B8,

/* A8R8G8B8 */
# if defined USE_D3D9
D3DFMT_A8R8G8B8,
# else
/* By default the X360 will swizzle the texture. Ask for linear. */
D3DFMT_LIN_A8R8G8B8,
# endif
};

int d3d_format = GET_CLAMPED(d3d_formats, format);
# if defined USE_D3D9
int d3d_usage = D3DUSAGE_DYNAMIC;
# else
int d3d_usage = D3DUSAGE_WRITEONLY;
# endif

#if defined USE_D3D9
g_d3ddevice->CreateTexture(m_data->m_size.x, m_data->m_size.y, 1,
D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8,
D3DPOOL_DEFAULT, &m_data->m_tex, NULL);
#elif defined _XBOX
/* By default the X360 will swizzle the texture. Ask for linear. */
g_d3ddevice->CreateTexture(m_data->m_size.x, m_data->m_size.y, 1,
D3DUSAGE_WRITEONLY, D3DFMT_LIN_A8R8G8B8,
d3d_usage, d3d_format,
D3DPOOL_DEFAULT, &m_data->m_tex, NULL);
#else
static struct
{
GLint internal_format;
GLenum format, type;
}
const gl_formats[] =
{
/* Unknown */
{ 0, 0, 0 },

/* R8G8B8 */
{ GL_RGB, GL_RGB, GL_UNSIGNED_BYTE },

/* A8R8G8B8 */
#if __CELLOS_LV2__
{ GL_ARGB_SCE, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV },
#elif defined __native_client__ || defined HAVE_GLES_2X
{ GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE },
#else
/* Seems efficient for little endian textures */
{ GL_RGBA, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV },
#endif

/* A8B8G8R8 */
#if __CELLOS_LV2__
{ GL_ARGB_SCE, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV },
#elif defined __native_client__ || defined HAVE_GLES_2X
/* FIXME: if GL_RGBA is not available, we should advertise
* this format as "not available" on this platform. */
{ GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE },
#else
/* Seems efficient for little endian textures */
{ GL_RGBA, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV },
#endif
};

m_data->m_internal_format = GET_CLAMPED(gl_formats, format).internal_format;
m_data->m_gl_format = GET_CLAMPED(gl_formats, format).format;
m_data->m_gl_type = GET_CLAMPED(gl_formats, format).type;

glGenTextures(1, &m_data->m_texid);
glBindTexture(GL_TEXTURE_2D, m_data->m_texid);

@@ -129,9 +180,9 @@ void Texture::SetData(void *data)
m_data->m_tex->UnlockRect(0);

#else
glTexImage2D(GL_TEXTURE_2D, 0, INTERNAL_FORMAT,
glTexImage2D(GL_TEXTURE_2D, 0, m_data->m_internal_format,
m_data->m_size.x, m_data->m_size.y, 0,
TEXTURE_FORMAT, TEXTURE_TYPE, data);
m_data->m_gl_format, m_data->m_gl_type, data);
#endif
}

@@ -153,7 +204,7 @@ void Texture::SetSubData(ivec2 origin, ivec2 size, void *data)

#else
glTexSubImage2D(GL_TEXTURE_2D, 0, origin.x, origin.y, size.x, size.y,
TEXTURE_FORMAT, TEXTURE_TYPE, data);
m_data->m_gl_format, m_data->m_gl_type, data);
#endif
}



+ 18
- 1
src/gpu/texture.h ファイルの表示

@@ -19,10 +19,27 @@
namespace lol
{

struct PixelFormat
{
/* XXX: make sure to update texture.cpp when this changes */
enum Value
{
Unknown = 0,
R8G8B8,
A8R8G8B8,
A8B8G8R8,
}
m_value;

inline PixelFormat() : m_value(Unknown) {}
inline PixelFormat(Value v) : m_value(v) {}
inline operator Value() { return m_value; }
};

class Texture
{
public:
Texture(ivec2 size);
Texture(ivec2 size, PixelFormat format);
~Texture();

void Bind();


+ 16
- 96
src/tileset.cpp ファイルの表示

@@ -56,13 +56,7 @@ private:
float tx, ty;

Image *img;
#if defined USE_D3D9
IDirect3DTexture9 *m_tex;
#elif defined _XBOX
D3DTexture *m_tex;
#else
GLuint m_tex;
#endif
Texture *m_texture;
};

/*
@@ -77,7 +71,7 @@ TileSet::TileSet(char const *path, ivec2 size, ivec2 count)
sprintf(data->name, "<tileset> %s", path);

data->tiles = NULL;
data->m_tex = 0;
data->m_texture = 0;
data->img = new Image(path);
data->isize = data->img->GetSize();

@@ -119,46 +113,24 @@ void TileSet::TickDraw(float seconds)
if (data->img)
delete data->img;
else
#if defined USE_D3D9 || defined _XBOX
/* FIXME: is it really the correct call? */
data->m_tex->Release();
#else
glDeleteTextures(1, &data->m_tex);
#endif
delete data->m_texture;
}
else if (data->img)
{
#if defined USE_D3D9 || defined _XBOX
D3DFORMAT format;
#else
GLuint format;
#endif
int planes;
PixelFormat format = PixelFormat::Unknown;

switch (data->img->GetFormat())
{
case Image::FORMAT_RGB:
#if defined USE_D3D9
format = D3DFMT_R8G8B8;
#elif defined _XBOX
format = D3DFMT_LIN_A8R8G8B8; /* FIXME */
#else
format = GL_RGB;
#endif
planes = 3;
break;
format = PixelFormat::R8G8B8;
planes = 3;
break;
case Image::FORMAT_RGBA:
default:
#if defined USE_D3D9
format = D3DFMT_A8R8G8B8;
#elif defined _XBOX
/* By default the X360 will swizzle the texture. Ask for linear. */
format = D3DFMT_LIN_A8R8G8B8;
#else
format = GL_RGBA;
#endif
planes = 4;
break;
format = PixelFormat::A8R8G8B8;
planes = 4;
break;
}

int w = PotUp(data->isize.x);
@@ -175,41 +147,8 @@ void TileSet::TickDraw(float seconds)
pixels = tmp;
}

#if defined USE_D3D9 || defined _XBOX
D3DLOCKED_RECT rect;
HRESULT hr;
# if defined USE_D3D9
hr = g_d3ddevice->CreateTexture(w, h, 1, D3DUSAGE_DYNAMIC, format,
D3DPOOL_DEFAULT, &data->m_tex, NULL);
# elif defined _XBOX
hr = g_d3ddevice->CreateTexture(w, h, 1, D3DUSAGE_WRITEONLY, format,
D3DPOOL_DEFAULT, &data->m_tex, NULL);
# endif
if (FAILED(hr))
Abort();
# if defined USE_D3D9
hr = data->m_tex->LockRect(0, &rect, NULL, D3DLOCK_DISCARD);
# else
hr = data->m_tex->LockRect(0, &rect, NULL, 0);
# endif
if (FAILED(hr))
Abort();
for (int j = 0; j < h; j++)
memcpy((uint8_t *)rect.pBits + j * rect.Pitch, pixels + w * j * 4, w * 4);
hr = data->m_tex->UnlockRect(0);
if (FAILED(hr))
Abort();
#else
glGenTextures(1, &data->m_tex);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, data->m_tex);

glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0,
format, GL_UNSIGNED_BYTE, pixels);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
#endif
data->m_texture = new Texture(ivec2(w, h), format);
data->m_texture->SetData(pixels);

if (pixels != data->img->GetData())
free(pixels);
@@ -237,32 +176,13 @@ ivec2 TileSet::GetSize(int tileid) const

void TileSet::Bind()
{
if (!data->img && data->m_tex)
{
#if defined USE_D3D9 || defined _XBOX
HRESULT hr = g_d3ddevice->SetTexture(0, data->m_tex);
if (FAILED(hr))
Abort();
#else
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, data->m_tex);
#endif
}
if (!data->img && data->m_texture)
data->m_texture->Bind();
}

void TileSet::Unbind()
{
if (!data->img && data->m_tex)
{
#if defined USE_D3D9 || defined _XBOX
HRESULT hr = g_d3ddevice->SetTexture(0, NULL);
if (FAILED(hr))
Abort();
#else
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, 0);
#endif
}
;
}

void TileSet::BlitTile(uint32_t id, vec3 pos, int o, vec2 scale,
@@ -287,7 +207,7 @@ void TileSet::BlitTile(uint32_t id, vec3 pos, int o, vec2 scale,
dtx = -dtx;
}

if (!data->img && data->m_tex)
if (!data->img && data->m_texture)
{
float tmp[10];



+ 2
- 1
tutorial/11_fractal.cpp ファイルの表示

@@ -445,7 +445,8 @@ public:
{
/* Create a texture of half the width and twice the height
* so that we can upload four different subimages each frame. */
m_texture = new Texture(ivec2(m_size.x / 2, m_size.y * 2));
m_texture = new Texture(ivec2(m_size.x / 2, m_size.y * 2),
PixelFormat::A8B8G8R8);

/* Ensure the texture data is complete at least once, otherwise
* uploading subimages will not work. */


読み込み中…
キャンセル
保存