Browse Source

gpu: put the texture creation code in its own class; for now a lot of things are

hardcoded and only the fractal demo uses it, but everything will eventually switch.
legacy
Sam Hocevar sam 12 years ago
parent
commit
b9aba5d27a
7 changed files with 239 additions and 97 deletions
  1. +1
    -0
      src/Makefile.am
  2. +1
    -0
      src/core.h
  3. +176
    -0
      src/gpu/texture.cpp
  4. +39
    -0
      src/gpu/texture.h
  5. +2
    -0
      src/lolcore.vcxproj
  6. +6
    -0
      src/lolcore.vcxproj.filters
  7. +14
    -97
      tutorial/11_fractal.cpp

+ 1
- 0
src/Makefile.am View File

@@ -50,6 +50,7 @@ liblol_a_SOURCES = \
gpu/indexbuffer.cpp gpu/indexbuffer.h \
gpu/vertexbuffer.cpp gpu/vertexbuffer.h \
gpu/framebuffer.cpp gpu/framebuffer.h \
gpu/texture.cpp gpu/texture.h \
\
gpu/defaultmaterial.lolfx \
gpu/tile.lolfx \


+ 1
- 0
src/core.h View File

@@ -115,6 +115,7 @@ static inline int isnan(float f)
#include "layer.h"
#include "gpu/lolfx.h"
#include "gpu/shader.h"
#include "gpu/texture.h"
#include "gpu/indexbuffer.h"
#include "gpu/vertexbuffer.h"
#include "gpu/framebuffer.h"


+ 176
- 0
src/gpu/texture.cpp View File

@@ -0,0 +1,176 @@
//
// Lol Engine
//
// Copyright: (c) 2010-2012 Sam Hocevar <sam@hocevar.net>
// This program is free software; you can redistribute it and/or
// modify it under the terms of the Do What The Fuck You Want To
// Public License, Version 2, as published by Sam Hocevar. See
// http://sam.zoy.org/projects/COPYING.WTFPL for more details.
//

#if defined HAVE_CONFIG_H
# include "config.h"
#endif

#include "core.h"
#include "lolgl.h"

#if defined _WIN32 && defined USE_D3D9
# define FAR
# define NEAR
# include <d3d9.h>
#endif

using namespace std;

#if defined USE_D3D9
extern IDirect3DDevice9 *g_d3ddevice;
#elif defined _XBOX
extern D3DDevice *g_d3ddevice;
#endif

namespace lol
{

//
// The TextureData class
// ---------------------
//

class TextureData
{
friend class Texture;

ivec2 m_size;

#if defined USE_D3D9
IDirect3DTexture9 *m_tex;
#elif defined _XBOX
D3DTexture *m_tex;
#else
GLuint m_texid;
#endif
};

//
// The Texture class
// -----------------
//

/* 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;
#else
/* 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

Texture::Texture(ivec2 size)
: m_data(new TextureData)
{
m_data->m_size = size;

#if defined USE_D3D9
g_d3ddevice->CreateTexture(m_data->m_size.x, m_data->m_size.y, 1,
D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8,
D3DPOOL_SYSTEMMEM, &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,
D3DPOOL_DEFAULT, &m_tex, NULL);
#else
glGenTextures(1, &m_data->m_texid);
glBindTexture(GL_TEXTURE_2D, m_data->m_texid);

# if defined __CELLOS_LV2__
/* We need this hint because by default the storage type is
* GL_TEXTURE_SWIZZLED_GPU_SCE. */
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_ALLOCATION_HINT_SCE,
GL_TEXTURE_TILED_GPU_SCE);
# endif
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
#endif
}

void Texture::Bind()
{
#if defined _XBOX || defined USE_D3D9
g_d3ddevice->SetTexture(0, m_data->m_tex);
#else
# if !defined HAVE_GLES_2X
glEnable(GL_TEXTURE_2D);
# endif
glBindTexture(GL_TEXTURE_2D, m_data->m_texid);
#endif
}

void Texture::SetData(void *data)
{
#if defined _XBOX || defined USE_D3D9
D3DLOCKED_RECT rect;
# if defined _XBOX
m_data->m_tex->LockRect(0, &rect, NULL, D3DLOCK_NOOVERWRITE);
# else
m_data->m_tex->LockRect(0, &rect, NULL,
D3DLOCK_DISCARD | D3DLOCK_NOOVERWRITE);
# endif
memcpy(rect.pBits, data, rect.Pitch * rect.Height);

m_data->m_tex->UnlockRect(0);

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

void Texture::SetSubData(ivec2 origin, ivec2 size, void *data)
{
#if defined _XBOX || defined USE_D3D9
D3DLOCKED_RECT rect;
# if defined _XBOX
m_data->m_tex->LockRect(0, &rect, NULL, D3DLOCK_NOOVERWRITE);
# else
m_data->m_tex->LockRect(0, &rect, NULL,
D3DLOCK_DISCARD | D3DLOCK_NOOVERWRITE);
# endif
for (int j = 0; j < size.y; j++)
{
uint8_t *dst = (uint8_t *)rect.pBits + (origin.y + j) * rect.Pitch;
/* FIXME: the source or destination pitch isn't necessarily 4! */
uint8_t *src = (uint8_t *)data + j * size.y * 4;
memcpy(dst, src, size.y * 4);
}

m_data->m_tex->UnlockRect(0);

#else
glTexSubImage2D(GL_TEXTURE_2D, 0, origin.x, origin.y, size.x, size.y,
TEXTURE_FORMAT, TEXTURE_TYPE, data);
#endif
}

Texture::~Texture()
{
#if defined USE_D3D9 || defined _XBOX
m_data->m_tex->Release();
#else
glDeleteTextures(1, &m_data->m_texid);
#endif

delete m_data;
}

} /* namespace lol */


+ 39
- 0
src/gpu/texture.h View File

@@ -0,0 +1,39 @@
//
// Lol Engine
//
// Copyright: (c) 2010-2012 Sam Hocevar <sam@hocevar.net>
// This program is free software; you can redistribute it and/or
// modify it under the terms of the Do What The Fuck You Want To
// Public License, Version 2, as published by Sam Hocevar. See
// http://sam.zoy.org/projects/COPYING.WTFPL for more details.
//

//
// The Texture class
// -----------------
//

#if !defined __LOL_TEXTURE_H__
#define __LOL_TEXTURE_H__

namespace lol
{

class Texture
{
public:
Texture(ivec2 size);
~Texture();

void Bind();
void SetData(void *data);
void SetSubData(ivec2 origin, ivec2 size, void *data);

private:
class TextureData *m_data;
};

} /* namespace lol */

#endif // __LOL_TEXTURE_H__


+ 2
- 0
src/lolcore.vcxproj View File

@@ -254,6 +254,7 @@
<ClCompile Include="gpu\lolfx-compiler.cpp" />
<ClCompile Include="gpu\lolfx.cpp" />
<ClCompile Include="gpu\shader.cpp" />
<ClCompile Include="gpu\texture.cpp" />
<ClCompile Include="gpu\vertexbuffer.cpp" />
<ClCompile Include="gradient.cpp" />
<ClCompile Include="hash.cpp" />
@@ -567,6 +568,7 @@
<ClInclude Include="gpu\lolfx-compiler.h" />
<ClInclude Include="gpu\lolfx.h" />
<ClInclude Include="gpu\shader.h" />
<ClInclude Include="gpu\texture.h" />
<ClInclude Include="gpu\vertexbuffer.h" />
<ClInclude Include="gradient.h" />
<ClInclude Include="hash.h" />


+ 6
- 0
src/lolcore.vcxproj.filters View File

@@ -97,6 +97,9 @@
<ClCompile Include="gpu\shader.cpp">
<Filter>src\gpu</Filter>
</ClCompile>
<ClCompile Include="gpu\texture.cpp">
<Filter>src\gpu</Filter>
</ClCompile>
<ClCompile Include="gpu\vertexbuffer.cpp">
<Filter>src\gpu</Filter>
</ClCompile>
@@ -669,6 +672,9 @@
<ClInclude Include="gpu\shader.h">
<Filter>src\gpu</Filter>
</ClInclude>
<ClInclude Include="gpu\texture.h">
<Filter>src\gpu</Filter>
</ClInclude>
<ClInclude Include="gpu\vertexbuffer.h">
<Filter>src\gpu</Filter>
</ClInclude>


+ 14
- 97
tutorial/11_fractal.cpp View File

@@ -15,41 +15,12 @@
#include <cstring>

#include "core.h"
#include "lolgl.h"
#include "loldebug.h"

using namespace lol;

#if defined _WIN32
# include <direct.h>
# if defined USE_D3D9
# define FAR
# define NEAR
# include <d3d9.h>
# endif
#endif

extern char const *lolfx_11_fractal;

#if defined USE_D3D9
extern IDirect3DDevice9 *g_d3ddevice;
#elif defined _XBOX
extern D3DDevice *g_d3ddevice;
#elif __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;
#else
/* 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

class Fractal : public WorldEntity
{
public:
@@ -467,32 +438,13 @@ public:

if (!m_ready)
{
#if !defined _XBOX && !defined USE_D3D9
/* Create a texture of half the width and twice the height
* so that we can upload four different subimages each frame. */
glGenTextures(1, &m_texid);
glBindTexture(GL_TEXTURE_2D, m_texid);
glTexImage2D(GL_TEXTURE_2D, 0, INTERNAL_FORMAT,
m_size.x / 2, m_size.y * 2, 0,
TEXTURE_FORMAT, TEXTURE_TYPE, &m_pixels[0]);
# if defined __CELLOS_LV2__
/* We need this hint because by default the storage type is
* GL_TEXTURE_SWIZZLED_GPU_SCE. */
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_ALLOCATION_HINT_SCE,
GL_TEXTURE_TILED_GPU_SCE);
# endif
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
#elif defined _XBOX
/* By default the X360 will swizzle the texture. Ask for linear. */
g_d3ddevice->CreateTexture(m_size.x / 2, m_size.y * 2, 1,
D3DUSAGE_WRITEONLY, D3DFMT_LIN_A8R8G8B8,
D3DPOOL_DEFAULT, &m_tex, NULL);
#else
g_d3ddevice->CreateTexture(m_size.x / 2, m_size.y * 2, 1,
D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8,
D3DPOOL_SYSTEMMEM, &m_tex, NULL);
#endif
m_texture = new Texture(ivec2(m_size.x / 2, m_size.y * 2));

/* Ensure the texture data is complete at least once, otherwise
* uploading subimages will not work. */
m_texture->SetData(&m_pixels[0]);

m_shader = Shader::Create(lolfx_11_fractal);

@@ -520,14 +472,7 @@ public:
m_ready = true;
}

#if defined _XBOX || defined USE_D3D9

#else
# if !defined HAVE_GLES_2X
glEnable(GL_TEXTURE_2D);
# endif
glBindTexture(GL_TEXTURE_2D, m_texid);
#endif
m_texture->Bind();

if (m_dirty[m_frame])
{
@@ -536,32 +481,14 @@ public:

m_dirty[m_frame]--;

#if defined _XBOX || defined USE_D3D9
D3DLOCKED_RECT rect;
# if defined _XBOX
m_tex->LockRect(0, &rect, NULL, D3DLOCK_NOOVERWRITE);
# else
m_tex->LockRect(0, &rect, NULL,
D3DLOCK_DISCARD | D3DLOCK_NOOVERWRITE);
# endif
for (int j = 0; j < m_size.y * 2; j++)
{
u8vec4 *line = (u8vec4 *)rect.pBits + j * rect.Pitch / 4;
for (int i = 0; i < m_size.x / 2; i++)
line[i] = m_pixels[m_size.x / 2 * j + i];
}
m_tex->UnlockRect(0);
#elif defined __CELLOS_LV2__
#if defined __CELLOS_LV2__
/* glTexSubImage2D is extremely slow on the PS3, to the point
* that uploading the whole texture is 40 times faster. */
glTexImage2D(GL_TEXTURE_2D, 0, INTERNAL_FORMAT,
m_size.x / 2, m_size.y * 2, 0,
TEXTURE_FORMAT, TEXTURE_TYPE, &m_pixels[0]);
m_texture->SetData(&m_pixels[0]);
#else
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, m_frame * m_size.y / 2,
m_size.x / 2, m_size.y / 2,
TEXTURE_FORMAT, TEXTURE_TYPE,
&m_pixels[m_size.x * m_size.y / 4 * m_frame]);
m_texture->SetSubData(ivec2(0, m_frame * m_size.y / 2),
m_size / 2,
&m_pixels[m_size.x * m_size.y / 4 * m_frame]);
#endif
}

@@ -572,12 +499,7 @@ public:
m_vdecl->Bind();
m_vdecl->SetStream(m_vbo, m_vertexattrib);
m_vdecl->SetStream(m_tbo, m_texattrib);
#if defined _XBOX || defined USE_D3D9
g_d3ddevice->SetTexture(0, m_tex);
g_d3ddevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);
#elif !defined __CELLOS_LV2__ && !defined __ANDROID__
#else
#endif
m_texture->Bind();
m_vdecl->DrawElements(MeshPrimitive::Triangles, 0, 6);
m_vdecl->Unbind();
}
@@ -599,13 +521,8 @@ private:

VertexDeclaration *m_vdecl;
VertexBuffer *m_vbo, *m_tbo;
#if defined USE_D3D9
IDirect3DTexture9 *m_tex;
#elif defined _XBOX
D3DTexture *m_tex;
#else
GLuint m_texid;
#endif
Texture *m_texture;

int m_frame, m_slices, m_dirty[4];
bool m_ready, m_drag;



Loading…
Cancel
Save