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

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

gpu: fix compilation on GL ES platforms.

  • Property svn:keywords set to Id
File size: 6.2 KB
Line 
1//
2// Lol Engine
3//
4// Copyright: (c) 2010-2013 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    int m_bytes_per_elem;
57};
58
59//
60// The Texture class
61// -----------------
62//
63
64#define GET_CLAMPED(array, index) \
65    array[std::max(0, std::min((int)(index), \
66                   (int)sizeof(array) / (int)sizeof(*array)))]
67
68Texture::Texture(ivec2 size, PixelFormat format)
69  : m_data(new TextureData)
70{
71    m_data->m_size = size;
72    m_data->m_format = format;
73
74#if defined USE_D3D9 || defined _XBOX
75    static struct
76    {
77        D3DFORMAT format;
78        int bytes;
79    }
80    const d3d_formats[] =
81    {
82        /* Unknown */
83        { D3DFMT_UNKNOWN, 0 },
84
85        /* R8G8B8 */
86#   if defined USE_D3D9
87        { D3DFMT_R8G8B8, 3 },
88#   else
89        { D3DFMT_UNKNOWN, 0 },
90#   endif
91
92        /* A8R8G8B8 */
93#   if defined USE_D3D9
94        { D3DFMT_A8R8G8B8, 4 },
95#   else
96        /* By default the X360 will swizzle the texture. Ask for linear. */
97        { D3DFMT_LIN_A8R8G8B8, 4 },
98#   endif
99
100        /* Y8 */
101#   if defined USE_D3D9
102        { D3DFMT_L8, 1 },
103#   else
104        /* By default the X360 will swizzle the texture. Ask for linear. */
105        { D3DFMT_LIN_L8, 1 },
106#   endif
107    };
108
109    D3DFORMAT d3d_format = GET_CLAMPED(d3d_formats, format).format;
110#   if defined USE_D3D9
111    int d3d_usage = D3DUSAGE_DYNAMIC;
112#   else
113    int d3d_usage = D3DUSAGE_WRITEONLY;
114#   endif
115
116    g_d3ddevice->CreateTexture(m_data->m_size.x, m_data->m_size.y, 1,
117                               d3d_usage, d3d_format,
118                               D3DPOOL_DEFAULT, &m_data->m_texture, NULL);
119    m_data->m_bytes_per_elem = GET_CLAMPED(d3d_formats, format).bytes;
120#else
121    static struct
122    {
123        GLint internal_format;
124        GLenum format, type;
125        int bytes;
126    }
127    const gl_formats[] =
128    {
129        { 0, 0, 0, 0 }, /* Unknown */
130        { GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE, 3 }, /* RGB_8 */
131
132#if __CELLOS_LV2__
133        { GL_ARGB_SCE, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, 4 },
134        { GL_ARGB_SCE, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, 4 },
135        { GL_LUMINANCE8, GL_LUMINANCE, GL_UNSIGNED_BYTE, 1 },
136#elif defined __native_client__ || defined HAVE_GLES_2X
137        { GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, 4 },
138        /* FIXME: if GL_RGBA is not available, we should advertise
139         * this format as "not available" on this platform. */
140        { GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, 4 },
141        { GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE, 1 },
142#else
143        /* Seems efficient for little endian textures */
144        { GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, 4 }, /* ARGB_8 */
145        { GL_RGBA8, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 4 }, /* ABGR_8 */
146        { GL_R8, GL_RED, GL_UNSIGNED_BYTE, 1 }, /* A8 */
147#endif
148    };
149
150    m_data->m_internal_format = GET_CLAMPED(gl_formats, format).internal_format;
151    m_data->m_gl_format = GET_CLAMPED(gl_formats, format).format;
152    m_data->m_gl_type = GET_CLAMPED(gl_formats, format).type;
153    m_data->m_bytes_per_elem = GET_CLAMPED(gl_formats, format).bytes;
154
155    glGenTextures(1, &m_data->m_texture);
156    glBindTexture(GL_TEXTURE_2D, m_data->m_texture);
157
158#   if defined __CELLOS_LV2__
159    /* We need this hint because by default the storage type is
160     * GL_TEXTURE_SWIZZLED_GPU_SCE. */
161    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_ALLOCATION_HINT_SCE,
162                    GL_TEXTURE_TILED_GPU_SCE);
163#   endif
164    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
165    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
166#endif
167}
168
169ShaderTexture Texture::GetTexture() const
170{
171    ShaderTexture ret;
172#if defined USE_D3D9 || defined _XBOX
173    ret.m_flags = (uint64_t)(uintptr_t)m_data->m_texture;
174#else
175    ret.m_flags = m_data->m_texture;
176#endif
177    return ret;
178}
179
180void Texture::Bind()
181{
182#if defined _XBOX || defined USE_D3D9
183    g_d3ddevice->SetTexture(0, m_data->m_texture);
184#else
185#   if !defined HAVE_GLES_2X
186    glEnable(GL_TEXTURE_2D);
187#   endif
188    glBindTexture(GL_TEXTURE_2D, m_data->m_texture);
189#endif
190}
191
192void Texture::SetData(void *data)
193{
194#if defined _XBOX || defined USE_D3D9
195    D3DLOCKED_RECT rect;
196#   if defined USE_D3D9
197    m_data->m_texture->LockRect(0, &rect, NULL, D3DLOCK_DISCARD);
198#   else
199    m_data->m_texture->LockRect(0, &rect, NULL, 0);
200#   endif
201
202    memcpy(rect.pBits, data, rect.Pitch * m_data->m_size.y);
203
204    m_data->m_texture->UnlockRect(0);
205
206#else
207    glTexImage2D(GL_TEXTURE_2D, 0, m_data->m_internal_format,
208                 m_data->m_size.x, m_data->m_size.y, 0,
209                 m_data->m_gl_format, m_data->m_gl_type, data);
210#endif
211}
212
213void Texture::SetSubData(ivec2 origin, ivec2 size, void *data)
214{
215#if defined _XBOX || defined USE_D3D9
216    D3DLOCKED_RECT rect;
217    m_data->m_texture->LockRect(0, &rect, NULL, 0);
218
219    int stride = size.x * m_data->m_bytes_per_elem;
220    for (int j = 0; j < size.y; j++)
221    {
222        uint8_t *dst = (uint8_t *)rect.pBits + (origin.y + j) * rect.Pitch;
223        uint8_t *src = (uint8_t *)data + j * stride;
224        memcpy(dst, src, stride);
225    }
226
227    m_data->m_texture->UnlockRect(0);
228
229#else
230    glTexSubImage2D(GL_TEXTURE_2D, 0, origin.x, origin.y, size.x, size.y,
231                    m_data->m_gl_format, m_data->m_gl_type, data);
232#endif
233}
234
235Texture::~Texture()
236{
237#if defined USE_D3D9 || defined _XBOX
238    m_data->m_texture->Release();
239#else
240    glDeleteTextures(1, &m_data->m_texture);
241#endif
242
243    delete m_data;
244}
245
246} /* namespace lol */
247
Note: See TracBrowser for help on using the repository browser.