mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-27 15:30:35 +00:00
Merge pull request #8591 from unknownbrackets/thin3d
Use thin3d for softgpu drawing (+thin3d improvements)
This commit is contained in:
commit
54a37f9bb8
@ -18,6 +18,7 @@
|
||||
#include <set>
|
||||
|
||||
#include "Common/ChunkFile.h"
|
||||
#include "Common/GraphicsContext.h"
|
||||
#include "base/NativeApp.h"
|
||||
#include "base/logging.h"
|
||||
#include "profiler/profiler.h"
|
||||
@ -391,8 +392,8 @@ static const CommandTableEntry commandTable[] = {
|
||||
|
||||
DIRECTX9_GPU::CommandInfo DIRECTX9_GPU::cmdInfo_[256];
|
||||
|
||||
DIRECTX9_GPU::DIRECTX9_GPU()
|
||||
: resized_(false) {
|
||||
DIRECTX9_GPU::DIRECTX9_GPU(GraphicsContext *gfxCtx)
|
||||
: resized_(false), gfxCtx_(gfxCtx) {
|
||||
lastVsync_ = g_Config.bVSync ? 1 : 0;
|
||||
dxstate.SetVSyncInterval(g_Config.bVSync);
|
||||
|
||||
@ -500,11 +501,12 @@ DIRECTX9_GPU::~DIRECTX9_GPU() {
|
||||
|
||||
// Needs to be called on GPU thread, not reporting thread.
|
||||
void DIRECTX9_GPU::BuildReportingInfo() {
|
||||
D3DADAPTER_IDENTIFIER9 identifier = {0};
|
||||
pD3D->GetAdapterIdentifier(D3DADAPTER_DEFAULT, 0, &identifier);
|
||||
Thin3DContext *thin3d = gfxCtx_->CreateThin3DContext();
|
||||
|
||||
reportingPrimaryInfo_ = identifier.Description;
|
||||
reportingFullInfo_ = reportingPrimaryInfo_ + " - " + System_GetProperty(SYSPROP_GPUDRIVER_VERSION);
|
||||
reportingPrimaryInfo_ = thin3d->GetInfoString(T3DInfo::VENDORSTRING);
|
||||
reportingFullInfo_ = reportingPrimaryInfo_ + " - " + System_GetProperty(SYSPROP_GPUDRIVER_VERSION) + " - " + thin3d->GetInfoString(T3DInfo::SHADELANGVERSION);
|
||||
|
||||
thin3d->Release();
|
||||
}
|
||||
|
||||
void DIRECTX9_GPU::DeviceLost() {
|
||||
|
@ -35,7 +35,7 @@ class LinkedShaderDX9;
|
||||
|
||||
class DIRECTX9_GPU : public GPUCommon {
|
||||
public:
|
||||
DIRECTX9_GPU();
|
||||
DIRECTX9_GPU(GraphicsContext *gfxCtx);
|
||||
~DIRECTX9_GPU();
|
||||
void CheckGPUFeatures();
|
||||
void InitClear() override;
|
||||
@ -187,6 +187,8 @@ private:
|
||||
|
||||
std::string reportingPrimaryInfo_;
|
||||
std::string reportingFullInfo_;
|
||||
|
||||
GraphicsContext *gfxCtx_;
|
||||
};
|
||||
|
||||
} // namespace DX9
|
||||
|
@ -50,11 +50,11 @@ bool GPU_Init(GraphicsContext *ctx) {
|
||||
SetGPU(new GLES_GPU(ctx));
|
||||
break;
|
||||
case GPU_SOFTWARE:
|
||||
SetGPU(new SoftGPU());
|
||||
SetGPU(new SoftGPU(ctx));
|
||||
break;
|
||||
case GPU_DIRECTX9:
|
||||
#if defined(_WIN32)
|
||||
SetGPU(new DIRECTX9_GPU());
|
||||
SetGPU(new DIRECTX9_GPU(ctx));
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
@ -15,11 +15,11 @@
|
||||
// Official git repository and contact information can be found at
|
||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
|
||||
#include "GPU/GPUState.h"
|
||||
#include "GPU/ge_constants.h"
|
||||
#include "GPU/Common/TextureDecoder.h"
|
||||
#include "Common/ColorConv.h"
|
||||
#include "Common/GraphicsContext.h"
|
||||
#include "Core/Config.h"
|
||||
#include "Core/Debugger/Breakpoints.h"
|
||||
#include "Core/Host.h"
|
||||
@ -28,68 +28,45 @@
|
||||
#include "Core/HLE/sceGe.h"
|
||||
#include "Core/MIPS/MIPS.h"
|
||||
#include "Core/Reporting.h"
|
||||
#include "gfx/gl_common.h"
|
||||
#include "gfx_es2/glsl_program.h"
|
||||
#include "gfx_es2/gpu_features.h"
|
||||
#include "profiler/profiler.h"
|
||||
#include "thin3d/thin3d.h"
|
||||
|
||||
#include "GPU/Software/SoftGpu.h"
|
||||
#include "GPU/Software/TransformUnit.h"
|
||||
#include "GPU/Software/Rasterizer.h"
|
||||
#include "GPU/Common/FramebufferCommon.h"
|
||||
|
||||
static GLuint temp_texture = 0;
|
||||
|
||||
static GLSLProgram *program;
|
||||
static GLuint vao;
|
||||
static GLuint vbuf;
|
||||
|
||||
const int FB_WIDTH = 480;
|
||||
const int FB_HEIGHT = 272;
|
||||
FormatBuffer fb;
|
||||
FormatBuffer depthbuf;
|
||||
u32 clut[4096];
|
||||
|
||||
SoftGPU::SoftGPU()
|
||||
static Thin3DContext *thin3d = nullptr;
|
||||
static Thin3DTexture *fbTex = nullptr;
|
||||
static Thin3DVertexFormat *vformat = nullptr;
|
||||
static Thin3DDepthStencilState *depth = nullptr;
|
||||
static Thin3DBuffer *vdata = nullptr;
|
||||
static Thin3DBuffer *idata = nullptr;
|
||||
static std::vector<u32> fbTexBuffer;
|
||||
|
||||
SoftGPU::SoftGPU(GraphicsContext *gfxCtx)
|
||||
: gfxCtx_(gfxCtx)
|
||||
{
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // 4-byte pixel alignment
|
||||
glGenTextures(1, &temp_texture);
|
||||
thin3d = gfxCtx_->CreateThin3DContext();
|
||||
fbTex = thin3d->CreateTexture(LINEAR2D, RGBA8888, 480, 272, 1, 1);
|
||||
|
||||
// TODO: Use highp for GLES
|
||||
static const char *fragShaderText =
|
||||
#ifdef USING_GLES2
|
||||
"#version 100\n"
|
||||
#endif
|
||||
"varying vec2 texcoord;\n"
|
||||
"uniform sampler2D sampler0;\n"
|
||||
"void main() {\n"
|
||||
" gl_FragColor = texture2D(sampler0, texcoord);\n"
|
||||
"}\n";
|
||||
static const char *vertShaderText =
|
||||
#ifdef USING_GLES2
|
||||
"#version 100\n"
|
||||
#endif
|
||||
"attribute vec4 a_position;\n"
|
||||
"attribute vec2 a_texcoord0;\n "
|
||||
"varying vec2 texcoord;\n "
|
||||
"void main() {\n"
|
||||
" gl_Position = a_position;\n"
|
||||
" texcoord = a_texcoord0;\n"
|
||||
"}\n";
|
||||
std::vector<Thin3DVertexComponent> components;
|
||||
components.push_back(Thin3DVertexComponent("Position", SEM_POSITION, FLOATx3, 0));
|
||||
components.push_back(Thin3DVertexComponent("TexCoord0", SEM_TEXCOORD0, FLOATx2, 12));
|
||||
components.push_back(Thin3DVertexComponent("Color0", SEM_COLOR0, UNORM8x4, 20));
|
||||
|
||||
std::string errorString;
|
||||
program = glsl_create_source(vertShaderText, fragShaderText, &errorString);
|
||||
if (!program) {
|
||||
ERROR_LOG_REPORT(G3D, "Failed to compile softgpu program! This shouldn't happen.\n%s", errorString.c_str());
|
||||
} else {
|
||||
glsl_bind(program);
|
||||
}
|
||||
Thin3DShader *vshader = thin3d->GetVshaderPreset(VS_TEXTURE_COLOR_2D);
|
||||
vformat = thin3d->CreateVertexFormat(components, 24, vshader);
|
||||
|
||||
if (gl_extensions.ARB_vertex_array_object) {
|
||||
glGenVertexArrays(1, &vao);
|
||||
glGenBuffers(1, &vbuf);
|
||||
}
|
||||
vdata = thin3d->CreateBuffer(24 * 4, T3DBufferUsage::DYNAMIC | T3DBufferUsage::VERTEXDATA);
|
||||
idata = thin3d->CreateBuffer(sizeof(int) * 6, T3DBufferUsage::DYNAMIC | T3DBufferUsage::INDEXDATA);
|
||||
depth = thin3d->CreateDepthStencilState(false, false, T3DComparison::LESS);
|
||||
|
||||
fb.data = Memory::GetPointer(0x44000000); // TODO: correct default address?
|
||||
depthbuf.data = Memory::GetPointer(0x44000000); // TODO: correct default address?
|
||||
@ -102,24 +79,16 @@ SoftGPU::SoftGPU()
|
||||
}
|
||||
|
||||
void SoftGPU::DeviceLost() {
|
||||
if (vao != 0) {
|
||||
// These deletes will likely fail, but let's try just in case.
|
||||
glDeleteVertexArrays(1, &vao);
|
||||
glDeleteBuffers(1, &vbuf);
|
||||
|
||||
glGenVertexArrays(1, &vao);
|
||||
glGenBuffers(1, &vbuf);
|
||||
}
|
||||
// Handled by thin3d.
|
||||
}
|
||||
|
||||
SoftGPU::~SoftGPU()
|
||||
{
|
||||
glsl_destroy(program);
|
||||
glDeleteTextures(1, &temp_texture);
|
||||
if (vao != 0) {
|
||||
glDeleteVertexArrays(1, &vao);
|
||||
glDeleteBuffers(1, &vbuf);
|
||||
}
|
||||
SoftGPU::~SoftGPU() {
|
||||
vformat->Release();
|
||||
vformat = nullptr;
|
||||
fbTex->Release();
|
||||
fbTex = nullptr;
|
||||
thin3d->Release();
|
||||
thin3d = nullptr;
|
||||
}
|
||||
|
||||
void SoftGPU::SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format) {
|
||||
@ -136,48 +105,51 @@ void SoftGPU::CopyToCurrentFboFromDisplayRam(int srcwidth, int srcheight)
|
||||
float dstwidth = (float)PSP_CoreParameter().pixelWidth;
|
||||
float dstheight = (float)PSP_CoreParameter().pixelHeight;
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
glViewport(0, 0, dstwidth, dstheight);
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
T3DViewport viewport = {0.0f, 0.0f, dstwidth, dstheight, 0.0f, 1.0f};
|
||||
thin3d->SetViewports(1, &viewport);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, temp_texture);
|
||||
thin3d->SetBlendState(thin3d->GetBlendStatePreset(BS_OFF));
|
||||
Thin3DSamplerState *sampler;
|
||||
if (g_Config.iBufFilter == SCALE_NEAREST) {
|
||||
sampler = thin3d->GetSamplerStatePreset(T3DSamplerStatePreset::SAMPS_NEAREST);
|
||||
} else {
|
||||
sampler = thin3d->GetSamplerStatePreset(T3DSamplerStatePreset::SAMPS_LINEAR);
|
||||
}
|
||||
thin3d->SetSamplerStates(0, 1, &sampler);
|
||||
thin3d->SetDepthStencilState(depth);
|
||||
thin3d->SetRenderState(T3DRenderState::CULL_MODE, T3DCullMode::NO_CULL);
|
||||
thin3d->SetScissorEnabled(false);
|
||||
|
||||
GLfloat texvert_u;
|
||||
float u0 = 0.0f;
|
||||
float u1;
|
||||
if (displayFramebuf_ == 0) {
|
||||
u32 data[] = {0};
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
|
||||
texvert_u = 1.0f;
|
||||
u8 data[] = {0, 0, 0, 0};
|
||||
fbTex->SetImageData(0, 0, 0, 1, 1, 1, 0, 4, data);
|
||||
u1 = 1.0f;
|
||||
} else if (displayFormat_ == GE_FORMAT_8888) {
|
||||
u8 *data = Memory::GetPointer(displayFramebuf_);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)displayStride_, (GLsizei)srcheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
|
||||
texvert_u = (float)srcwidth / displayStride_;
|
||||
fbTex->SetImageData(0, 0, 0, displayStride_, srcheight, 1, 0, displayStride_ * 4, data);
|
||||
u1 = (float)srcwidth / displayStride_;
|
||||
} else {
|
||||
// TODO: This should probably be converted in a shader instead..
|
||||
// TODO: Do something less brain damaged to manage this buffer...
|
||||
u32 *buf = new u32[srcwidth * srcheight];
|
||||
fbTexBuffer.resize(srcwidth * srcheight);
|
||||
FormatBuffer displayBuffer;
|
||||
displayBuffer.data = Memory::GetPointer(displayFramebuf_);
|
||||
for (int y = 0; y < srcheight; ++y) {
|
||||
u32 *buf_line = &buf[y * srcwidth];
|
||||
u32 *buf_line = &fbTexBuffer[y * srcwidth];
|
||||
const u16 *fb_line = &displayBuffer.as16[y * displayStride_];
|
||||
|
||||
switch (displayFormat_) {
|
||||
case GE_FORMAT_565:
|
||||
for (int x = 0; x < srcwidth; ++x) {
|
||||
buf_line[x] = RGB565ToRGBA8888(fb_line[x]);
|
||||
}
|
||||
ConvertRGBA565ToRGBA8888(buf_line, fb_line, srcwidth);
|
||||
break;
|
||||
|
||||
case GE_FORMAT_5551:
|
||||
for (int x = 0; x < srcwidth; ++x) {
|
||||
buf_line[x] = RGBA5551ToRGBA8888(fb_line[x]);
|
||||
}
|
||||
ConvertRGBA5551ToRGBA8888(buf_line, fb_line, srcwidth);
|
||||
break;
|
||||
|
||||
case GE_FORMAT_4444:
|
||||
for (int x = 0; x < srcwidth; ++x) {
|
||||
buf_line[x] = RGBA4444ToRGBA8888(fb_line[x]);
|
||||
}
|
||||
ConvertRGBA4444ToRGBA8888(buf_line, fb_line, srcwidth);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -185,20 +157,19 @@ void SoftGPU::CopyToCurrentFboFromDisplayRam(int srcwidth, int srcheight)
|
||||
}
|
||||
}
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)srcwidth, (GLsizei)srcheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf);
|
||||
texvert_u = 1.0f;
|
||||
|
||||
delete[] buf;
|
||||
fbTex->SetImageData(0, 0, 0, srcwidth, srcheight, 1, 0, srcwidth * 4, (const uint8_t *)&fbTexBuffer[0]);
|
||||
u1 = 1.0f;
|
||||
}
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, g_Config.iBufFilter == SCALE_NEAREST ? GL_NEAREST : GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, g_Config.iBufFilter == SCALE_NEAREST ? GL_NEAREST : GL_LINEAR);
|
||||
|
||||
glsl_bind(program);
|
||||
fbTex->Finalize(0);
|
||||
|
||||
float x, y, w, h;
|
||||
CenterDisplayOutputRect(&x, &y, &w, &h, 480.0f, 272.0f, dstwidth, dstheight, ROTATION_LOCKED_HORIZONTAL);
|
||||
|
||||
if (GetGPUBackend() == GPUBackend::DIRECT3D9) {
|
||||
x += 0.5f;
|
||||
y += 0.5f;
|
||||
}
|
||||
|
||||
x /= 0.5f * dstwidth;
|
||||
y /= 0.5f * dstheight;
|
||||
w /= 0.5f * dstwidth;
|
||||
@ -210,53 +181,37 @@ void SoftGPU::CopyToCurrentFboFromDisplayRam(int srcwidth, int srcheight)
|
||||
x2 -= 1.0f;
|
||||
y2 -= 1.0f;
|
||||
|
||||
const GLfloat verts[4][2] = {
|
||||
{ x, y }, // Left top
|
||||
{ x, y2}, // left bottom
|
||||
{ x2, y2}, // right bottom
|
||||
{ x2, y} // right top
|
||||
struct Vertex {
|
||||
float x, y, z;
|
||||
float u, v;
|
||||
uint32_t rgba;
|
||||
};
|
||||
|
||||
const GLfloat texverts[4][2] = {
|
||||
{0, 1},
|
||||
{0, 0},
|
||||
{texvert_u, 0},
|
||||
{texvert_u, 1}
|
||||
float v0 = 1.0f;
|
||||
float v1 = 0.0f;
|
||||
|
||||
const Vertex verts[4] = {
|
||||
{x, y, 0, u0, v0, 0xFFFFFFFF}, // TL
|
||||
{x, y2, 0, u0, v1, 0xFFFFFFFF}, // BL
|
||||
{x2, y2, 0, u1, v1, 0xFFFFFFFF}, // BR
|
||||
{x2, y, 0, u1, v0, 0xFFFFFFFF}, // TR
|
||||
};
|
||||
vdata->SetData((const uint8_t *)verts, sizeof(verts));
|
||||
|
||||
if (vao != 0) {
|
||||
glBindVertexArray(vao);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbuf);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(verts) + sizeof(texverts), nullptr, GL_STREAM_DRAW);
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(verts), verts);
|
||||
glBufferSubData(GL_ARRAY_BUFFER, sizeof(verts), sizeof(texverts), texverts);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
int indexes[] = {0, 1, 2, 0, 2, 3};
|
||||
idata->SetData((const uint8_t *)indexes, sizeof(indexes));
|
||||
|
||||
glVertexAttribPointer(program->a_position, 2, GL_FLOAT, GL_FALSE, 0, 0);
|
||||
glVertexAttribPointer(program->a_texcoord0, 2, GL_FLOAT, GL_FALSE, 0, (void *)sizeof(verts));
|
||||
} else {
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
thin3d->SetTexture(0, fbTex);
|
||||
Thin3DShaderSet *texColor = thin3d->GetShaderSetPreset(SS_TEXTURE_COLOR_2D);
|
||||
|
||||
glVertexAttribPointer(program->a_position, 2, GL_FLOAT, GL_FALSE, 0, verts);
|
||||
glVertexAttribPointer(program->a_texcoord0, 2, GL_FLOAT, GL_FALSE, 0, texverts);
|
||||
}
|
||||
|
||||
glEnableVertexAttribArray(program->a_position);
|
||||
glEnableVertexAttribArray(program->a_texcoord0);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glUniform1i(program->sampler0, 0);
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
glDisableVertexAttribArray(program->a_position);
|
||||
glDisableVertexAttribArray(program->a_texcoord0);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
if (vao != 0) {
|
||||
glBindVertexArray(0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
}
|
||||
static const float identity4x4[16] = {
|
||||
1.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 1.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 1.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 1.0f,
|
||||
};
|
||||
texColor->SetMatrix4x4("WorldViewProj", identity4x4);
|
||||
thin3d->DrawIndexed(T3DPrimitive::PRIM_TRIANGLES, texColor, vformat, vdata, idata, 6, 0);
|
||||
}
|
||||
|
||||
void SoftGPU::CopyDisplayToOutput()
|
||||
|
@ -48,7 +48,7 @@ class ShaderManager;
|
||||
|
||||
class SoftGPU : public GPUCommon {
|
||||
public:
|
||||
SoftGPU();
|
||||
SoftGPU(GraphicsContext *gfxCtx);
|
||||
~SoftGPU();
|
||||
void InitClear() override {}
|
||||
void ExecuteOp(u32 op, u32 diff) override;
|
||||
@ -100,4 +100,6 @@ private:
|
||||
u32 displayFramebuf_;
|
||||
u32 displayStride_;
|
||||
GEBufferFormat displayFormat_;
|
||||
|
||||
GraphicsContext *gfxCtx_;
|
||||
};
|
||||
|
@ -98,10 +98,13 @@ void EmuScreen::bootGame(const std::string &filename) {
|
||||
|
||||
CoreParameter coreParam;
|
||||
coreParam.cpuCore = g_Config.bJit ? CPU_JIT : CPU_INTERPRETER;
|
||||
coreParam.gpuCore = g_Config.bSoftwareRendering ? GPU_SOFTWARE : GPU_GLES;
|
||||
coreParam.gpuCore = GPU_GLES;
|
||||
if (GetGPUBackend() == GPUBackend::DIRECT3D9) {
|
||||
coreParam.gpuCore = GPU_DIRECTX9;
|
||||
}
|
||||
if (g_Config.bSoftwareRendering) {
|
||||
coreParam.gpuCore = GPU_SOFTWARE;
|
||||
}
|
||||
// Preserve the existing graphics context.
|
||||
coreParam.graphicsContext = PSP_CoreParameter().graphicsContext;
|
||||
coreParam.enableSound = g_Config.bEnableSound;
|
||||
|
@ -331,7 +331,7 @@ void GameSettingsScreen::CreateViews() {
|
||||
CheckBox *softwareGPU = graphicsSettings->Add(new CheckBox(&g_Config.bSoftwareRendering, gr->T("Software Rendering", "Software Rendering (experimental)")));
|
||||
softwareGPU->OnClick.Handle(this, &GameSettingsScreen::OnSoftwareRendering);
|
||||
|
||||
if (PSP_IsInited() || g_Config.iGPUBackend != GPU_BACKEND_OPENGL)
|
||||
if (PSP_IsInited())
|
||||
softwareGPU->SetEnabled(false);
|
||||
|
||||
// Audio
|
||||
@ -886,11 +886,6 @@ void GameSettingsScreen::CallbackRenderingBackend(bool yes) {
|
||||
// If the user ends up deciding not to restart, set the config back to the current backend
|
||||
// so it doesn't get switched by accident.
|
||||
if (yes) {
|
||||
if (g_Config.iGPUBackend == (int)GPUBackend::DIRECT3D9) {
|
||||
// TODO: Remove once software renderer supports D3D9.
|
||||
g_Config.bSoftwareRendering = false;
|
||||
}
|
||||
|
||||
g_Config.bRestartRequired = true;
|
||||
PostMessage(MainWindow::GetHWND(), WM_CLOSE, 0, 0);
|
||||
} else {
|
||||
|
@ -691,8 +691,6 @@ namespace MainWindow {
|
||||
|
||||
case ID_OPTIONS_DIRECT3D9:
|
||||
g_Config.iGPUBackend = GPU_BACKEND_DIRECT3D9;
|
||||
// TODO: Remove once software renderer supports D3D9.
|
||||
g_Config.bSoftwareRendering = false;
|
||||
g_Config.bRestartRequired = true;
|
||||
PostMessage(MainWindow::GetHWND(), WM_CLOSE, 0, 0);
|
||||
break;
|
||||
|
@ -472,13 +472,10 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin
|
||||
if (restOfOption == L"directx9") {
|
||||
g_Config.iGPUBackend = GPU_BACKEND_DIRECT3D9;
|
||||
g_Config.bSoftwareRendering = false;
|
||||
}
|
||||
else if (restOfOption == L"gles") {
|
||||
} else if (restOfOption == L"gles") {
|
||||
g_Config.iGPUBackend = GPU_BACKEND_OPENGL;
|
||||
g_Config.bSoftwareRendering = false;
|
||||
}
|
||||
|
||||
else if (restOfOption == L"software") {
|
||||
} else if (restOfOption == L"software") {
|
||||
g_Config.iGPUBackend = GPU_BACKEND_OPENGL;
|
||||
g_Config.bSoftwareRendering = true;
|
||||
}
|
||||
|
@ -80,7 +80,7 @@ void DrawBuffer::Flush(bool set_blend_state) {
|
||||
if (count_ == 0)
|
||||
return;
|
||||
|
||||
shaderSet_->SetMatrix4x4("WorldViewProj", drawMatrix_);
|
||||
shaderSet_->SetMatrix4x4("WorldViewProj", drawMatrix_.getReadPtr());
|
||||
|
||||
if (vbuf_) {
|
||||
vbuf_->SubData((const uint8_t *)verts_, 0, sizeof(Vertex) * count_);
|
||||
|
@ -94,6 +94,12 @@ void Thin3DContext::CreatePresets() {
|
||||
bsPresets_[BS_STANDARD_ALPHA] = CreateBlendState(standard_alpha);
|
||||
bsPresets_[BS_PREMUL_ALPHA] = CreateBlendState(premul_alpha);
|
||||
|
||||
T3DSamplerStateDesc nearest = { CLAMP, CLAMP, NEAREST, NEAREST, NEAREST };
|
||||
T3DSamplerStateDesc linear = { CLAMP, CLAMP, LINEAR, LINEAR, NEAREST };
|
||||
|
||||
sampsPresets_[SAMPS_NEAREST] = CreateSamplerState(nearest);
|
||||
sampsPresets_[SAMPS_LINEAR] = CreateSamplerState(linear);
|
||||
|
||||
vsPresets_[VS_TEXTURE_COLOR_2D] = CreateVertexShader(glsl_vsTexCol, hlslVsTexCol);
|
||||
vsPresets_[VS_COLOR_2D] = CreateVertexShader(glsl_vsCol, hlslVsCol);
|
||||
|
||||
|
@ -66,6 +66,16 @@ enum T3DBlendFactor : int {
|
||||
FIXED_COLOR,
|
||||
};
|
||||
|
||||
enum T3DTextureWrap : int {
|
||||
REPEAT,
|
||||
CLAMP,
|
||||
};
|
||||
|
||||
enum T3DTextureFilter : int {
|
||||
NEAREST,
|
||||
LINEAR,
|
||||
};
|
||||
|
||||
enum T3DBufferUsage : int {
|
||||
VERTEXDATA = 1,
|
||||
INDEXDATA = 2,
|
||||
@ -126,6 +136,12 @@ enum T3DBlendStatePreset : int {
|
||||
BS_MAX_PRESET,
|
||||
};
|
||||
|
||||
enum T3DSamplerStatePreset : int {
|
||||
SAMPS_NEAREST,
|
||||
SAMPS_LINEAR,
|
||||
SAMPS_MAX_PRESET,
|
||||
};
|
||||
|
||||
enum T3DClear : int {
|
||||
COLOR = 1,
|
||||
DEPTH = 2,
|
||||
@ -207,6 +223,10 @@ class Thin3DBlendState : public Thin3DObject {
|
||||
public:
|
||||
};
|
||||
|
||||
class Thin3DSamplerState : public Thin3DObject {
|
||||
public:
|
||||
};
|
||||
|
||||
class Thin3DDepthStencilState : public Thin3DObject {
|
||||
public:
|
||||
};
|
||||
@ -262,7 +282,7 @@ class Thin3DShaderSet : public Thin3DObject {
|
||||
public:
|
||||
// TODO: Make some faster way of doing these. Support uniform buffers (and fake them on GL 2.0?)
|
||||
virtual void SetVector(const char *name, float *value, int n) = 0;
|
||||
virtual void SetMatrix4x4(const char *name, const Matrix4x4 &value) = 0;
|
||||
virtual void SetMatrix4x4(const char *name, const float value[16]) = 0;
|
||||
};
|
||||
|
||||
struct T3DBlendStateDesc {
|
||||
@ -278,6 +298,14 @@ struct T3DBlendStateDesc {
|
||||
// int colorMask;
|
||||
};
|
||||
|
||||
struct T3DSamplerStateDesc {
|
||||
T3DTextureWrap wrapS;
|
||||
T3DTextureWrap wrapT;
|
||||
T3DTextureFilter magFilt;
|
||||
T3DTextureFilter minFilt;
|
||||
T3DTextureFilter mipFilt;
|
||||
};
|
||||
|
||||
class Thin3DContext : public Thin3DObject {
|
||||
public:
|
||||
virtual ~Thin3DContext();
|
||||
@ -286,6 +314,7 @@ public:
|
||||
|
||||
virtual Thin3DDepthStencilState *CreateDepthStencilState(bool depthTestEnabled, bool depthWriteEnabled, T3DComparison depthCompare) = 0;
|
||||
virtual Thin3DBlendState *CreateBlendState(const T3DBlendStateDesc &desc) = 0;
|
||||
virtual Thin3DSamplerState *CreateSamplerState(const T3DSamplerStateDesc &desc) = 0;
|
||||
virtual Thin3DBuffer *CreateBuffer(size_t size, uint32_t usageFlags) = 0;
|
||||
virtual Thin3DShaderSet *CreateShaderSet(Thin3DShader *vshader, Thin3DShader *fshader) = 0;
|
||||
virtual Thin3DVertexFormat *CreateVertexFormat(const std::vector<Thin3DVertexComponent> &components, int stride, Thin3DShader *vshader) = 0;
|
||||
@ -299,6 +328,7 @@ public:
|
||||
|
||||
// Note that these DO NOT AddRef so you must not ->Release presets unless you manually AddRef them.
|
||||
Thin3DBlendState *GetBlendStatePreset(T3DBlendStatePreset preset) { return bsPresets_[preset]; }
|
||||
Thin3DSamplerState *GetSamplerStatePreset(T3DSamplerStatePreset preset) { return sampsPresets_[preset]; }
|
||||
Thin3DShader *GetVshaderPreset(T3DVertexShaderPreset preset) { return fsPresets_[preset]; }
|
||||
Thin3DShader *GetFshaderPreset(T3DFragmentShaderPreset preset) { return vsPresets_[preset]; }
|
||||
Thin3DShaderSet *GetShaderSetPreset(T3DShaderSetPreset preset) { return ssPresets_[preset]; }
|
||||
@ -309,6 +339,7 @@ public:
|
||||
|
||||
// Bound state objects. Too cumbersome to add them all as parameters to Draw.
|
||||
virtual void SetBlendState(Thin3DBlendState *state) = 0;
|
||||
virtual void SetSamplerStates(int start, int count, Thin3DSamplerState **state) = 0;
|
||||
virtual void SetDepthStencilState(Thin3DDepthStencilState *state) = 0;
|
||||
virtual void SetTextures(int start, int count, Thin3DTexture **textures) = 0;
|
||||
|
||||
@ -345,6 +376,7 @@ protected:
|
||||
Thin3DShader *fsPresets_[FS_MAX_PRESET];
|
||||
Thin3DBlendState *bsPresets_[BS_MAX_PRESET];
|
||||
Thin3DShaderSet *ssPresets_[SS_MAX_PRESET];
|
||||
Thin3DSamplerState *sampsPresets_[SAMPS_MAX_PRESET];
|
||||
|
||||
int targetWidth_;
|
||||
int targetHeight_;
|
||||
|
@ -56,12 +56,28 @@ static const D3DBLEND blendFactorToD3D9[] = {
|
||||
D3DBLEND_BLENDFACTOR,
|
||||
};
|
||||
|
||||
static const D3DTEXTUREADDRESS texWrapToD3D9[] = {
|
||||
D3DTADDRESS_WRAP,
|
||||
D3DTADDRESS_CLAMP,
|
||||
};
|
||||
|
||||
static const D3DTEXTUREFILTERTYPE texFilterToD3D9[] = {
|
||||
D3DTEXF_POINT,
|
||||
D3DTEXF_LINEAR,
|
||||
};
|
||||
|
||||
static const D3DPRIMITIVETYPE primToD3D9[] = {
|
||||
D3DPT_POINTLIST,
|
||||
D3DPT_LINELIST,
|
||||
D3DPT_TRIANGLELIST,
|
||||
};
|
||||
|
||||
static const int primCountDivisor[] = {
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
};
|
||||
|
||||
class Thin3DDX9DepthStencilState : public Thin3DDepthStencilState {
|
||||
public:
|
||||
BOOL depthTestEnabled;
|
||||
@ -94,6 +110,20 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class Thin3DDX9SamplerState : public Thin3DSamplerState {
|
||||
public:
|
||||
D3DTEXTUREADDRESS wrapS, wrapT;
|
||||
D3DTEXTUREFILTERTYPE magFilt, minFilt, mipFilt;
|
||||
|
||||
void Apply(LPDIRECT3DDEVICE9 device, int index) {
|
||||
device->SetSamplerState(index, D3DSAMP_ADDRESSU, wrapS);
|
||||
device->SetSamplerState(index, D3DSAMP_ADDRESSV, wrapT);
|
||||
device->SetSamplerState(index, D3DSAMP_MAGFILTER, magFilt);
|
||||
device->SetSamplerState(index, D3DSAMP_MINFILTER, minFilt);
|
||||
device->SetSamplerState(index, D3DSAMP_MIPFILTER, mipFilt);
|
||||
}
|
||||
};
|
||||
|
||||
class Thin3DDX9Buffer : public Thin3DBuffer {
|
||||
public:
|
||||
Thin3DDX9Buffer(LPDIRECT3DDEVICE9 device, size_t size, uint32_t flags) : vbuffer_(nullptr), ibuffer_(nullptr), maxSize_(size) {
|
||||
@ -212,7 +242,7 @@ public:
|
||||
}
|
||||
}
|
||||
void SetVector(LPDIRECT3DDEVICE9 device, const char *name, float *value, int n);
|
||||
void SetMatrix4x4(LPDIRECT3DDEVICE9 device, const char *name, const Matrix4x4 &value);
|
||||
void SetMatrix4x4(LPDIRECT3DDEVICE9 device, const char *name, const float value[16]);
|
||||
|
||||
private:
|
||||
bool isPixelShader_;
|
||||
@ -228,7 +258,7 @@ public:
|
||||
Thin3DDX9Shader *pshader;
|
||||
void Apply(LPDIRECT3DDEVICE9 device);
|
||||
void SetVector(const char *name, float *value, int n) { vshader->SetVector(device_, name, value, n); pshader->SetVector(device_, name, value, n); }
|
||||
void SetMatrix4x4(const char *name, const Matrix4x4 &value) { vshader->SetMatrix4x4(device_, name, value); } // pshaders don't usually have matrices
|
||||
void SetMatrix4x4(const char *name, const float value[16]) { vshader->SetMatrix4x4(device_, name, value); } // pshaders don't usually have matrices
|
||||
private:
|
||||
LPDIRECT3DDEVICE9 device_;
|
||||
};
|
||||
@ -397,6 +427,7 @@ public:
|
||||
|
||||
Thin3DDepthStencilState *CreateDepthStencilState(bool depthTestEnabled, bool depthWriteEnabled, T3DComparison depthCompare);
|
||||
Thin3DBlendState *CreateBlendState(const T3DBlendStateDesc &desc) override;
|
||||
Thin3DSamplerState *CreateSamplerState(const T3DSamplerStateDesc &desc) override;
|
||||
Thin3DBuffer *CreateBuffer(size_t size, uint32_t usageFlags) override;
|
||||
Thin3DShaderSet *CreateShaderSet(Thin3DShader *vshader, Thin3DShader *fshader) override;
|
||||
Thin3DVertexFormat *CreateVertexFormat(const std::vector<Thin3DVertexComponent> &components, int stride, Thin3DShader *vshader) override;
|
||||
@ -411,6 +442,12 @@ public:
|
||||
Thin3DDX9BlendState *bs = static_cast<Thin3DDX9BlendState *>(state);
|
||||
bs->Apply(device_);
|
||||
}
|
||||
void SetSamplerStates(int start, int count, Thin3DSamplerState **states) {
|
||||
for (int i = 0; i < count; ++i) {
|
||||
Thin3DDX9SamplerState *s = static_cast<Thin3DDX9SamplerState *>(states[start + i]);
|
||||
s->Apply(device_, start + i);
|
||||
}
|
||||
}
|
||||
void SetDepthStencilState(Thin3DDepthStencilState *state) {
|
||||
Thin3DDX9DepthStencilState *bs = static_cast<Thin3DDX9DepthStencilState *>(state);
|
||||
bs->Apply(device_);
|
||||
@ -522,6 +559,16 @@ Thin3DBlendState *Thin3DDX9Context::CreateBlendState(const T3DBlendStateDesc &de
|
||||
return bs;
|
||||
}
|
||||
|
||||
Thin3DSamplerState *Thin3DDX9Context::CreateSamplerState(const T3DSamplerStateDesc &desc) {
|
||||
Thin3DDX9SamplerState *samps = new Thin3DDX9SamplerState();
|
||||
samps->wrapS = texWrapToD3D9[desc.wrapS];
|
||||
samps->wrapT = texWrapToD3D9[desc.wrapT];
|
||||
samps->magFilt = texFilterToD3D9[desc.magFilt];
|
||||
samps->minFilt = texFilterToD3D9[desc.minFilt];
|
||||
samps->mipFilt = texFilterToD3D9[desc.mipFilt];
|
||||
return samps;
|
||||
}
|
||||
|
||||
Thin3DTexture *Thin3DDX9Context::CreateTexture() {
|
||||
Thin3DDX9Texture *tex = new Thin3DDX9Texture(device_, deviceEx_);
|
||||
return tex;
|
||||
@ -625,12 +672,6 @@ void Thin3DDX9Context::Draw(T3DPrimitive prim, Thin3DShaderSet *shaderSet, Thin3
|
||||
Thin3DDX9VertexFormat *fmt = static_cast<Thin3DDX9VertexFormat *>(format);
|
||||
Thin3DDX9ShaderSet *ss = static_cast<Thin3DDX9ShaderSet*>(shaderSet);
|
||||
|
||||
device_->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
|
||||
device_->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
|
||||
device_->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
|
||||
device_->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
|
||||
device_->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
|
||||
|
||||
vbuf->BindAsVertexBuf(device_, fmt->GetStride(), offset);
|
||||
ss->Apply(device_);
|
||||
fmt->Apply(device_);
|
||||
@ -647,19 +688,13 @@ void Thin3DDX9Context::DrawIndexed(T3DPrimitive prim, Thin3DShaderSet *shaderSet
|
||||
fmt->Apply(device_);
|
||||
vbuf->BindAsVertexBuf(device_, fmt->GetStride(), offset);
|
||||
ibuf->BindAsIndexBuf(device_);
|
||||
device_->DrawIndexedPrimitive(primToD3D9[prim], 0, 0, vertexCount, 0, vertexCount / 3);
|
||||
device_->DrawIndexedPrimitive(primToD3D9[prim], 0, 0, vertexCount, 0, vertexCount / primCountDivisor[prim]);
|
||||
}
|
||||
|
||||
void Thin3DDX9Context::DrawUP(T3DPrimitive prim, Thin3DShaderSet *shaderSet, Thin3DVertexFormat *format, const void *vdata, int vertexCount) {
|
||||
Thin3DDX9VertexFormat *fmt = static_cast<Thin3DDX9VertexFormat *>(format);
|
||||
Thin3DDX9ShaderSet *ss = static_cast<Thin3DDX9ShaderSet*>(shaderSet);
|
||||
|
||||
device_->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
|
||||
device_->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
|
||||
device_->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
|
||||
device_->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
|
||||
device_->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
|
||||
|
||||
ss->Apply(device_);
|
||||
fmt->Apply(device_);
|
||||
device_->DrawPrimitiveUP(primToD3D9[prim], vertexCount / 3, vdata, fmt->GetStride());
|
||||
@ -757,10 +792,10 @@ void Thin3DDX9Shader::SetVector(LPDIRECT3DDEVICE9 device, const char *name, floa
|
||||
}
|
||||
}
|
||||
|
||||
void Thin3DDX9Shader::SetMatrix4x4(LPDIRECT3DDEVICE9 device, const char *name, const Matrix4x4 &value) {
|
||||
void Thin3DDX9Shader::SetMatrix4x4(LPDIRECT3DDEVICE9 device, const char *name, const float value[16]) {
|
||||
D3DXHANDLE handle = constantTable_->GetConstantByName(NULL, name);
|
||||
if (handle) {
|
||||
constantTable_->SetFloatArray(device, handle, value.getReadPtr(), 16);
|
||||
constantTable_->SetFloatArray(device, handle, value, 16);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,6 +43,23 @@ static const unsigned short blendFactorToGL[] = {
|
||||
GL_CONSTANT_COLOR,
|
||||
};
|
||||
|
||||
static const unsigned short texWrapToGL[] = {
|
||||
GL_REPEAT,
|
||||
GL_CLAMP_TO_EDGE,
|
||||
};
|
||||
|
||||
static const unsigned short texFilterToGL[] = {
|
||||
GL_NEAREST,
|
||||
GL_LINEAR,
|
||||
};
|
||||
|
||||
static const unsigned short texMipFilterToGL[2][2] = {
|
||||
// Min nearest:
|
||||
{ GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR },
|
||||
// Min linear:
|
||||
{ GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR },
|
||||
};
|
||||
|
||||
#ifndef USING_GLES2
|
||||
static const unsigned short logicOpToGL[] = {
|
||||
GL_CLEAR,
|
||||
@ -108,6 +125,32 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class Thin3DGLSamplerState : public Thin3DSamplerState {
|
||||
public:
|
||||
GLint wrapS;
|
||||
GLint wrapT;
|
||||
GLint magFilt;
|
||||
GLint minFilt;
|
||||
GLint mipMinFilt;
|
||||
|
||||
void Apply(bool hasMips, bool canWrap) {
|
||||
if (canWrap) {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapS);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapT);
|
||||
} else {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
}
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilt);
|
||||
if (hasMips) {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, mipMinFilt);
|
||||
} else {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilt);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class Thin3DGLDepthStencilState : public Thin3DDepthStencilState {
|
||||
public:
|
||||
bool depthTestEnabled;
|
||||
@ -278,7 +321,7 @@ public:
|
||||
int GetUniformLoc(const char *name);
|
||||
|
||||
void SetVector(const char *name, float *value, int n) override;
|
||||
void SetMatrix4x4(const char *name, const Matrix4x4 &value) override;
|
||||
void SetMatrix4x4(const char *name, const float value[16]) override;
|
||||
|
||||
void GLRestore() override {
|
||||
vshader->Compile(vshader->GetSource().c_str());
|
||||
@ -301,6 +344,7 @@ public:
|
||||
|
||||
Thin3DDepthStencilState *CreateDepthStencilState(bool depthTestEnabled, bool depthWriteEnabled, T3DComparison depthCompare) override;
|
||||
Thin3DBlendState *CreateBlendState(const T3DBlendStateDesc &desc) override;
|
||||
Thin3DSamplerState *CreateSamplerState(const T3DSamplerStateDesc &desc) override;
|
||||
Thin3DBuffer *CreateBuffer(size_t size, uint32_t usageFlags) override;
|
||||
Thin3DShaderSet *CreateShaderSet(Thin3DShader *vshader, Thin3DShader *fshader) override;
|
||||
Thin3DVertexFormat *CreateVertexFormat(const std::vector<Thin3DVertexComponent> &components, int stride, Thin3DShader *vshader) override;
|
||||
@ -313,6 +357,28 @@ public:
|
||||
s->Apply();
|
||||
}
|
||||
|
||||
void SetSamplerStates(int start, int count, Thin3DSamplerState **states) override {
|
||||
if (samplerStates_.size() < (size_t)(start + count)) {
|
||||
samplerStates_.resize(start + count);
|
||||
}
|
||||
for (int i = 0; i < count; ++i) {
|
||||
int index = i + start;
|
||||
Thin3DGLSamplerState *s = static_cast<Thin3DGLSamplerState *>(states[index]);
|
||||
|
||||
if (samplerStates_[index]) {
|
||||
samplerStates_[index]->Release();
|
||||
}
|
||||
samplerStates_[index] = s;
|
||||
samplerStates_[index]->AddRef();
|
||||
|
||||
// TODO: Ideally, get these from the texture and apply on the right stage?
|
||||
if (index == 0) {
|
||||
s->Apply(false, true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Bound state objects
|
||||
void SetDepthStencilState(Thin3DDepthStencilState *state) override {
|
||||
Thin3DGLDepthStencilState *s = static_cast<Thin3DGLDepthStencilState *>(state);
|
||||
@ -385,6 +451,8 @@ public:
|
||||
default: return "?";
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<Thin3DGLSamplerState *> samplerStates_;
|
||||
};
|
||||
|
||||
Thin3DGLContext::Thin3DGLContext() {
|
||||
@ -392,6 +460,12 @@ Thin3DGLContext::Thin3DGLContext() {
|
||||
}
|
||||
|
||||
Thin3DGLContext::~Thin3DGLContext() {
|
||||
for (Thin3DGLSamplerState *s : samplerStates_) {
|
||||
if (s) {
|
||||
s->Release();
|
||||
}
|
||||
}
|
||||
samplerStates_.clear();
|
||||
}
|
||||
|
||||
Thin3DVertexFormat *Thin3DGLContext::CreateVertexFormat(const std::vector<Thin3DVertexComponent> &components, int stride, Thin3DShader *vshader) {
|
||||
@ -422,6 +496,7 @@ class Thin3DGLTexture : public Thin3DTexture, GfxResourceHolder {
|
||||
public:
|
||||
Thin3DGLTexture() : tex_(0), target_(0) {
|
||||
generatedMips_ = false;
|
||||
canWrap_ = true;
|
||||
width_ = 0;
|
||||
height_ = 0;
|
||||
depth_ = 0;
|
||||
@ -430,6 +505,7 @@ public:
|
||||
}
|
||||
Thin3DGLTexture(T3DTextureType type, T3DImageFormat format, int width, int height, int depth, int mipLevels) : tex_(0), target_(TypeToTarget(type)), format_(format), mipLevels_(mipLevels) {
|
||||
generatedMips_ = false;
|
||||
canWrap_ = true;
|
||||
width_ = width;
|
||||
height_ = height;
|
||||
depth_ = depth;
|
||||
@ -443,6 +519,7 @@ public:
|
||||
|
||||
bool Create(T3DTextureType type, T3DImageFormat format, int width, int height, int depth, int mipLevels) override {
|
||||
generatedMips_ = false;
|
||||
canWrap_ = true;
|
||||
format_ = format;
|
||||
target_ = TypeToTarget(type);
|
||||
mipLevels_ = mipLevels;
|
||||
@ -462,6 +539,13 @@ public:
|
||||
void SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, const uint8_t *data) override;
|
||||
void AutoGenMipmaps() override;
|
||||
|
||||
bool HasMips() {
|
||||
return mipLevels_ > 1 || generatedMips_;
|
||||
}
|
||||
bool CanWrap() {
|
||||
return canWrap_;
|
||||
}
|
||||
|
||||
void Bind() {
|
||||
glBindTexture(target_, tex_);
|
||||
}
|
||||
@ -491,6 +575,7 @@ private:
|
||||
T3DImageFormat format_;
|
||||
int mipLevels_;
|
||||
bool generatedMips_;
|
||||
bool canWrap_;
|
||||
};
|
||||
|
||||
Thin3DTexture *Thin3DGLContext::CreateTexture() {
|
||||
@ -505,6 +590,7 @@ void Thin3DGLTexture::AutoGenMipmaps() {
|
||||
if (!generatedMips_) {
|
||||
Bind();
|
||||
glGenerateMipmap(target_);
|
||||
// TODO: Really, this should follow the sampler state.
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
|
||||
generatedMips_ = true;
|
||||
}
|
||||
@ -528,6 +614,11 @@ void Thin3DGLTexture::SetImageData(int x, int y, int z, int width, int height, i
|
||||
default:
|
||||
return;
|
||||
}
|
||||
if (level == 0) {
|
||||
width_ = width;
|
||||
height_ = height;
|
||||
depth_ = depth;
|
||||
}
|
||||
|
||||
Bind();
|
||||
switch (target_) {
|
||||
@ -545,17 +636,7 @@ bool isPowerOf2(int n) {
|
||||
}
|
||||
|
||||
void Thin3DGLTexture::Finalize(int zim_flags) {
|
||||
GLenum wrap = GL_REPEAT;
|
||||
if ((zim_flags & ZIM_CLAMP) || !isPowerOf2(width_) || !isPowerOf2(height_))
|
||||
wrap = GL_CLAMP_TO_EDGE;
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
if ((zim_flags & (ZIM_HAS_MIPS | ZIM_GEN_MIPS))) {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
|
||||
} else {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
}
|
||||
canWrap_ = (zim_flags & ZIM_CLAMP) || !isPowerOf2(width_) || !isPowerOf2(height_);
|
||||
}
|
||||
|
||||
|
||||
@ -610,6 +691,16 @@ Thin3DBlendState *Thin3DGLContext::CreateBlendState(const T3DBlendStateDesc &des
|
||||
return bs;
|
||||
}
|
||||
|
||||
Thin3DSamplerState *Thin3DGLContext::CreateSamplerState(const T3DSamplerStateDesc &desc) {
|
||||
Thin3DGLSamplerState *samps = new Thin3DGLSamplerState();
|
||||
samps->wrapS = texWrapToGL[desc.wrapS];
|
||||
samps->wrapT = texWrapToGL[desc.wrapT];
|
||||
samps->magFilt = texFilterToGL[desc.magFilt];
|
||||
samps->minFilt = texFilterToGL[desc.minFilt];
|
||||
samps->mipMinFilt = texMipFilterToGL[desc.minFilt][desc.mipFilt];
|
||||
return samps;
|
||||
}
|
||||
|
||||
Thin3DBuffer *Thin3DGLContext::CreateBuffer(size_t size, uint32_t usageFlags) {
|
||||
return new Thin3DGLBuffer(size, usageFlags);
|
||||
}
|
||||
@ -637,6 +728,10 @@ void Thin3DGLContext::SetTextures(int start, int count, Thin3DTexture **textures
|
||||
Thin3DGLTexture *glTex = static_cast<Thin3DGLTexture *>(textures[i]);
|
||||
glActiveTexture(GL_TEXTURE0 + i);
|
||||
glTex->Bind();
|
||||
|
||||
if (samplerStates_.size() > i && samplerStates_[i]) {
|
||||
samplerStates_[i]->Apply(glTex->HasMips(), glTex->CanWrap());
|
||||
}
|
||||
}
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
}
|
||||
@ -737,11 +832,11 @@ void Thin3DGLShaderSet::SetVector(const char *name, float *value, int n) {
|
||||
}
|
||||
}
|
||||
|
||||
void Thin3DGLShaderSet::SetMatrix4x4(const char *name, const Matrix4x4 &value) {
|
||||
void Thin3DGLShaderSet::SetMatrix4x4(const char *name, const float value[16]) {
|
||||
glUseProgram(program_);
|
||||
int loc = GetUniformLoc(name);
|
||||
if (loc != -1) {
|
||||
glUniformMatrix4fv(loc, 1, false, value.getReadPtr());
|
||||
glUniformMatrix4fv(loc, 1, false, value);
|
||||
}
|
||||
}
|
||||
|
||||
@ -791,8 +886,8 @@ void Thin3DGLContext::DrawIndexed(T3DPrimitive prim, Thin3DShaderSet *shaderSet,
|
||||
ss->Apply();
|
||||
// Note: ibuf binding is stored in the VAO, so call this after binding the fmt.
|
||||
ibuf->Bind();
|
||||
|
||||
glDrawElements(primToGL[prim], offset, GL_INT, 0);
|
||||
|
||||
glDrawElements(primToGL[prim], vertexCount, GL_UNSIGNED_INT, (const void *)(size_t)offset);
|
||||
|
||||
ss->Unapply();
|
||||
fmt->Unapply();
|
||||
@ -805,6 +900,8 @@ void Thin3DGLContext::DrawUP(T3DPrimitive prim, Thin3DShaderSet *shaderSet, Thin
|
||||
fmt->Apply(vdata);
|
||||
ss->Apply();
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
glDrawArrays(primToGL[prim], 0, vertexCount);
|
||||
|
||||
ss->Unapply();
|
||||
|
@ -23,6 +23,7 @@ UIContext::~UIContext() {
|
||||
void UIContext::Init(Thin3DContext *thin3d, Thin3DShaderSet *uishader, Thin3DShaderSet *uishadernotex, Thin3DTexture *uitexture, DrawBuffer *uidrawbuffer, DrawBuffer *uidrawbufferTop) {
|
||||
thin3d_ = thin3d;
|
||||
blend_ = thin3d_->GetBlendStatePreset(T3DBlendStatePreset::BS_STANDARD_ALPHA);
|
||||
sampler_ = thin3d_->GetSamplerStatePreset(T3DSamplerStatePreset::SAMPS_LINEAR);
|
||||
depth_ = thin3d_->CreateDepthStencilState(false, false, T3DComparison::LESS);
|
||||
|
||||
uishader_ = uishader;
|
||||
@ -39,6 +40,7 @@ void UIContext::Init(Thin3DContext *thin3d, Thin3DShaderSet *uishader, Thin3DSha
|
||||
|
||||
void UIContext::Begin() {
|
||||
thin3d_->SetBlendState(blend_);
|
||||
thin3d_->SetSamplerStates(0, 1, &sampler_);
|
||||
thin3d_->SetDepthStencilState(depth_);
|
||||
thin3d_->SetRenderState(T3DRenderState::CULL_MODE, T3DCullMode::NO_CULL);
|
||||
thin3d_->SetTexture(0, uitexture_);
|
||||
@ -48,6 +50,7 @@ void UIContext::Begin() {
|
||||
|
||||
void UIContext::BeginNoTex() {
|
||||
thin3d_->SetBlendState(blend_);
|
||||
thin3d_->SetSamplerStates(0, 1, &sampler_);
|
||||
thin3d_->SetRenderState(T3DRenderState::CULL_MODE, T3DCullMode::NO_CULL);
|
||||
|
||||
UIBegin(uishadernotex_);
|
||||
|
@ -14,6 +14,7 @@ class Thin3DShaderSet;
|
||||
class Thin3DDepthStencilState;
|
||||
class Thin3DTexture;
|
||||
class Thin3DBlendState;
|
||||
class Thin3DSamplerState;
|
||||
class Texture;
|
||||
class DrawBuffer;
|
||||
class TextDrawer;
|
||||
@ -82,6 +83,7 @@ private:
|
||||
Thin3DContext *thin3D_;
|
||||
Thin3DDepthStencilState *depth_;
|
||||
Thin3DBlendState *blend_;
|
||||
Thin3DSamplerState *sampler_;
|
||||
Thin3DShaderSet *uishader_;
|
||||
Thin3DShaderSet *uishadernotex_;
|
||||
Thin3DTexture *uitexture_;
|
||||
|
Loading…
Reference in New Issue
Block a user