softgpu: Fix incorrect depth buffer write base address.

softgpu: Implement framebuffer pixel formats different than RGBA8888.
softgpu: Move texel decoding functions to a separate header.
This commit is contained in:
Tony Wasserka 2013-07-21 19:15:28 +02:00 committed by neobrain
parent b2d4df2ddf
commit a013aad6f1
6 changed files with 169 additions and 54 deletions

View File

@ -163,6 +163,7 @@
<ClInclude Include="Math3D.h" />
<ClInclude Include="Null\NullGpu.h" />
<ClInclude Include="Software\Clipper.h" />
<ClInclude Include="Software\Colors.h" />
<ClInclude Include="Software\Lighting.h" />
<ClInclude Include="Software\Rasterizer.h" />
<ClInclude Include="Software\SoftGpu.h" />

View File

@ -68,6 +68,9 @@
<ClInclude Include="GLES\TextureScaler.h">
<Filter>GLES</Filter>
</ClInclude>
<ClInclude Include="Software\Colors.h">
<Filter>Software</Filter>
</ClInclude>
<ClInclude Include="Software\Clipper.h">
<Filter>Software</Filter>
</ClInclude>

View File

@ -211,6 +211,7 @@ struct GPUgstate
float tgenMatrix[12];
float boneMatrix[12 * 8]; // Eight bone matrices.
GEBufferFormat FrameBufFormat() const { return static_cast<GEBufferFormat>(framebufpixformat & 3); }
int FrameBufStride() const { return fbwidth&0x7C0; }
int DepthBufStride() const { return fbwidth&0x7C0; }

104
GPU/Software/Colors.h Normal file
View File

@ -0,0 +1,104 @@
// Copyright (c) 2013- PPSSPP Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0 or later versions.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#pragma once
#include "CommonTypes.h"
static inline u32 DecodeRGBA4444(u16 src)
{
u8 r = (src>>12) & 0x0F;
u8 g = (src>>8) & 0x0F;
u8 b = (src>>4) & 0x0F;
u8 a = (src>>0) & 0x0F;
r = (r << 4) | r;
g = (g << 4) | g;
b = (b << 4) | b;
a = (a << 4) | a;
return (a << 24) | (b << 16) | (g << 8) | r;
}
static inline u32 DecodeRGBA5551(u16 src)
{
u8 r = src & 0x1F;
u8 g = (src >> 5) & 0x1F;
u8 b = (src >> 10) & 0x1F;
u8 a = (src >> 15) & 0x1;
r = (r << 3) | (r >> 2);
g = (g << 3) | (g >> 2);
b = (b << 3) | (b >> 2);
a = (a) ? 0xff : 0;
return (a << 24) | (b << 16) | (g << 8) | r;
}
static inline u32 DecodeRGB565(u16 src)
{
u8 r = src & 0x1F;
u8 g = (src >> 5) & 0x3F;
u8 b = (src >> 11) & 0x1F;
u8 a = 0xFF;
r = (r << 3) | (r >> 2);
g = (g << 2) | (g >> 4);
b = (b << 3) | (b >> 2);
return (a << 24) | (b << 16) | (g << 8) | r;
}
static inline u32 DecodeRGBA8888(u32 src)
{
u8 r = src & 0xFF;
u8 g = (src >> 8) & 0xFF;
u8 b = (src >> 16) & 0xFF;
u8 a = (src >> 24) & 0xFF;
return (a << 24) | (b << 16) | (g << 8) | r;
}
static inline u16 RGBA8888To565(u32 value)
{
u8 r = value & 0xFF;
u8 g = (value >> 8) & 0xFF;
u8 b = (value >> 16) & 0xFF;
r >>= 3;
g >>= 2;
b >>= 3;
return (u16)r | ((u16)g << 5) | ((u16)b << 11);
}
static inline u16 RGBA8888To5551(u32 value)
{
u8 r = value & 0xFF;
u8 g = (value >> 8) & 0xFF;
u8 b = (value >> 16) & 0xFF;
u8 a = (value >> 24) & 0xFF;
r >>= 3;
g >>= 3;
b >>= 3;
a >>= 7;
return (u16)r | ((u16)g << 5) | ((u16)b << 10) | ((u16)a << 15);
}
static inline u16 RGBA8888To4444(u32 value)
{
u8 r = value & 0xFF;
u8 g = (value >> 8) & 0xFF;
u8 b = (value >> 16) & 0xFF;
u8 a = (value >> 24) & 0xFF;
r >>= 4;
g >>= 4;
b >>= 4;
a >>= 4;
return (u16)r | ((u16)g << 4) | ((u16)b << 8) | ((u16)a << 12);
}

View File

@ -19,6 +19,7 @@
#include "../GPUState.h"
#include "Rasterizer.h"
#include "Colors.h"
extern u8* fb;
extern u8* depthbuf;
@ -53,53 +54,6 @@ static inline int GetPixelDataOffset(unsigned int texel_size_bits, unsigned int
return tile_idx * tile_size_bits/8 + ((u % (tile_size_bits / texel_size_bits)));
}
static inline u32 DecodeRGBA4444(u16 src)
{
u8 r = src & 0x0F;
u8 g = (src>>4) & 0x0F;
u8 b = (src>>8) & 0x0F;
u8 a = (src>>12) & 0x0F;
r = (r << 4) | r;
g = (g << 4) | g;
b = (b << 4) | b;
a = (a << 4) | a;
return (a << 24) | (b << 16) | (g << 8) | r;
}
static inline u32 DecodeRGBA5551(u16 src)
{
u8 r = src & 0x1F;
u8 g = (src >> 5) & 0x1F;
u8 b = (src >> 10) & 0x1F;
u8 a = (src >> 15) & 0x1;
r = (r << 3) | (r >> 2);
g = (g << 3) | (g >> 2);
b = (b << 3) | (b >> 2);
a = (a) ? 0xff : 0;
return (a << 24) | (b << 16) | (g << 8) | r;
}
static inline u32 DecodeRGB565(u16 src)
{
u8 r = src & 0x1F;
u8 g = (src >> 5) & 0x3F;
u8 b = (src >> 11) & 0x1F;
u8 a = 0xFF;
r = (r << 3) | (r >> 2);
g = (g << 2) | (g >> 4);
b = (b << 3) | (b >> 2);
return (a << 24) | (b << 16) | (g << 8) | r;
}
static inline u32 DecodeRGBA8888(u32 src)
{
u8 r = src & 0xFF;
u8 g = (src >> 8) & 0xFF;
u8 b = (src >> 16) & 0xFF;
u8 a = (src >> 24) & 0xFF;
return (a << 24) | (b << 16) | (g << 8) | r;
}
static inline u32 LookupColor(unsigned int index, unsigned int level)
{
const bool mipmapShareClut = (gstate.texmode & 0x100) == 0;
@ -199,13 +153,41 @@ static inline u32 SampleNearest(int level, float s, float t)
// NOTE: These likely aren't endian safe
static inline u32 GetPixelColor(int x, int y)
{
// TODO: Fix for other pixel formats!
return *(u32*)&fb[4*x + 4*y*gstate.FrameBufStride()];
switch (gstate.FrameBufFormat()) {
case GE_FORMAT_565:
return DecodeRGB565(*(u16*)&fb[4*x + 4*y*gstate.FrameBufStride()]);
case GE_FORMAT_5551:
return DecodeRGBA5551(*(u16*)&fb[4*x + 4*y*gstate.FrameBufStride()]);
case GE_FORMAT_4444:
return DecodeRGBA4444(*(u16*)&fb[4*x + 4*y*gstate.FrameBufStride()]);
case GE_FORMAT_8888:
return *(u32*)&fb[4*x + 4*y*gstate.FrameBufStride()];
}
return 0;
}
static inline void SetPixelColor(int x, int y, u32 value)
{
*(u32*)&fb[4*x + 4*y*gstate.FrameBufStride()] = value;
switch (gstate.FrameBufFormat()) {
case GE_FORMAT_565:
*(u16*)&fb[4*x + 4*y*gstate.FrameBufStride()] = RGBA8888To565(value);
break;
case GE_FORMAT_5551:
*(u16*)&fb[4*x + 4*y*gstate.FrameBufStride()] = RGBA8888To5551(value);
break;
case GE_FORMAT_4444:
*(u16*)&fb[4*x + 4*y*gstate.FrameBufStride()] = RGBA8888To4444(value);
break;
case GE_FORMAT_8888:
*(u32*)&fb[4*x + 4*y*gstate.FrameBufStride()] = value;
break;
}
}
static inline u16 GetPixelDepth(int x, int y)
@ -220,11 +202,13 @@ static inline void SetPixelDepth(int x, int y, u16 value)
static inline u8 GetPixelStencil(int x, int y)
{
// TODO: Fix for other pixel formats ?
return (((*(u32*)&fb[4*x + 4*y*gstate.FrameBufStride()]) & 0x80000000) != 0) ? 0xFF : 0;
}
static inline void SetPixelStencil(int x, int y, u8 value)
{
// TODO: Fix for other pixel formats ?
*(u32*)&fb[4*x + 4*y*gstate.FrameBufStride()] = (*(u32*)&fb[4*x + 4*y*gstate.FrameBufStride()] & ~0x80000000) | ((value&0x80)<<24);
}

View File

@ -25,6 +25,7 @@
#include "SoftGpu.h"
#include "TransformUnit.h"
#include "Colors.h"
static GLuint temp_texture = 0;
@ -156,7 +157,29 @@ void CopyToCurrentFboFromRam(u8* data, int srcwidth, int srcheight, int dstwidth
glBindTexture(GL_TEXTURE_2D, temp_texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)srcwidth, (GLsizei)srcheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
if (gstate.FrameBufFormat() == GE_FORMAT_8888) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)srcwidth, (GLsizei)srcheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
} 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];
for (int y = 0; y < srcheight; ++y) {
for (int x = 0; x < srcwidth; ++x) {
u16 src = *(u16*)&fb[4*x + 4*y*gstate.FrameBufStride()];
if (gstate.FrameBufFormat() == GE_FORMAT_565)
buf[x+y*srcwidth] = DecodeRGB565(src);
else if (gstate.FrameBufFormat() == GE_FORMAT_5551)
buf[x+y*srcwidth] = DecodeRGBA5551(src);
else if (gstate.FrameBufFormat() == GE_FORMAT_4444)
buf[x+y*srcwidth] = DecodeRGBA4444(src);
}
}
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)srcwidth, (GLsizei)srcheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf);
delete[] buf;
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
@ -255,7 +278,6 @@ void SoftGPU::ExecuteOp(u32 op, u32 diff)
if (type != GE_PRIM_TRIANGLES && type != GE_PRIM_TRIANGLE_STRIP && type != GE_PRIM_RECTANGLES)
break;
// ERROR_LOG(G3D, "DL DrawPrim type: %s count: %i vaddr= %08x, iaddr= %08x", type<7 ? types[type] : "INVALID", count, gstate_c.vertexAddr, gstate_c.indexAddr);
void *verts = Memory::GetPointer(gstate_c.vertexAddr);
@ -542,7 +564,7 @@ void SoftGPU::ExecuteOp(u32 op, u32 diff)
case GE_CMD_ZBUFPTR:
{
u32 ptr = op & 0xFFE000;
depthbuf = Memory::GetPointer(0x44000000 | (gstate.fbptr & 0xFFE000) | ((gstate.fbwidth & 0xFF0000) << 8));
depthbuf = Memory::GetPointer(0x44000000 | (gstate.zbptr & 0xFFE000) | ((gstate.zbwidth & 0xFF0000) << 8));
DEBUG_LOG(G3D,"Zbuf Ptr: %06x", ptr);
}
break;
@ -550,7 +572,7 @@ void SoftGPU::ExecuteOp(u32 op, u32 diff)
case GE_CMD_ZBUFWIDTH:
{
u32 w = data & 0xFFFFFF;
depthbuf = Memory::GetPointer(0x44000000 | (gstate.fbptr & 0xFFE000) | ((gstate.fbwidth & 0xFF0000) << 8));
depthbuf = Memory::GetPointer(0x44000000 | (gstate.zbptr & 0xFFE000) | ((gstate.zbwidth & 0xFF0000) << 8));
DEBUG_LOG(G3D,"Zbuf Width: %i", w);
}
break;