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

Last change on this file since 2183 was 2183, checked in by sam, 7 years ago

build: fix the WTFPL site URL in all code comments.

  • Property svn:keywords set to Id
File size: 5.7 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://www.wtfpl.net/ 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_texture;
49#elif defined _XBOX
50    D3DTexture *m_texture;
51#else
52    GLuint m_texture;
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 D3DFORMAT const d3d_formats[] =
75    {
76        /* Unknown */
77        D3DFMT_UNKNOWN,
78
79        /* R8G8B8 */
80#   if defined USE_D3D9
81        D3DFMT_R8G8B8,
82#   else
83        D3DFMT_UNKNOWN,
84#   endif
85
86        /* A8R8G8B8 */
87#   if defined USE_D3D9
88        D3DFMT_A8R8G8B8,
89#   else
90        /* By default the X360 will swizzle the texture. Ask for linear. */
91        D3DFMT_LIN_A8R8G8B8,
92#   endif
93    };
94
95    D3DFORMAT d3d_format = GET_CLAMPED(d3d_formats, format);
96#   if defined USE_D3D9
97    int d3d_usage = D3DUSAGE_DYNAMIC;
98#   else
99    int d3d_usage = D3DUSAGE_WRITEONLY;
100#   endif
101
102    g_d3ddevice->CreateTexture(m_data->m_size.x, m_data->m_size.y, 1,
103                               d3d_usage, d3d_format,
104                               D3DPOOL_DEFAULT, &m_data->m_texture, NULL);
105#else
106    static struct
107    {
108        GLint internal_format;
109        GLenum format, type;
110    }
111    const gl_formats[] =
112    {
113        /* Unknown */
114        { 0, 0, 0 },
115
116        /* R8G8B8 */
117        { GL_RGB, GL_RGB, GL_UNSIGNED_BYTE },
118
119        /* A8R8G8B8 */
120#if __CELLOS_LV2__
121        { GL_ARGB_SCE, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV },
122#elif defined __native_client__ || defined HAVE_GLES_2X
123        { GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE },
124#else
125        /* Seems efficient for little endian textures */
126        { GL_RGBA, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV },
127#endif
128
129        /* A8B8G8R8 */
130#if __CELLOS_LV2__
131        { GL_ARGB_SCE, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV },
132#elif defined __native_client__ || defined HAVE_GLES_2X
133        /* FIXME: if GL_RGBA is not available, we should advertise
134         * this format as "not available" on this platform. */
135        { GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE },
136#else
137        /* Seems efficient for little endian textures */
138        { GL_RGBA, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV },
139#endif
140    };
141
142    m_data->m_internal_format = GET_CLAMPED(gl_formats, format).internal_format;
143    m_data->m_gl_format = GET_CLAMPED(gl_formats, format).format;
144    m_data->m_gl_type = GET_CLAMPED(gl_formats, format).type;
145
146    glGenTextures(1, &m_data->m_texture);
147    glBindTexture(GL_TEXTURE_2D, m_data->m_texture);
148
149#   if defined __CELLOS_LV2__
150    /* We need this hint because by default the storage type is
151     * GL_TEXTURE_SWIZZLED_GPU_SCE. */
152    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_ALLOCATION_HINT_SCE,
153                    GL_TEXTURE_TILED_GPU_SCE);
154#   endif
155    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
156    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
157#endif
158}
159
160ShaderTexture Texture::GetTexture() const
161{
162    ShaderTexture ret;
163#if defined USE_D3D9 || defined _XBOX
164    ret.m_flags = (uint64_t)(uintptr_t)m_data->m_texture;
165#else
166    ret.m_flags = m_data->m_texture;
167#endif
168    return ret;
169}
170
171void Texture::Bind()
172{
173#if defined _XBOX || defined USE_D3D9
174    g_d3ddevice->SetTexture(0, m_data->m_texture);
175#else
176#   if !defined HAVE_GLES_2X
177    glEnable(GL_TEXTURE_2D);
178#   endif
179    glBindTexture(GL_TEXTURE_2D, m_data->m_texture);
180#endif
181}
182
183void Texture::SetData(void *data)
184{
185#if defined _XBOX || defined USE_D3D9
186    D3DLOCKED_RECT rect;
187#   if defined USE_D3D9
188    m_data->m_texture->LockRect(0, &rect, NULL, D3DLOCK_DISCARD);
189#   else
190    m_data->m_texture->LockRect(0, &rect, NULL, 0);
191#   endif
192
193    memcpy(rect.pBits, data, rect.Pitch * m_data->m_size.y);
194
195    m_data->m_texture->UnlockRect(0);
196
197#else
198    glTexImage2D(GL_TEXTURE_2D, 0, m_data->m_internal_format,
199                 m_data->m_size.x, m_data->m_size.y, 0,
200                 m_data->m_gl_format, m_data->m_gl_type, data);
201#endif
202}
203
204void Texture::SetSubData(ivec2 origin, ivec2 size, void *data)
205{
206#if defined _XBOX || defined USE_D3D9
207    D3DLOCKED_RECT rect;
208    m_data->m_texture->LockRect(0, &rect, NULL, 0);
209
210    for (int j = 0; j < size.y; j++)
211    {
212        uint8_t *dst = (uint8_t *)rect.pBits + (origin.y + j) * rect.Pitch;
213        /* FIXME: the source or destination pitch isn't necessarily 4! */
214        uint8_t *src = (uint8_t *)data + j * size.x * 4;
215        memcpy(dst, src, size.x * 4);
216    }
217
218    m_data->m_texture->UnlockRect(0);
219
220#else
221    glTexSubImage2D(GL_TEXTURE_2D, 0, origin.x, origin.y, size.x, size.y,
222                    m_data->m_gl_format, m_data->m_gl_type, data);
223#endif
224}
225
226Texture::~Texture()
227{
228#if defined USE_D3D9 || defined _XBOX
229    m_data->m_texture->Release();
230#else
231    glDeleteTextures(1, &m_data->m_texture);
232#endif
233
234    delete m_data;
235}
236
237} /* namespace lol */
238
Note: See TracBrowser for help on using the repository browser.