~ppsspp/ppsspp/ppsspp_1.3.0

« back to all changes in this revision

Viewing changes to ext/native/thin3d/thin3d.cpp

  • Committer: Sérgio Benjamim
  • Date: 2017-01-02 00:12:05 UTC
  • Revision ID: sergio_br2@yahoo.com.br-20170102001205-cxbta9za203nmjwm
1.3.0 source (from ppsspp_1.3.0-r160.p5.l1762.a165.t83~56~ubuntu16.04.1.tar.xz).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include <string.h>
 
2
#include <thin3d/thin3d.h>
 
3
 
 
4
#include "base/logging.h"
 
5
#include "image/zim_load.h"
 
6
#include "image/png_load.h"
 
7
#include "file/vfs.h"
 
8
#include "ext/jpge/jpgd.h"
 
9
 
 
10
// ================================== PIXEL/FRAGMENT SHADERS
 
11
 
 
12
// The Vulkan ones can be re-used with modern GL later if desired, as they're just GLSL.
 
13
 
 
14
static const char * const glsl_fsTexCol =
 
15
"#ifdef GL_ES\n"
 
16
"precision lowp float;\n"
 
17
"#endif\n"
 
18
"varying vec4 oColor0;\n"
 
19
"varying vec2 oTexCoord0;\n"
 
20
"uniform sampler2D Sampler0;\n"
 
21
"void main() { gl_FragColor = texture2D(Sampler0, oTexCoord0) * oColor0; }\n";
 
22
 
 
23
static const char * const hlslFsTexCol =
 
24
"struct PS_INPUT { float4 color : COLOR0; float2 uv : TEXCOORD0; };\n"
 
25
"sampler2D Sampler0 : register(s0);\n"
 
26
"float4 main(PS_INPUT input) : COLOR0 {\n"
 
27
"  return input.color * tex2D(Sampler0, input.uv);\n"
 
28
"}\n";
 
29
 
 
30
static const char * const vulkan_fsTexCol =
 
31
"#version 140\n"
 
32
"#extension GL_ARB_separate_shader_objects : enable\n"
 
33
"#extension GL_ARB_shading_language_420pack : enable\n"
 
34
"layout(location = 0) in vec4 oColor0;\n"
 
35
"layout(location = 1) in vec2 oTexCoord0;\n"
 
36
"layout(location = 0) out vec4 fragColor0\n;"
 
37
"layout(set = 0, binding = 1) uniform sampler2D Sampler0;\n"
 
38
"void main() { fragColor0 = texture(Sampler0, oTexCoord0) * oColor0; }\n";
 
39
 
 
40
static const char * const glsl_fsCol =
 
41
"#ifdef GL_ES\n"
 
42
"precision lowp float;\n"
 
43
"#endif\n"
 
44
"varying vec4 oColor0;\n"
 
45
"void main() { gl_FragColor = oColor0; }\n";
 
46
 
 
47
static const char * const hlslFsCol =
 
48
"struct PS_INPUT { float4 color : COLOR0; };\n"
 
49
"float4 main(PS_INPUT input) : COLOR0 {\n"
 
50
"  return input.color;\n"
 
51
"}\n";
 
52
 
 
53
static const char * const vulkan_fsCol =
 
54
"#version 140\n"
 
55
"#extension GL_ARB_separate_shader_objects : enable\n"
 
56
"#extension GL_ARB_shading_language_420pack : enable\n"
 
57
"layout(location = 0) in vec4 oColor0;\n"
 
58
"layout(location = 0) out vec4 fragColor0\n;"
 
59
"void main() { fragColor0 = oColor0; }\n";
 
60
 
 
61
 
 
62
 
 
63
// ================================== VERTEX SHADERS
 
64
 
 
65
static const char * const glsl_vsCol =
 
66
"attribute vec3 Position;\n"
 
67
"attribute vec4 Color0;\n"
 
68
"varying vec4 oColor0;\n"
 
69
"uniform mat4 WorldViewProj;\n"
 
70
"void main() {\n"
 
71
"  gl_Position = WorldViewProj * vec4(Position, 1.0);\n"
 
72
"  oColor0 = Color0;\n"
 
73
"}";
 
74
 
 
75
static const char * const hlslVsCol =
 
76
"struct VS_INPUT { float3 Position : POSITION; float4 Color0 : COLOR0; };\n"
 
77
"struct VS_OUTPUT { float4 Position : POSITION; float4 Color0 : COLOR0; };\n"
 
78
"float4x4 WorldViewProj;\n"
 
79
"VS_OUTPUT main(VS_INPUT input) {\n"
 
80
"  VS_OUTPUT output;\n"
 
81
"  output.Position = mul(float4(input.Position, 1.0), WorldViewProj);\n"
 
82
"  output.Color0 = input.Color0;\n"
 
83
"  return output;\n"
 
84
"}\n";
 
85
 
 
86
static const char * const vulkan_vsCol =
 
87
"#version 400\n"
 
88
"#extension GL_ARB_separate_shader_objects : enable\n"
 
89
"#extension GL_ARB_shading_language_420pack : enable\n"
 
90
"layout (std140, set = 0, binding = 0) uniform bufferVals {\n"
 
91
"    mat4 WorldViewProj;\n"
 
92
"} myBufferVals;\n"
 
93
"layout (location = 0) in vec4 pos;\n"
 
94
"layout (location = 1) in vec4 inColor;\n"
 
95
"layout (location = 0) out vec4 outColor;\n"
 
96
"out gl_PerVertex { vec4 gl_Position; };\n"
 
97
"void main() {\n"
 
98
"   outColor = inColor;\n"
 
99
"   gl_Position = myBufferVals.WorldViewProj * pos;\n"
 
100
"}\n";
 
101
 
 
102
 
 
103
static const char * const glsl_vsTexCol =
 
104
"attribute vec3 Position;\n"
 
105
"attribute vec4 Color0;\n"
 
106
"attribute vec2 TexCoord0;\n"
 
107
"varying vec4 oColor0;\n"
 
108
"varying vec2 oTexCoord0;\n"
 
109
"uniform mat4 WorldViewProj;\n"
 
110
"void main() {\n"
 
111
"  gl_Position = WorldViewProj * vec4(Position, 1.0);\n"
 
112
"  oColor0 = Color0;\n"
 
113
"  oTexCoord0 = TexCoord0;\n"
 
114
"}\n";
 
115
 
 
116
static const char * const hlslVsTexCol =
 
117
"struct VS_INPUT { float3 Position : POSITION; float2 Texcoord0 : TEXCOORD0; float4 Color0 : COLOR0; };\n"
 
118
"struct VS_OUTPUT { float4 Position : POSITION; float2 Texcoord0 : TEXCOORD0; float4 Color0 : COLOR0; };\n"
 
119
"float4x4 WorldViewProj;\n"
 
120
"VS_OUTPUT main(VS_INPUT input) {\n"
 
121
"  VS_OUTPUT output;\n"
 
122
"  output.Position = mul(float4(input.Position, 1.0), WorldViewProj);\n"
 
123
"  output.Texcoord0 = input.Texcoord0;\n"
 
124
"  output.Color0 = input.Color0;\n"
 
125
"  return output;\n"
 
126
"}\n";
 
127
 
 
128
static const char * const vulkan_vsTexCol =
 
129
"#version 400\n"
 
130
"#extension GL_ARB_separate_shader_objects : enable\n"
 
131
"#extension GL_ARB_shading_language_420pack : enable\n"
 
132
"layout (std140, set = 0, binding = 0) uniform bufferVals {\n"
 
133
"    mat4 WorldViewProj;\n"
 
134
"} myBufferVals;\n"
 
135
"layout (location = 0) in vec4 pos;\n"
 
136
"layout (location = 1) in vec4 inColor;\n"
 
137
"layout (location = 2) in vec2 inTexCoord;\n"
 
138
"layout (location = 0) out vec4 outColor;\n"
 
139
"layout (location = 1) out vec2 outTexCoord;\n"
 
140
"out gl_PerVertex { vec4 gl_Position; };\n"
 
141
"void main() {\n"
 
142
"   outColor = inColor;\n"
 
143
"   outTexCoord = inTexCoord;\n"
 
144
"   gl_Position = myBufferVals.WorldViewProj * pos;\n"
 
145
"}\n";
 
146
 
 
147
 
 
148
void Thin3DContext::CreatePresets() {
 
149
        // Build prebuilt objects
 
150
        T3DBlendStateDesc off = { false };
 
151
        T3DBlendStateDesc additive = { true, T3DBlendEquation::ADD, T3DBlendFactor::ONE, T3DBlendFactor::ONE, T3DBlendEquation::ADD, T3DBlendFactor::ONE, T3DBlendFactor::ZERO };
 
152
        T3DBlendStateDesc standard_alpha = { true, T3DBlendEquation::ADD, T3DBlendFactor::SRC_ALPHA, T3DBlendFactor::ONE_MINUS_SRC_ALPHA, T3DBlendEquation::ADD, T3DBlendFactor::ONE, T3DBlendFactor::ZERO };
 
153
        T3DBlendStateDesc premul_alpha = { true, T3DBlendEquation::ADD, T3DBlendFactor::ONE, T3DBlendFactor::ONE_MINUS_SRC_ALPHA, T3DBlendEquation::ADD, T3DBlendFactor::ONE, T3DBlendFactor::ZERO };
 
154
 
 
155
        bsPresets_[BS_OFF] = CreateBlendState(off);
 
156
        bsPresets_[BS_ADDITIVE] = CreateBlendState(additive);
 
157
        bsPresets_[BS_STANDARD_ALPHA] = CreateBlendState(standard_alpha);
 
158
        bsPresets_[BS_PREMUL_ALPHA] = CreateBlendState(premul_alpha);
 
159
 
 
160
        T3DSamplerStateDesc nearest = { CLAMP, CLAMP, NEAREST, NEAREST, NEAREST };
 
161
        T3DSamplerStateDesc linear = { CLAMP, CLAMP, LINEAR, LINEAR, NEAREST };
 
162
 
 
163
        sampsPresets_[SAMPS_NEAREST] = CreateSamplerState(nearest);
 
164
        sampsPresets_[SAMPS_LINEAR] = CreateSamplerState(linear);
 
165
 
 
166
        vsPresets_[VS_TEXTURE_COLOR_2D] = CreateVertexShader(glsl_vsTexCol, hlslVsTexCol, vulkan_vsTexCol);
 
167
        vsPresets_[VS_COLOR_2D] = CreateVertexShader(glsl_vsCol, hlslVsCol, vulkan_vsCol);
 
168
 
 
169
        fsPresets_[FS_TEXTURE_COLOR_2D] = CreateFragmentShader(glsl_fsTexCol, hlslFsTexCol, vulkan_fsTexCol);
 
170
        fsPresets_[FS_COLOR_2D] = CreateFragmentShader(glsl_fsCol, hlslFsCol, vulkan_fsCol);
 
171
 
 
172
        ssPresets_[SS_TEXTURE_COLOR_2D] = CreateShaderSet(vsPresets_[VS_TEXTURE_COLOR_2D], fsPresets_[FS_TEXTURE_COLOR_2D]);
 
173
        ssPresets_[SS_COLOR_2D] = CreateShaderSet(vsPresets_[VS_COLOR_2D], fsPresets_[FS_COLOR_2D]);
 
174
}
 
175
 
 
176
Thin3DContext::~Thin3DContext() {
 
177
        for (int i = 0; i < VS_MAX_PRESET; i++) {
 
178
                if (vsPresets_[i]) {
 
179
                        vsPresets_[i]->Release();
 
180
                }
 
181
        }
 
182
        for (int i = 0; i < FS_MAX_PRESET; i++) {
 
183
                if (fsPresets_[i]) {
 
184
                        fsPresets_[i]->Release();
 
185
                }
 
186
        }
 
187
        for (int i = 0; i < BS_MAX_PRESET; i++) {
 
188
                if (bsPresets_[i]) {
 
189
                        bsPresets_[i]->Release();
 
190
                }
 
191
        }
 
192
        for (int i = 0; i < SS_MAX_PRESET; i++) {
 
193
                if (ssPresets_[i]) {
 
194
                        ssPresets_[i]->Release();
 
195
                }
 
196
        }
 
197
        for (int i = 0; i < SAMPS_MAX_PRESET; i++) {
 
198
                if (sampsPresets_[i]) {
 
199
                        sampsPresets_[i]->Release();
 
200
                }
 
201
        }
 
202
}
 
203
 
 
204
static T3DImageFormat ZimToT3DFormat(int zim) {
 
205
        switch (zim) {
 
206
        case ZIM_ETC1: return T3DImageFormat::ETC1;
 
207
        case ZIM_RGBA8888: return T3DImageFormat::RGBA8888;
 
208
        case ZIM_LUMINANCE: return T3DImageFormat::LUMINANCE;
 
209
        default: return T3DImageFormat::RGBA8888;
 
210
        }
 
211
}
 
212
 
 
213
static T3DImageType DetectImageFileType(const uint8_t *data, size_t size) {
 
214
        if (!memcmp(data, "ZIMG", 4)) {
 
215
                return ZIM;
 
216
        } else if (!memcmp(data, "\x89\x50\x4E\x47", 4)) {
 
217
                return PNG;
 
218
        } else if (!memcmp(data, "\xff\xd8\xff\xe0", 4)) {
 
219
                return JPEG;
 
220
        } else {
 
221
                return TYPE_UNKNOWN;
 
222
        }
 
223
}
 
224
 
 
225
static bool LoadTextureLevels(const uint8_t *data, size_t size, T3DImageType type, int width[16], int height[16], int *num_levels, T3DImageFormat *fmt, uint8_t *image[16], int *zim_flags) {
 
226
        if (type == DETECT) {
 
227
                type = DetectImageFileType(data, size);
 
228
        }
 
229
        if (type == TYPE_UNKNOWN) {
 
230
                ELOG("File has unknown format");
 
231
                return false;
 
232
        }
 
233
 
 
234
        *num_levels = 0;
 
235
        *zim_flags = 0;
 
236
 
 
237
        switch (type) {
 
238
        case ZIM:
 
239
        {
 
240
                *num_levels = LoadZIMPtr((const uint8_t *)data, size, width, height, zim_flags, image);
 
241
                *fmt = ZimToT3DFormat(*zim_flags & ZIM_FORMAT_MASK);
 
242
        }
 
243
                break;
 
244
 
 
245
        case PNG:
 
246
                if (1 == pngLoadPtr((const unsigned char *)data, size, &width[0], &height[0], &image[0], false)) {
 
247
                        *num_levels = 1;
 
248
                        *fmt = RGBA8888;
 
249
                }
 
250
                break;
 
251
 
 
252
        case JPEG:
 
253
                {
 
254
                        int actual_components = 0;
 
255
                        unsigned char *jpegBuf = jpgd::decompress_jpeg_image_from_memory(data, (int)size, &width[0], &height[0], &actual_components, 4);
 
256
                        if (jpegBuf) {
 
257
                                *num_levels = 1;
 
258
                                *fmt = RGBA8888;
 
259
                                image[0] = (uint8_t *)jpegBuf;
 
260
                        }
 
261
                }
 
262
                break;
 
263
 
 
264
        default:
 
265
                ELOG("Unknown image format");
 
266
                return false;
 
267
        }
 
268
 
 
269
        return *num_levels > 0;
 
270
}
 
271
 
 
272
bool Thin3DTexture::LoadFromFileData(const uint8_t *data, size_t dataSize, T3DImageType type) {
 
273
        int width[16], height[16];
 
274
        uint8_t *image[16] = { nullptr };
 
275
 
 
276
        int num_levels;
 
277
        int zim_flags;
 
278
        T3DImageFormat fmt;
 
279
 
 
280
        if (!LoadTextureLevels(data, dataSize, type, width, height, &num_levels, &fmt, image, &zim_flags)) {
 
281
                return false;
 
282
        }
 
283
 
 
284
        if (num_levels < 0 || num_levels >= 16) {
 
285
                ELOG("Invalid num_levels: %d. Falling back to one. Image: %dx%d", num_levels, width[0], height[0]);
 
286
                num_levels = 1;
 
287
        }
 
288
 
 
289
        Create(LINEAR2D, fmt, width[0], height[0], 1, num_levels);
 
290
        for (int i = 0; i < num_levels; i++) {
 
291
                if (image[i]) {
 
292
                        SetImageData(0, 0, 0, width[i], height[i], 1, i, width[i] * 4, image[i]);
 
293
                        free(image[i]);
 
294
                } else {
 
295
                        ELOG("Missing image level %i", i);
 
296
                }
 
297
        }
 
298
 
 
299
        Finalize(zim_flags);
 
300
        return true;
 
301
}
 
302
 
 
303
bool Thin3DTexture::LoadFromFile(const std::string &filename, T3DImageType type) {
 
304
        filename_ = "";
 
305
        size_t fileSize;
 
306
        uint8_t *buffer = VFSReadFile(filename.c_str(), &fileSize);
 
307
        if (!buffer) {
 
308
                return false;
 
309
        }
 
310
        bool retval = LoadFromFileData(buffer, fileSize, type);
 
311
        if (retval) {
 
312
                filename_ = filename;
 
313
        } else {
 
314
                ELOG("%s: Failed to load texture %s", __FUNCTION__, filename.c_str());
 
315
        }
 
316
        delete[] buffer;
 
317
        return retval;
 
318
}
 
319
 
 
320
Thin3DTexture *Thin3DContext::CreateTextureFromFile(const char *filename, T3DImageType type) {
 
321
        Thin3DTexture *tex = CreateTexture();
 
322
        if (!tex->LoadFromFile(filename, type)) {
 
323
                tex->Release();
 
324
                return NULL;
 
325
        }
 
326
        return tex;
 
327
}
 
328
 
 
329
// TODO: Remove the code duplication between this and LoadFromFileData
 
330
Thin3DTexture *Thin3DContext::CreateTextureFromFileData(const uint8_t *data, int size, T3DImageType type) {
 
331
        int width[16], height[16];
 
332
        int num_levels = 0;
 
333
        int zim_flags = 0;
 
334
        T3DImageFormat fmt;
 
335
        uint8_t *image[16] = { nullptr };
 
336
 
 
337
        if (!LoadTextureLevels(data, size, type, width, height, &num_levels, &fmt, image, &zim_flags)) {
 
338
                return NULL;
 
339
        }
 
340
 
 
341
        Thin3DTexture *tex = CreateTexture(LINEAR2D, fmt, width[0], height[0], 1, num_levels);
 
342
        for (int i = 0; i < num_levels; i++) {
 
343
                tex->SetImageData(0, 0, 0, width[i], height[i], 1, i, width[i] * 4, image[i]);
 
344
                free(image[i]);
 
345
        }
 
346
 
 
347
        tex->Finalize(zim_flags);
 
348
        return tex;
 
349
}