mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-05 10:36:17 +02:00
Add Thin3d support to draw_text (Qt not touched)
This commit is contained in:
1 parent
a1ff7a4488
commit
ff5df25135
7 files changed
+112
-43
No files matched your search
+12
-15
@@ -1,9 +1,9 @@
|
||||
#include "base/logging.h"
|
||||
#include "base/stringutil.h"
|
||||
#include "gfx/gl_common.h"
|
||||
#include "gfx_es2/draw_text.h"
|
||||
#include "thin3d/thin3d.h"
|
||||
#include "util/hash/hash.h"
|
||||
#include "util/text/utf8.h"
|
||||
#include "gfx_es2/draw_text.h"
|
||||
|
||||
#ifdef USING_QT_UI
|
||||
#include <QtGui/QImage>
|
||||
@@ -32,9 +32,10 @@ struct TextDrawerContext {
|
||||
int *pBitmapBits;
|
||||
};
|
||||
|
||||
TextDrawer::TextDrawer() {
|
||||
TextDrawer::TextDrawer(Thin3DContext *thin3d) : thin3d_(thin3d), ctx_(NULL) {
|
||||
fontScaleX_ = 1.0f;
|
||||
fontScaleY_ = 1.0f;
|
||||
|
||||
ctx_ = new TextDrawerContext();
|
||||
ctx_->hDC = CreateCompatibleDC(NULL);
|
||||
|
||||
@@ -55,7 +56,7 @@ TextDrawer::TextDrawer() {
|
||||
|
||||
TextDrawer::~TextDrawer() {
|
||||
for (auto iter = cache_.begin(); iter != cache_.end(); ++iter) {
|
||||
glDeleteTextures(1, &iter->second->textureHandle);
|
||||
iter->second->texture->Release();
|
||||
delete iter->second;
|
||||
}
|
||||
cache_.clear();
|
||||
@@ -123,6 +124,9 @@ void TextDrawer::MeasureString(const char *str, float *w, float *h) {
|
||||
}
|
||||
|
||||
void TextDrawer::DrawString(DrawBuffer &target, const char *str, float x, float y, uint32_t color, int align) {
|
||||
if (!strlen(str))
|
||||
return;
|
||||
|
||||
uint32_t stringHash = hash::Fletcher((const uint8_t *)str, strlen(str));
|
||||
uint32_t entryHash = stringHash ^ fontHash_;
|
||||
|
||||
@@ -134,7 +138,7 @@ void TextDrawer::DrawString(DrawBuffer &target, const char *str, float x, float
|
||||
if (iter != cache_.end()) {
|
||||
entry = iter->second;
|
||||
entry->lastUsedFrame = frameCount_;
|
||||
glBindTexture(GL_TEXTURE_2D, entry->textureHandle);
|
||||
thin3d_->SetTexture(0, entry->texture);
|
||||
} else {
|
||||
// Render the string to our bitmap and save to a GL texture.
|
||||
std::wstring wstr = ConvertUTF8ToWString(ReplaceAll(str, "\n", "\r\n"));
|
||||
@@ -163,30 +167,23 @@ void TextDrawer::DrawString(DrawBuffer &target, const char *str, float x, float
|
||||
DrawTextExW(ctx_->hDC, (LPWSTR)wstr.c_str(), (int)wstr.size(), &rc, DT_HIDEPREFIX|DT_TOP|DT_LEFT, 0);
|
||||
|
||||
entry = new TextStringEntry();
|
||||
glGenTextures(1, &entry->textureHandle);
|
||||
glBindTexture(GL_TEXTURE_2D, entry->textureHandle);
|
||||
entry->width = size.cx;
|
||||
entry->height = size.cy;
|
||||
entry->bmWidth = (size.cx + 3) & ~3;
|
||||
entry->bmHeight = (size.cy + 3) & ~3;
|
||||
entry->lastUsedFrame = frameCount_;
|
||||
entry->texture = thin3d_->CreateTexture(LINEAR2D, RGBA4444, entry->bmWidth, entry->bmHeight, 1, 0);
|
||||
|
||||
// Convert the bitmap to a gl-compatible array of pixels.
|
||||
uint16_t *bitmapData = new uint16_t[entry->bmWidth * entry->bmHeight];
|
||||
|
||||
for (int y = 0; y < entry->bmHeight; y++) {
|
||||
for (int x = 0; x < entry->bmWidth; x++) {
|
||||
BYTE bAlpha = (BYTE)((ctx_->pBitmapBits[MAX_TEXT_WIDTH * y + x] & 0xff) >> 4);
|
||||
bitmapData[entry->bmWidth * y + x] = (bAlpha) | 0xfff0; // ^ rand();
|
||||
}
|
||||
}
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, entry->bmWidth, entry->bmHeight, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, bitmapData);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
|
||||
entry->texture->SetImageData(0, 0, 0, entry->bmWidth, entry->bmHeight, 1, 0, entry->bmWidth * 2, (const uint8_t *)bitmapData);
|
||||
entry->texture->Finalize(0);
|
||||
delete [] bitmapData;
|
||||
|
||||
cache_[entryHash] = entry;
|
||||
|
||||
+14
-2
@@ -12,13 +12,23 @@
|
||||
|
||||
#include "base/basictypes.h"
|
||||
#include "gfx_es2/draw_buffer.h"
|
||||
#if !(defined(_WIN32) && !defined(USING_QT_UI))
|
||||
#include "gfx_es2/gl_state.h"
|
||||
#endif
|
||||
|
||||
class Thin3DContext;
|
||||
class Thin3DTexture;
|
||||
|
||||
#ifdef USING_QT_UI
|
||||
#include <QtGui/QFont>
|
||||
#endif
|
||||
|
||||
struct TextStringEntry {
|
||||
uint32_t textureHandle;
|
||||
#if defined(_WIN32) && !defined(USING_QT_UI)
|
||||
Thin3DTexture *texture;
|
||||
#else
|
||||
GLuint textureHandle;
|
||||
#endif
|
||||
int width;
|
||||
int height;
|
||||
int bmWidth;
|
||||
@@ -38,7 +48,7 @@ struct TextDrawerFontContext;
|
||||
|
||||
class TextDrawer {
|
||||
public:
|
||||
TextDrawer();
|
||||
TextDrawer(Thin3DContext *thin3d);
|
||||
~TextDrawer();
|
||||
|
||||
uint32_t SetFont(const char *fontName, int size, int flags);
|
||||
@@ -52,6 +62,8 @@ public:
|
||||
void OncePerFrame();
|
||||
|
||||
private:
|
||||
Thin3DContext *thin3d_;
|
||||
|
||||
int frameCount_;
|
||||
float fontScaleX_;
|
||||
float fontScaleY_;
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ static const char * const hlslFsTexCol =
|
||||
"struct PS_INPUT { float4 color : COLOR0; float2 uv : TEXCOORD0; };\n"
|
||||
"sampler2D tex0 : register(s0);\n"
|
||||
"float4 main(PS_INPUT input) : COLOR0 {\n"
|
||||
" return input.color * tex2D(tex0, input.uv).bgra;\n"
|
||||
" return input.color * tex2D(tex0, input.uv);\n"
|
||||
"}\n";
|
||||
|
||||
static const char * const glsl_fsCol =
|
||||
|
||||
+11
-2
@@ -147,7 +147,7 @@ public:
|
||||
|
||||
class Thin3DTexture : public Thin3DObject {
|
||||
public:
|
||||
virtual void SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, uint8_t *data) = 0;
|
||||
virtual void SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, const uint8_t *data) = 0;
|
||||
virtual void AutoGenMipmaps() = 0;
|
||||
virtual void Finalize(int zim_flags) = 0; // TODO: Tidy up
|
||||
|
||||
@@ -210,6 +210,7 @@ enum T3DTextureType : uint8_t {
|
||||
enum T3DImageFormat : uint8_t {
|
||||
LUMINANCE,
|
||||
RGBA8888,
|
||||
RGBA4444,
|
||||
DXT1,
|
||||
ETC1, // Needs simulation on many platforms
|
||||
D16,
|
||||
@@ -234,6 +235,14 @@ enum T3DFileType {
|
||||
DETECT,
|
||||
};
|
||||
|
||||
enum T3DInfo {
|
||||
APINAME,
|
||||
APIVERSION,
|
||||
VENDOR,
|
||||
SHADELANGVERSION,
|
||||
RENDERER,
|
||||
};
|
||||
|
||||
class Thin3DContext : public Thin3DObject {
|
||||
public:
|
||||
virtual ~Thin3DContext();
|
||||
@@ -287,7 +296,7 @@ public:
|
||||
targetHeight_ = h;
|
||||
}
|
||||
|
||||
virtual const char *GetAPIName() const = 0;
|
||||
virtual const char *GetInfoString(T3DInfo info) const = 0;
|
||||
|
||||
protected:
|
||||
void CreatePresets();
|
||||
|
||||
+45
-4
@@ -214,7 +214,7 @@ private:
|
||||
class Thin3DDX9Texture : public Thin3DTexture {
|
||||
public:
|
||||
Thin3DDX9Texture(LPDIRECT3DDEVICE9 device, T3DTextureType type, T3DImageFormat format, int width, int height, int depth, int mipLevels);
|
||||
void SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, uint8_t *data) override;
|
||||
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 {}
|
||||
void SetToSampler(LPDIRECT3DDEVICE9 device, int sampler);
|
||||
void Finalize(int zim_flags) override {}
|
||||
@@ -230,6 +230,7 @@ private:
|
||||
D3DFORMAT FormatToD3D(T3DImageFormat fmt) {
|
||||
switch (fmt) {
|
||||
case RGBA8888: return D3DFMT_A8R8G8B8;
|
||||
case RGBA4444: return D3DFMT_A4R4G4B4;
|
||||
case D24S8: return D3DFMT_D24S8;
|
||||
case D16: return D3DFMT_D16;
|
||||
default: return D3DFMT_UNKNOWN;
|
||||
@@ -256,9 +257,22 @@ Thin3DDX9Texture::Thin3DDX9Texture(LPDIRECT3DDEVICE9 device, T3DTextureType type
|
||||
hr = device->CreateCubeTexture(width, mipLevels, 0, fmt_, D3DPOOL_MANAGED, &cubeTex_, NULL);
|
||||
break;
|
||||
}
|
||||
if (FAILED(hr)) {
|
||||
ELOG("Texture creation failed");
|
||||
}
|
||||
}
|
||||
|
||||
void Thin3DDX9Texture::SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, uint8_t *data) {
|
||||
inline uint16_t Shuffle4444(uint16_t x) {
|
||||
return (x << 12) | (x >> 4);
|
||||
}
|
||||
|
||||
// A rather different transform, for curious reasons..
|
||||
inline uint32_t Shuffle8888(uint32_t x) {
|
||||
return (x & 0xFF00FF00) | ((x >> 16) & 0xFF) | ((x << 16) & 0xFF0000);
|
||||
}
|
||||
|
||||
|
||||
void Thin3DDX9Texture::SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, const uint8_t *data) {
|
||||
if (!tex_) {
|
||||
return;
|
||||
}
|
||||
@@ -274,8 +288,25 @@ void Thin3DDX9Texture::SetImageData(int x, int y, int z, int width, int height,
|
||||
D3DLOCKED_RECT rect;
|
||||
if (x == 0 && y == 0) {
|
||||
tex_->LockRect(level, &rect, NULL, D3DLOCK_DISCARD);
|
||||
|
||||
for (int i = 0; i < height; i++) {
|
||||
memcpy((uint8_t *)rect.pBits + rect.Pitch * i, data + stride * i, width * 4);
|
||||
uint8_t *dest = (uint8_t *)rect.pBits + rect.Pitch * i;
|
||||
const uint8_t *source = data + stride * i;
|
||||
int j;
|
||||
switch (fmt_) {
|
||||
case D3DFMT_A4R4G4B4:
|
||||
// This is backwards from OpenGL so we need to shuffle around a bit.
|
||||
for (j = 0; j < width; j++) {
|
||||
((uint16_t *)dest)[j] = Shuffle4444(((uint16_t *)source)[j]);
|
||||
}
|
||||
break;
|
||||
|
||||
case D3DFMT_A8R8G8B8:
|
||||
for (j = 0; j < width; j++) {
|
||||
((uint32_t *)dest)[j] = Shuffle8888(((uint32_t *)source)[j]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
tex_->UnlockRect(level);
|
||||
}
|
||||
@@ -344,7 +375,17 @@ public:
|
||||
void DrawIndexed(T3DPrimitive prim, Thin3DShaderSet *pipeline, Thin3DVertexFormat *format, Thin3DBuffer *vdata, Thin3DBuffer *idata, int vertexCount, int offset) override;
|
||||
void Clear(int mask, uint32_t colorval, float depthVal, int stencilVal);
|
||||
|
||||
const char *GetAPIName() const override { return "Direct3D9"; }
|
||||
const char *GetInfoString(T3DInfo info) const override {
|
||||
// TODO: Make these actually query the right information
|
||||
switch (info) {
|
||||
case APIVERSION: return "DirectX 9.0";
|
||||
case VENDOR: return "?";
|
||||
case RENDERER: return "?";
|
||||
case SHADELANGVERSION: return "3.0";
|
||||
case APINAME: return "Direct3D 9";
|
||||
default: return "?";
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
// void CompileShader(const char *hlsl_source);
|
||||
|
||||
+28
-18
@@ -279,12 +279,21 @@ public:
|
||||
void DrawIndexed(T3DPrimitive prim, Thin3DShaderSet *shaderSet, Thin3DVertexFormat *format, Thin3DBuffer *vdata, Thin3DBuffer *idata, int vertexCount, int offset) override;
|
||||
void Clear(int mask, uint32_t colorval, float depthVal, int stencilVal) override;
|
||||
|
||||
const char *GetAPIName() const override {
|
||||
#ifdef USING_GLES2
|
||||
return "OpenGL ES";
|
||||
#else
|
||||
return "OpenGL";
|
||||
#endif
|
||||
const char *GetInfoString(T3DInfo info) const override {
|
||||
// TODO: Make these actually query the right information
|
||||
switch (info) {
|
||||
case APINAME:
|
||||
#ifdef USING_GLES2
|
||||
return "OpenGL ES";
|
||||
#else
|
||||
return "OpenGL";
|
||||
#endif
|
||||
case VENDOR: return (const char *)glGetString(GL_VENDOR);
|
||||
case RENDERER: return (const char *)glGetString(GL_RENDERER);
|
||||
case SHADELANGVERSION: return (const char *)glGetString(GL_SHADING_LANGUAGE_VERSION);
|
||||
case APIVERSION: return (const char *)glGetString(GL_VERSION);
|
||||
default: return "?";
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
@@ -318,13 +327,16 @@ GLuint TypeToTarget(T3DTextureType type) {
|
||||
|
||||
class Thin3DGLTexture : public Thin3DTexture {
|
||||
public:
|
||||
Thin3DGLTexture(T3DTextureType type, T3DImageFormat format, int mipLevels) : format_(format), tex_(0), target_(TypeToTarget(type)), mipLevels_(mipLevels) {
|
||||
Thin3DGLTexture(T3DTextureType type, T3DImageFormat format, int width, int height, int depth, int mipLevels) : format_(format), tex_(0), target_(TypeToTarget(type)), mipLevels_(mipLevels) {
|
||||
width_ = width;
|
||||
height_ = height;
|
||||
depth_ = depth;
|
||||
glGenTextures(1, &tex_);
|
||||
}
|
||||
~Thin3DGLTexture() {
|
||||
glDeleteTextures(1, &tex_);
|
||||
}
|
||||
void SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, uint8_t *data) override;
|
||||
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;
|
||||
|
||||
void Bind() {
|
||||
@@ -341,8 +353,7 @@ private:
|
||||
};
|
||||
|
||||
Thin3DTexture *Thin3DGLContext::CreateTexture(T3DTextureType type, T3DImageFormat format, int width, int height, int depth, int mipLevels) {
|
||||
Thin3DGLTexture *tex = new Thin3DGLTexture(type, format, mipLevels);
|
||||
return tex;
|
||||
return new Thin3DGLTexture(type, format, width, height, depth, mipLevels);
|
||||
}
|
||||
|
||||
void Thin3DGLTexture::AutoGenMipmaps() {
|
||||
@@ -350,13 +361,7 @@ void Thin3DGLTexture::AutoGenMipmaps() {
|
||||
glGenerateMipmap(target_);
|
||||
}
|
||||
|
||||
void Thin3DGLTexture::SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, uint8_t *data) {
|
||||
if (level == 0) {
|
||||
width_ = width;
|
||||
height_ = height;
|
||||
depth_ = depth;
|
||||
}
|
||||
|
||||
void Thin3DGLTexture::SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, const uint8_t *data) {
|
||||
int internalFormat;
|
||||
int format;
|
||||
int type;
|
||||
@@ -366,6 +371,11 @@ void Thin3DGLTexture::SetImageData(int x, int y, int z, int width, int height, i
|
||||
format = GL_RGBA;
|
||||
type = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
case RGBA4444:
|
||||
internalFormat = GL_RGBA;
|
||||
format = GL_RGBA;
|
||||
type = GL_UNSIGNED_SHORT_4_4_4_4;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
@@ -373,7 +383,7 @@ void Thin3DGLTexture::SetImageData(int x, int y, int z, int width, int height, i
|
||||
glBindTexture(target_, tex_);
|
||||
switch (target_) {
|
||||
case GL_TEXTURE_2D:
|
||||
glTexImage2D(GL_TEXTURE_2D, level, internalFormat, width, height, 0, format, type, data);
|
||||
glTexImage2D(GL_TEXTURE_2D, level, internalFormat, width_, height_, 0, format, type, data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -30,7 +30,7 @@ void UIContext::Init(Thin3DContext *thin3d, Thin3DShaderSet *uishader, Thin3DSha
|
||||
uidrawbuffer_ = uidrawbuffer;
|
||||
uidrawbufferTop_ = uidrawbufferTop;
|
||||
#if defined(_WIN32) || defined(USING_QT_UI)
|
||||
textDrawer_ = new TextDrawer();
|
||||
textDrawer_ = new TextDrawer(thin3d);
|
||||
#else
|
||||
textDrawer_ = 0;
|
||||
#endif
|
||||
|
||||
Reference in new issue
Block a user