source: trunk/src/gpu/texture.cpp @ 1992

Last change on this file since 1992 was 1992, checked in by sam, 10 years ago

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.

  • Property svn:keywords set to Id
File size: 5.4 KB
Line 
1//
2// Lol Engine
3//
4// Copyright: (c) 2010-2012 Sam Hocevar <sam@hocevar.net>
5//   This program is free software; you can redistribute it and/or
6//   modify it under the terms of the Do What The Fuck You Want To
7//   Public License, Version 2, as published by Sam Hocevar. See
8//   http://sam.zoy.org/projects/COPYING.WTFPL for more details.
9//
10
11#if defined HAVE_CONFIG_H
12#   include "config.h"
13#endif
14
15#include "core.h"
16#include "lolgl.h"
17
18#if defined _WIN32 && defined USE_D3D9
19#   define FAR
20#   define NEAR
21#   include <d3d9.h>
22#endif
23
24using namespace std;
25
26#if defined USE_D3D9
27extern IDirect3DDevice9 *g_d3ddevice;
28#elif defined _XBOX
29extern D3DDevice *g_d3ddevice;
30#endif
31
32namespace lol
33{
34
35//
36// The TextureData class
37// ---------------------
38//
39
40class TextureData
41{
42    friend class Texture;
43
44    ivec2 m_size;
45    PixelFormat m_format;
46
47#if defined USE_D3D9
48    IDirect3DTexture9 *m_tex;
49#elif defined _XBOX
50    D3DTexture *m_tex;
51#else
52    GLuint m_texid;
53    GLint m_internal_format;
54    GLenum m_gl_format, m_gl_type;
55#endif
56};
57
58//
59// The Texture class
60// -----------------
61//
62
63#define GET_CLAMPED(array, index) \
64    array[std::max(0, std::min((int)(index), \
65                   (int)sizeof(array) / (int)sizeof(*array)))]
66
67Texture::Texture(ivec2 size, PixelFormat format)
68  : m_data(new TextureData)
69{
70    m_data->m_size = size;
71    m_data->m_format = format;
72
73#if defined USE_D3D9 || defined _XBOX
74    static int const d3d_formats[] =
75    {
76        /* Unknown */
77        D3DFMT_UNKNOWN,
78
79        /* R8G8B8 */
80        D3DFMT_R8G8B8,
81
82        /* A8R8G8B8 */
83#   if defined USE_D3D9
84        D3DFMT_A8R8G8B8,
85#   else
86        /* By default the X360 will swizzle the texture. Ask for linear. */
87        D3DFMT_LIN_A8R8G8B8,
88#   endif
89    };
90
91    int d3d_format = GET_CLAMPED(d3d_formats, format);
92#   if defined USE_D3D9
93    int d3d_usage = D3DUSAGE_DYNAMIC;
94#   else
95    int d3d_usage = D3DUSAGE_WRITEONLY;
96#   endif
97
98    g_d3ddevice->CreateTexture(m_data->m_size.x, m_data->m_size.y, 1,
99                               d3d_usage, d3d_format,
100                               D3DPOOL_DEFAULT, &m_data->m_tex, NULL);
101#else
102    static struct
103    {
104        GLint internal_format;
105        GLenum format, type;
106    }
107    const gl_formats[] =
108    {
109        /* Unknown */
110        { 0, 0, 0 },
111
112        /* R8G8B8 */
113        { GL_RGB, GL_RGB, GL_UNSIGNED_BYTE },
114
115        /* A8R8G8B8 */
116#if __CELLOS_LV2__
117        { GL_ARGB_SCE, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV },
118#elif defined __native_client__ || defined HAVE_GLES_2X
119        { GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE },
120#else
121        /* Seems efficient for little endian textures */
122        { GL_RGBA, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV },
123#endif
124
125        /* A8B8G8R8 */
126#if __CELLOS_LV2__
127        { GL_ARGB_SCE, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV },
128#elif defined __native_client__ || defined HAVE_GLES_2X
129        /* FIXME: if GL_RGBA is not available, we should advertise
130         * this format as "not available" on this platform. */
131        { GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE },
132#else
133        /* Seems efficient for little endian textures */
134        { GL_RGBA, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV },
135#endif
136    };
137
138    m_data->m_internal_format = GET_CLAMPED(gl_formats, format).internal_format;
139    m_data->m_gl_format = GET_CLAMPED(gl_formats, format).format;
140    m_data->m_gl_type = GET_CLAMPED(gl_formats, format).type;
141
142    glGenTextures(1, &m_data->m_texid);
143    glBindTexture(GL_TEXTURE_2D, m_data->m_texid);
144
145#   if defined __CELLOS_LV2__
146    /* We need this hint because by default the storage type is
147     * GL_TEXTURE_SWIZZLED_GPU_SCE. */
148    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_ALLOCATION_HINT_SCE,
149                    GL_TEXTURE_TILED_GPU_SCE);
150#   endif
151    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
152    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
153#endif
154}
155
156void Texture::Bind()
157{
158#if defined _XBOX || defined USE_D3D9
159    g_d3ddevice->SetTexture(0, m_data->m_tex);
160#else
161#   if !defined HAVE_GLES_2X
162    glEnable(GL_TEXTURE_2D);
163#   endif
164    glBindTexture(GL_TEXTURE_2D, m_data->m_texid);
165#endif
166}
167
168void Texture::SetData(void *data)
169{
170#if defined _XBOX || defined USE_D3D9
171    D3DLOCKED_RECT rect;
172#   if defined USE_D3D9
173    m_data->m_tex->LockRect(0, &rect, NULL, D3DLOCK_DISCARD);
174#   else
175    m_data->m_tex->LockRect(0, &rect, NULL, 0);
176#   endif
177
178    memcpy(rect.pBits, data, rect.Pitch * m_data->m_size.y);
179
180    m_data->m_tex->UnlockRect(0);
181
182#else
183    glTexImage2D(GL_TEXTURE_2D, 0, m_data->m_internal_format,
184                 m_data->m_size.x, m_data->m_size.y, 0,
185                 m_data->m_gl_format, m_data->m_gl_type, data);
186#endif
187}
188
189void Texture::SetSubData(ivec2 origin, ivec2 size, void *data)
190{
191#if defined _XBOX || defined USE_D3D9
192    D3DLOCKED_RECT rect;
193    m_data->m_tex->LockRect(0, &rect, NULL, 0);
194
195    for (int j = 0; j < size.y; j++)
196    {
197        uint8_t *dst = (uint8_t *)rect.pBits + (origin.y + j) * rect.Pitch;
198        /* FIXME: the source or destination pitch isn't necessarily 4! */
199        uint8_t *src = (uint8_t *)data + j * size.x * 4;
200        memcpy(dst, src, size.x * 4);
201    }
202
203    m_data->m_tex->UnlockRect(0);
204
205#else
206    glTexSubImage2D(GL_TEXTURE_2D, 0, origin.x, origin.y, size.x, size.y,
207                    m_data->m_gl_format, m_data->m_gl_type, data);
208#endif
209}
210
211Texture::~Texture()
212{
213#if defined USE_D3D9 || defined _XBOX
214    m_data->m_tex->Release();
215#else
216    glDeleteTextures(1, &m_data->m_texid);
217#endif
218
219    delete m_data;
220}
221
222} /* namespace lol */
223
Note: See TracBrowser for help on using the repository browser.