mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-24 14:49:42 -06:00
Hg:
enable newline normalization get revision number via `hg svn info` for svnrev.h ignore incremental/generated binary files (windows/VS at least) leave a comment if some files need native eol set in svnprops git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@5637 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
@ -1,150 +1,150 @@
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "pluginspecs_video.h"
|
||||
#include "../../../Core/VideoCommon/Src/VideoCommon.h"
|
||||
#include "main.h"
|
||||
|
||||
#include "BPMemLoader.h"
|
||||
#include "EfbCopy.h"
|
||||
#include "Rasterizer.h"
|
||||
#include "PixelEngine.h"
|
||||
#include "../../../Core/VideoCommon/Src/TextureDecoder.h"
|
||||
|
||||
|
||||
BPMemory bpmem;
|
||||
|
||||
void InitBPMemory()
|
||||
{
|
||||
memset(&bpmem, 0, sizeof(bpmem));
|
||||
bpmem.bpMask = 0xFFFFFF;
|
||||
}
|
||||
|
||||
void BPWritten(int address, int newvalue);
|
||||
|
||||
void LoadBPReg(u32 value)
|
||||
{
|
||||
//handle the mask register
|
||||
int address = value >> 24;
|
||||
int oldval = ((u32*)&bpmem)[address];
|
||||
int newval = (oldval & ~bpmem.bpMask) | (value & bpmem.bpMask);
|
||||
|
||||
((u32*)&bpmem)[address] = newval;
|
||||
|
||||
//reset the mask register
|
||||
if (address != 0xFE)
|
||||
bpmem.bpMask = 0xFFFFFF;
|
||||
|
||||
BPWritten(address, newval);
|
||||
}
|
||||
|
||||
void BPWritten(int address, int newvalue)
|
||||
{
|
||||
switch (address)
|
||||
{
|
||||
case BPMEM_SCISSORTL:
|
||||
case BPMEM_SCISSORBR:
|
||||
case BPMEM_SCISSOROFFSET:
|
||||
Rasterizer::SetScissor();
|
||||
break;
|
||||
case BPMEM_SETDRAWDONE: // This is called when the game is done drawing (eg: like in DX: Begin(); Draw(); End();)
|
||||
switch (bpmem.drawdone & 0xFF)
|
||||
{
|
||||
case 0x02:
|
||||
PixelEngine::SetFinish(); // may generate interrupt
|
||||
DEBUG_LOG(VIDEO, "GXSetDrawDone SetPEFinish (value: 0x%02X)", (bpmem.drawdone & 0xFFFF));
|
||||
break;
|
||||
|
||||
default:
|
||||
WARN_LOG(VIDEO, "GXSetDrawDone ??? (value 0x%02X)", (bpmem.drawdone & 0xFFFF));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case BPMEM_PE_TOKEN_ID: // Pixel Engine Token ID
|
||||
DEBUG_LOG(VIDEO, "SetPEToken 0x%04x", (bpmem.petoken & 0xFFFF));
|
||||
PixelEngine::SetToken(static_cast<u16>(bpmem.petokenint & 0xFFFF), false);
|
||||
break;
|
||||
case BPMEM_PE_TOKEN_INT_ID: // Pixel Engine Interrupt Token ID
|
||||
DEBUG_LOG(VIDEO, "SetPEToken + INT 0x%04x", (bpmem.petokenint & 0xFFFF));
|
||||
PixelEngine::SetToken(static_cast<u16>(bpmem.petokenint & 0xFFFF), TRUE);
|
||||
break;
|
||||
case BPMEM_TRIGGER_EFB_COPY:
|
||||
EfbCopy::CopyEfb();
|
||||
break;
|
||||
case BPMEM_CLEARBBOX1:
|
||||
PixelEngine::pereg.boxRight = newvalue >> 10;
|
||||
PixelEngine::pereg.boxLeft = newvalue & 0x3ff;
|
||||
break;
|
||||
case BPMEM_CLEARBBOX2:
|
||||
PixelEngine::pereg.boxBottom = newvalue >> 10;
|
||||
PixelEngine::pereg.boxTop = newvalue & 0x3ff;
|
||||
break;
|
||||
case BPMEM_LOADTLUT0: // This one updates bpmem.tlutXferSrc, no need to do anything here.
|
||||
break;
|
||||
case BPMEM_LOADTLUT1: // Load a Texture Look Up Table
|
||||
{
|
||||
u32 tlutTMemAddr = (newvalue & 0x3FF) << 9;
|
||||
u32 tlutXferCount = (newvalue & 0x1FFC00) >> 5;
|
||||
|
||||
u8 *ptr = 0;
|
||||
|
||||
// TODO - figure out a cleaner way.
|
||||
if (g_VideoInitialize.bWii)
|
||||
ptr = g_VideoInitialize.pGetMemoryPointer(bpmem.tlutXferSrc << 5);
|
||||
else
|
||||
ptr = g_VideoInitialize.pGetMemoryPointer((bpmem.tlutXferSrc & 0xFFFFF) << 5);
|
||||
|
||||
if (ptr)
|
||||
memcpy_gc(texMem + tlutTMemAddr, ptr, tlutXferCount);
|
||||
else
|
||||
PanicAlert("Invalid palette pointer %08x %08x %08x", bpmem.tlutXferSrc, bpmem.tlutXferSrc << 5, (bpmem.tlutXferSrc & 0xFFFFF)<< 5);
|
||||
break;
|
||||
}
|
||||
|
||||
case BPMEM_TEV_REGISTER_L: // Reg 1
|
||||
case BPMEM_TEV_REGISTER_L+2: // Reg 2
|
||||
case BPMEM_TEV_REGISTER_L+4: // Reg 3
|
||||
case BPMEM_TEV_REGISTER_L+6: // Reg 4
|
||||
{
|
||||
int regNum = (address >> 1 ) & 0x3;
|
||||
ColReg& reg = bpmem.tevregs[regNum].low;
|
||||
bool konst = reg.type;
|
||||
|
||||
Rasterizer::SetTevReg(regNum, 3, konst, reg.b); // A
|
||||
Rasterizer::SetTevReg(regNum, 0, konst, reg.a); // R
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case BPMEM_TEV_REGISTER_H: // Reg 1
|
||||
case BPMEM_TEV_REGISTER_H+2: // Reg 2
|
||||
case BPMEM_TEV_REGISTER_H+4: // Reg 3
|
||||
case BPMEM_TEV_REGISTER_H+6: // Reg 4
|
||||
{
|
||||
int regNum = (address >> 1 ) & 0x3;
|
||||
ColReg& reg = bpmem.tevregs[regNum].high;
|
||||
bool konst = reg.type;
|
||||
|
||||
Rasterizer::SetTevReg(regNum, 1, konst, reg.b); // G
|
||||
Rasterizer::SetTevReg(regNum, 2, konst, reg.a); // B
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "pluginspecs_video.h"
|
||||
#include "../../../Core/VideoCommon/Src/VideoCommon.h"
|
||||
#include "main.h"
|
||||
|
||||
#include "BPMemLoader.h"
|
||||
#include "EfbCopy.h"
|
||||
#include "Rasterizer.h"
|
||||
#include "PixelEngine.h"
|
||||
#include "../../../Core/VideoCommon/Src/TextureDecoder.h"
|
||||
|
||||
|
||||
BPMemory bpmem;
|
||||
|
||||
void InitBPMemory()
|
||||
{
|
||||
memset(&bpmem, 0, sizeof(bpmem));
|
||||
bpmem.bpMask = 0xFFFFFF;
|
||||
}
|
||||
|
||||
void BPWritten(int address, int newvalue);
|
||||
|
||||
void LoadBPReg(u32 value)
|
||||
{
|
||||
//handle the mask register
|
||||
int address = value >> 24;
|
||||
int oldval = ((u32*)&bpmem)[address];
|
||||
int newval = (oldval & ~bpmem.bpMask) | (value & bpmem.bpMask);
|
||||
|
||||
((u32*)&bpmem)[address] = newval;
|
||||
|
||||
//reset the mask register
|
||||
if (address != 0xFE)
|
||||
bpmem.bpMask = 0xFFFFFF;
|
||||
|
||||
BPWritten(address, newval);
|
||||
}
|
||||
|
||||
void BPWritten(int address, int newvalue)
|
||||
{
|
||||
switch (address)
|
||||
{
|
||||
case BPMEM_SCISSORTL:
|
||||
case BPMEM_SCISSORBR:
|
||||
case BPMEM_SCISSOROFFSET:
|
||||
Rasterizer::SetScissor();
|
||||
break;
|
||||
case BPMEM_SETDRAWDONE: // This is called when the game is done drawing (eg: like in DX: Begin(); Draw(); End();)
|
||||
switch (bpmem.drawdone & 0xFF)
|
||||
{
|
||||
case 0x02:
|
||||
PixelEngine::SetFinish(); // may generate interrupt
|
||||
DEBUG_LOG(VIDEO, "GXSetDrawDone SetPEFinish (value: 0x%02X)", (bpmem.drawdone & 0xFFFF));
|
||||
break;
|
||||
|
||||
default:
|
||||
WARN_LOG(VIDEO, "GXSetDrawDone ??? (value 0x%02X)", (bpmem.drawdone & 0xFFFF));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case BPMEM_PE_TOKEN_ID: // Pixel Engine Token ID
|
||||
DEBUG_LOG(VIDEO, "SetPEToken 0x%04x", (bpmem.petoken & 0xFFFF));
|
||||
PixelEngine::SetToken(static_cast<u16>(bpmem.petokenint & 0xFFFF), false);
|
||||
break;
|
||||
case BPMEM_PE_TOKEN_INT_ID: // Pixel Engine Interrupt Token ID
|
||||
DEBUG_LOG(VIDEO, "SetPEToken + INT 0x%04x", (bpmem.petokenint & 0xFFFF));
|
||||
PixelEngine::SetToken(static_cast<u16>(bpmem.petokenint & 0xFFFF), TRUE);
|
||||
break;
|
||||
case BPMEM_TRIGGER_EFB_COPY:
|
||||
EfbCopy::CopyEfb();
|
||||
break;
|
||||
case BPMEM_CLEARBBOX1:
|
||||
PixelEngine::pereg.boxRight = newvalue >> 10;
|
||||
PixelEngine::pereg.boxLeft = newvalue & 0x3ff;
|
||||
break;
|
||||
case BPMEM_CLEARBBOX2:
|
||||
PixelEngine::pereg.boxBottom = newvalue >> 10;
|
||||
PixelEngine::pereg.boxTop = newvalue & 0x3ff;
|
||||
break;
|
||||
case BPMEM_LOADTLUT0: // This one updates bpmem.tlutXferSrc, no need to do anything here.
|
||||
break;
|
||||
case BPMEM_LOADTLUT1: // Load a Texture Look Up Table
|
||||
{
|
||||
u32 tlutTMemAddr = (newvalue & 0x3FF) << 9;
|
||||
u32 tlutXferCount = (newvalue & 0x1FFC00) >> 5;
|
||||
|
||||
u8 *ptr = 0;
|
||||
|
||||
// TODO - figure out a cleaner way.
|
||||
if (g_VideoInitialize.bWii)
|
||||
ptr = g_VideoInitialize.pGetMemoryPointer(bpmem.tlutXferSrc << 5);
|
||||
else
|
||||
ptr = g_VideoInitialize.pGetMemoryPointer((bpmem.tlutXferSrc & 0xFFFFF) << 5);
|
||||
|
||||
if (ptr)
|
||||
memcpy_gc(texMem + tlutTMemAddr, ptr, tlutXferCount);
|
||||
else
|
||||
PanicAlert("Invalid palette pointer %08x %08x %08x", bpmem.tlutXferSrc, bpmem.tlutXferSrc << 5, (bpmem.tlutXferSrc & 0xFFFFF)<< 5);
|
||||
break;
|
||||
}
|
||||
|
||||
case BPMEM_TEV_REGISTER_L: // Reg 1
|
||||
case BPMEM_TEV_REGISTER_L+2: // Reg 2
|
||||
case BPMEM_TEV_REGISTER_L+4: // Reg 3
|
||||
case BPMEM_TEV_REGISTER_L+6: // Reg 4
|
||||
{
|
||||
int regNum = (address >> 1 ) & 0x3;
|
||||
ColReg& reg = bpmem.tevregs[regNum].low;
|
||||
bool konst = reg.type;
|
||||
|
||||
Rasterizer::SetTevReg(regNum, 3, konst, reg.b); // A
|
||||
Rasterizer::SetTevReg(regNum, 0, konst, reg.a); // R
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case BPMEM_TEV_REGISTER_H: // Reg 1
|
||||
case BPMEM_TEV_REGISTER_H+2: // Reg 2
|
||||
case BPMEM_TEV_REGISTER_H+4: // Reg 3
|
||||
case BPMEM_TEV_REGISTER_H+6: // Reg 4
|
||||
{
|
||||
int regNum = (address >> 1 ) & 0x3;
|
||||
ColReg& reg = bpmem.tevregs[regNum].high;
|
||||
bool konst = reg.type;
|
||||
|
||||
Rasterizer::SetTevReg(regNum, 1, konst, reg.b); // G
|
||||
Rasterizer::SetTevReg(regNum, 2, konst, reg.a); // B
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,82 +1,82 @@
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "VideoCommon.h"
|
||||
|
||||
#include "CPMemLoader.h"
|
||||
|
||||
|
||||
// CP state
|
||||
u8 *cached_arraybases[16];
|
||||
|
||||
// STATE_TO_SAVE
|
||||
u32 arraybases[16];
|
||||
u32 arraystrides[16];
|
||||
TMatrixIndexA MatrixIndexA;
|
||||
TMatrixIndexB MatrixIndexB;
|
||||
TVtxDesc g_VtxDesc;
|
||||
VAT g_VtxAttr[8];
|
||||
|
||||
|
||||
void LoadCPReg(u32 sub_cmd, u32 value)
|
||||
{
|
||||
switch (sub_cmd & 0xF0)
|
||||
{
|
||||
case 0x30:
|
||||
MatrixIndexA.Hex = value;
|
||||
break;
|
||||
|
||||
case 0x40:
|
||||
MatrixIndexB.Hex = value;
|
||||
break;
|
||||
|
||||
case 0x50:
|
||||
g_VtxDesc.Hex &= ~0x1FFFF; // keep the Upper bits
|
||||
g_VtxDesc.Hex |= value;
|
||||
break;
|
||||
|
||||
case 0x60:
|
||||
g_VtxDesc.Hex &= 0x1FFFF; // keep the lower 17Bits
|
||||
g_VtxDesc.Hex |= (u64)value << 17;
|
||||
break;
|
||||
|
||||
case 0x70:
|
||||
_assert_((sub_cmd & 0x0F) < 8);
|
||||
g_VtxAttr[sub_cmd & 7].g0.Hex = value;
|
||||
break;
|
||||
|
||||
case 0x80:
|
||||
_assert_((sub_cmd & 0x0F) < 8);
|
||||
g_VtxAttr[sub_cmd & 7].g1.Hex = value;
|
||||
break;
|
||||
|
||||
case 0x90:
|
||||
_assert_((sub_cmd & 0x0F) < 8);
|
||||
g_VtxAttr[sub_cmd & 7].g2.Hex = value;
|
||||
break;
|
||||
|
||||
// Pointers to vertex arrays in GC RAM
|
||||
case 0xA0:
|
||||
arraybases[sub_cmd & 0xF] = value;
|
||||
cached_arraybases[sub_cmd & 0xF] = Memory_GetPtr(value);
|
||||
break;
|
||||
|
||||
case 0xB0:
|
||||
arraystrides[sub_cmd & 0xF] = value & 0xFF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "VideoCommon.h"
|
||||
|
||||
#include "CPMemLoader.h"
|
||||
|
||||
|
||||
// CP state
|
||||
u8 *cached_arraybases[16];
|
||||
|
||||
// STATE_TO_SAVE
|
||||
u32 arraybases[16];
|
||||
u32 arraystrides[16];
|
||||
TMatrixIndexA MatrixIndexA;
|
||||
TMatrixIndexB MatrixIndexB;
|
||||
TVtxDesc g_VtxDesc;
|
||||
VAT g_VtxAttr[8];
|
||||
|
||||
|
||||
void LoadCPReg(u32 sub_cmd, u32 value)
|
||||
{
|
||||
switch (sub_cmd & 0xF0)
|
||||
{
|
||||
case 0x30:
|
||||
MatrixIndexA.Hex = value;
|
||||
break;
|
||||
|
||||
case 0x40:
|
||||
MatrixIndexB.Hex = value;
|
||||
break;
|
||||
|
||||
case 0x50:
|
||||
g_VtxDesc.Hex &= ~0x1FFFF; // keep the Upper bits
|
||||
g_VtxDesc.Hex |= value;
|
||||
break;
|
||||
|
||||
case 0x60:
|
||||
g_VtxDesc.Hex &= 0x1FFFF; // keep the lower 17Bits
|
||||
g_VtxDesc.Hex |= (u64)value << 17;
|
||||
break;
|
||||
|
||||
case 0x70:
|
||||
_assert_((sub_cmd & 0x0F) < 8);
|
||||
g_VtxAttr[sub_cmd & 7].g0.Hex = value;
|
||||
break;
|
||||
|
||||
case 0x80:
|
||||
_assert_((sub_cmd & 0x0F) < 8);
|
||||
g_VtxAttr[sub_cmd & 7].g1.Hex = value;
|
||||
break;
|
||||
|
||||
case 0x90:
|
||||
_assert_((sub_cmd & 0x0F) < 8);
|
||||
g_VtxAttr[sub_cmd & 7].g2.Hex = value;
|
||||
break;
|
||||
|
||||
// Pointers to vertex arrays in GC RAM
|
||||
case 0xA0:
|
||||
arraybases[sub_cmd & 0xF] = value;
|
||||
cached_arraybases[sub_cmd & 0xF] = Memory_GetPtr(value);
|
||||
break;
|
||||
|
||||
case 0xB0:
|
||||
arraystrides[sub_cmd & 0xF] = value & 0xFF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,443 +1,443 @@
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
/*
|
||||
Portions of this file are based off work by Markus Trenkwalder.
|
||||
Copyright (c) 2007, 2008 Markus Trenkwalder
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of the library's copyright owner nor the names of its
|
||||
contributors may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "Clipper.h"
|
||||
#include "Rasterizer.h"
|
||||
#include "NativeVertexFormat.h"
|
||||
#include "XFMemLoader.h"
|
||||
#include "BPMemLoader.h"
|
||||
#include "Statistics.h"
|
||||
#include "VideoConfig.h"
|
||||
|
||||
|
||||
namespace Clipper
|
||||
{
|
||||
float m_ViewOffset[3];
|
||||
OutputVertexData ClippedVertices[18];
|
||||
OutputVertexData *Vertices[21];
|
||||
|
||||
void Init()
|
||||
{
|
||||
for (int i = 0; i < 18; ++i)
|
||||
Vertices[i+3] = &ClippedVertices[i];
|
||||
}
|
||||
|
||||
void SetViewOffset()
|
||||
{
|
||||
m_ViewOffset[0] = xfregs.viewport.xOrig - 342;
|
||||
m_ViewOffset[1] = xfregs.viewport.yOrig - 342;
|
||||
m_ViewOffset[2] = xfregs.viewport.farZ - xfregs.viewport.farZ;
|
||||
}
|
||||
|
||||
|
||||
enum {
|
||||
SKIP_FLAG = -1,
|
||||
CLIP_POS_X_BIT = 0x01,
|
||||
CLIP_NEG_X_BIT = 0x02,
|
||||
CLIP_POS_Y_BIT = 0x04,
|
||||
CLIP_NEG_Y_BIT = 0x08,
|
||||
CLIP_POS_Z_BIT = 0x10,
|
||||
CLIP_NEG_Z_BIT = 0x20
|
||||
};
|
||||
|
||||
static inline int CalcClipMask(OutputVertexData *v)
|
||||
{
|
||||
int cmask = 0;
|
||||
Vec4 pos = v->projectedPosition;
|
||||
if (pos.w - pos.x < 0) cmask |= CLIP_POS_X_BIT;
|
||||
if (pos.x + pos.w < 0) cmask |= CLIP_NEG_X_BIT;
|
||||
if (pos.w - pos.y < 0) cmask |= CLIP_POS_Y_BIT;
|
||||
if (pos.y + pos.w < 0) cmask |= CLIP_NEG_Y_BIT;
|
||||
if (pos.w * pos.z > 0) cmask |= CLIP_POS_Z_BIT;
|
||||
if (pos.z + pos.w < 0) cmask |= CLIP_NEG_Z_BIT;
|
||||
return cmask;
|
||||
}
|
||||
|
||||
static inline void AddInterpolatedVertex(float t, int out, int in, int& numVertices)
|
||||
{
|
||||
Vertices[numVertices]->Lerp(t, Vertices[out], Vertices[in]);
|
||||
numVertices++;
|
||||
}
|
||||
|
||||
#define DIFFERENT_SIGNS(x,y) ((x <= 0 && y > 0) || (x > 0 && y <= 0))
|
||||
|
||||
#define CLIP_DOTPROD(I, A, B, C, D) \
|
||||
(Vertices[I]->projectedPosition.x * A + Vertices[I]->projectedPosition.y * B + Vertices[I]->projectedPosition.z * C + Vertices[I]->projectedPosition.w * D)
|
||||
|
||||
#define POLY_CLIP( PLANE_BIT, A, B, C, D ) \
|
||||
{ \
|
||||
if (mask & PLANE_BIT) { \
|
||||
int idxPrev = inlist[0]; \
|
||||
float dpPrev = CLIP_DOTPROD(idxPrev, A, B, C, D ); \
|
||||
int outcount = 0; \
|
||||
\
|
||||
inlist[n] = inlist[0]; \
|
||||
for (int j = 1; j <= n; j++) { \
|
||||
int idx = inlist[j]; \
|
||||
float dp = CLIP_DOTPROD(idx, A, B, C, D ); \
|
||||
if (dpPrev >= 0) { \
|
||||
outlist[outcount++] = idxPrev; \
|
||||
} \
|
||||
\
|
||||
if (DIFFERENT_SIGNS(dp, dpPrev)) { \
|
||||
if (dp < 0) { \
|
||||
float t = dp / (dp - dpPrev); \
|
||||
AddInterpolatedVertex(t, idx, idxPrev, numVertices); \
|
||||
} else { \
|
||||
float t = dpPrev / (dpPrev - dp); \
|
||||
AddInterpolatedVertex(t, idxPrev, idx, numVertices); \
|
||||
} \
|
||||
outlist[outcount++] = numVertices - 1; \
|
||||
} \
|
||||
\
|
||||
idxPrev = idx; \
|
||||
dpPrev = dp; \
|
||||
} \
|
||||
\
|
||||
if (outcount < 3) \
|
||||
continue; \
|
||||
\
|
||||
{ \
|
||||
int *tmp = inlist; \
|
||||
inlist = outlist; \
|
||||
outlist = tmp; \
|
||||
n = outcount; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#define LINE_CLIP(PLANE_BIT, A, B, C, D ) \
|
||||
{ \
|
||||
if (mask & PLANE_BIT) { \
|
||||
const float dp0 = CLIP_DOTPROD( 0, A, B, C, D ); \
|
||||
const float dp1 = CLIP_DOTPROD( 1, A, B, C, D ); \
|
||||
const bool neg_dp0 = dp0 < 0; \
|
||||
const bool neg_dp1 = dp1 < 0; \
|
||||
\
|
||||
if (neg_dp0 && neg_dp1) \
|
||||
return; \
|
||||
\
|
||||
if (neg_dp1) { \
|
||||
float t = dp1 / (dp1 - dp0); \
|
||||
if (t > t1) t1 = t; \
|
||||
} else if (neg_dp0) { \
|
||||
float t = dp0 / (dp0 - dp1); \
|
||||
if (t > t0) t0 = t; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
void ClipTriangle(int *indices, int &numIndices)
|
||||
{
|
||||
int mask = 0;
|
||||
|
||||
mask |= CalcClipMask(Vertices[0]);
|
||||
mask |= CalcClipMask(Vertices[1]);
|
||||
mask |= CalcClipMask(Vertices[2]);
|
||||
|
||||
if (mask != 0)
|
||||
{
|
||||
for(int i = 0; i < 3; i += 3)
|
||||
{
|
||||
int vlist[2][2*6+1];
|
||||
int *inlist = vlist[0], *outlist = vlist[1];
|
||||
int n = 3;
|
||||
int numVertices = 3;
|
||||
|
||||
inlist[0] = 0;
|
||||
inlist[1] = 1;
|
||||
inlist[2] = 2;
|
||||
|
||||
// mark this triangle as unused in case it should be completely
|
||||
// clipped
|
||||
indices[0] = SKIP_FLAG;
|
||||
indices[1] = SKIP_FLAG;
|
||||
indices[2] = SKIP_FLAG;
|
||||
|
||||
POLY_CLIP(CLIP_POS_X_BIT, -1, 0, 0, 1);
|
||||
POLY_CLIP(CLIP_NEG_X_BIT, 1, 0, 0, 1);
|
||||
POLY_CLIP(CLIP_POS_Y_BIT, 0, -1, 0, 1);
|
||||
POLY_CLIP(CLIP_NEG_Y_BIT, 0, 1, 0, 1);
|
||||
POLY_CLIP(CLIP_POS_Z_BIT, 0, 0, 0, 1);
|
||||
POLY_CLIP(CLIP_NEG_Z_BIT, 0, 0, 1, 1);
|
||||
|
||||
INCSTAT(stats.thisFrame.numTrianglesClipped);
|
||||
|
||||
// transform the poly in inlist into triangles
|
||||
indices[0] = inlist[0];
|
||||
indices[1] = inlist[1];
|
||||
indices[2] = inlist[2];
|
||||
for (int j = 3; j < n; ++j) {
|
||||
indices[numIndices++] = inlist[0];
|
||||
indices[numIndices++] = inlist[j - 1];
|
||||
indices[numIndices++] = inlist[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ClipLine(int *indices)
|
||||
{
|
||||
int mask = 0;
|
||||
int clip_mask[2] = { 0, 0 };
|
||||
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
clip_mask[i] = CalcClipMask(Vertices[i]);
|
||||
mask |= clip_mask[i];
|
||||
}
|
||||
|
||||
if (mask == 0)
|
||||
return;
|
||||
|
||||
float t0 = 0;
|
||||
float t1 = 0;
|
||||
|
||||
// Mark unused in case of early termination
|
||||
// of the macros below. (When fully clipped)
|
||||
indices[0] = SKIP_FLAG;
|
||||
indices[1] = SKIP_FLAG;
|
||||
|
||||
LINE_CLIP(CLIP_POS_X_BIT, -1, 0, 0, 1);
|
||||
LINE_CLIP(CLIP_NEG_X_BIT, 1, 0, 0, 1);
|
||||
LINE_CLIP(CLIP_POS_Y_BIT, 0, -1, 0, 1);
|
||||
LINE_CLIP(CLIP_NEG_Y_BIT, 0, 1, 0, 1);
|
||||
LINE_CLIP(CLIP_POS_Z_BIT, 0, 0, -1, 1);
|
||||
LINE_CLIP(CLIP_NEG_Z_BIT, 0, 0, 1, 1);
|
||||
|
||||
// Restore the old values as this line
|
||||
// was not fully clipped.
|
||||
indices[0] = 0;
|
||||
indices[1] = 1;
|
||||
|
||||
int numVertices = 2;
|
||||
|
||||
if (clip_mask[0]) {
|
||||
indices[0] = numVertices;
|
||||
AddInterpolatedVertex(t0, 0, 1, numVertices);
|
||||
}
|
||||
|
||||
if (clip_mask[1]) {
|
||||
indices[1] = numVertices;
|
||||
AddInterpolatedVertex(t1, 1, 0, numVertices);
|
||||
}
|
||||
}
|
||||
|
||||
void ProcessTriangle(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2)
|
||||
{
|
||||
if (stats.thisFrame.numDrawnObjects < g_Config.drawStart || stats.thisFrame.numDrawnObjects >= g_Config.drawEnd )
|
||||
return;
|
||||
|
||||
INCSTAT(stats.thisFrame.numTrianglesIn)
|
||||
|
||||
bool backface;
|
||||
|
||||
if(!CullTest(v0, v1, v2, backface))
|
||||
return;
|
||||
|
||||
int indices[21] = { 0, 1, 2, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG,
|
||||
SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG,
|
||||
SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG };
|
||||
int numIndices = 3;
|
||||
|
||||
if (backface)
|
||||
{
|
||||
Vertices[0] = v0;
|
||||
Vertices[1] = v2;
|
||||
Vertices[2] = v1;
|
||||
}
|
||||
else
|
||||
{
|
||||
Vertices[0] = v0;
|
||||
Vertices[1] = v1;
|
||||
Vertices[2] = v2;
|
||||
}
|
||||
|
||||
ClipTriangle(indices, numIndices);
|
||||
|
||||
for(int i = 0; i+3 <= numIndices; i+=3)
|
||||
{
|
||||
if(indices[i] != SKIP_FLAG)
|
||||
{
|
||||
PerspectiveDivide(Vertices[indices[i]]);
|
||||
PerspectiveDivide(Vertices[indices[i+1]]);
|
||||
PerspectiveDivide(Vertices[indices[i+2]]);
|
||||
|
||||
Rasterizer::DrawTriangleFrontFace(Vertices[indices[i]], Vertices[indices[i+1]], Vertices[indices[i+2]]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CopyVertex(OutputVertexData *dst, OutputVertexData *src, float dx, float dy, unsigned int sOffset)
|
||||
{
|
||||
dst->screenPosition.x = src->screenPosition.x + dx;
|
||||
dst->screenPosition.y = src->screenPosition.y + dy;
|
||||
dst->screenPosition.z = src->screenPosition.z;
|
||||
|
||||
for (int i = 0; i < 3; ++i)
|
||||
dst->normal[i] = src->normal[i];
|
||||
|
||||
for (int i = 0; i < 4; ++i)
|
||||
dst->color[0][i] = src->color[0][i];
|
||||
|
||||
// todo - s offset
|
||||
for (int i = 0; i < 8; ++i)
|
||||
dst->texCoords[i] = src->texCoords[i];
|
||||
}
|
||||
|
||||
void ProcessLine(OutputVertexData *lineV0, OutputVertexData *lineV1)
|
||||
{
|
||||
int indices[4] = { 0, 1, SKIP_FLAG, SKIP_FLAG };
|
||||
|
||||
Vertices[0] = lineV0;
|
||||
Vertices[1] = lineV1;
|
||||
|
||||
// point to a valid vertex to store to when clipping
|
||||
Vertices[2] = &ClippedVertices[17];
|
||||
|
||||
ClipLine(indices);
|
||||
|
||||
if(indices[0] != SKIP_FLAG)
|
||||
{
|
||||
OutputVertexData *v0 = Vertices[indices[0]];
|
||||
OutputVertexData *v1 = Vertices[indices[1]];
|
||||
|
||||
PerspectiveDivide(v0);
|
||||
PerspectiveDivide(v1);
|
||||
|
||||
float dx = v1->screenPosition.x - v0->screenPosition.x;
|
||||
float dy = v1->screenPosition.y - v0->screenPosition.y;
|
||||
|
||||
float screenDx = 0;
|
||||
float screenDy = 0;
|
||||
|
||||
if(abs(dx) > abs(dy))
|
||||
{
|
||||
if(dx > 0)
|
||||
screenDy = bpmem.lineptwidth.linesize / -12.0f;
|
||||
else
|
||||
screenDy = bpmem.lineptwidth.linesize / 12.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(dy > 0)
|
||||
screenDx = bpmem.lineptwidth.linesize / 12.0f;
|
||||
else
|
||||
screenDx = bpmem.lineptwidth.linesize / -12.0f;
|
||||
}
|
||||
|
||||
OutputVertexData triangle[3];
|
||||
|
||||
CopyVertex(&triangle[0], v0, screenDx, screenDy, 0);
|
||||
CopyVertex(&triangle[1], v1, screenDx, screenDy, 0);
|
||||
CopyVertex(&triangle[2], v1, -screenDx, -screenDy, bpmem.lineptwidth.lineoff);
|
||||
|
||||
// ccw winding
|
||||
Rasterizer::DrawTriangleFrontFace(&triangle[2], &triangle[1], &triangle[0]);
|
||||
|
||||
CopyVertex(&triangle[1], v0, -screenDx, -screenDy, bpmem.lineptwidth.lineoff);
|
||||
|
||||
Rasterizer::DrawTriangleFrontFace(&triangle[0], &triangle[1], &triangle[2]);
|
||||
}
|
||||
}
|
||||
|
||||
bool CullTest(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2, bool &backface)
|
||||
{
|
||||
int mask = CalcClipMask(v0);
|
||||
mask &= CalcClipMask(v1);
|
||||
mask &= CalcClipMask(v2);
|
||||
|
||||
if(mask)
|
||||
{
|
||||
INCSTAT(stats.thisFrame.numTrianglesRejected)
|
||||
return false;
|
||||
}
|
||||
|
||||
float x0 = v0->projectedPosition.x;
|
||||
float x1 = v1->projectedPosition.x;
|
||||
float x2 = v2->projectedPosition.x;
|
||||
float y1 = v1->projectedPosition.y;
|
||||
float y0 = v0->projectedPosition.y;
|
||||
float y2 = v2->projectedPosition.y;
|
||||
float w0 = v0->projectedPosition.w;
|
||||
float w1 = v1->projectedPosition.w;
|
||||
float w2 = v2->projectedPosition.w;
|
||||
|
||||
float normalZDir = (x0*w2 - x2*w0)*y1 + (x2*y0 - x0*y2)*w1 + (y2*w0 - y0*w2)*x1;
|
||||
|
||||
backface = normalZDir <= 0.0f;
|
||||
|
||||
if ((bpmem.genMode.cullmode & 1) && !backface) // cull frontfacing
|
||||
{
|
||||
INCSTAT(stats.thisFrame.numTrianglesCulled)
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((bpmem.genMode.cullmode & 2) && backface) // cull backfacing
|
||||
{
|
||||
INCSTAT(stats.thisFrame.numTrianglesCulled)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PerspectiveDivide(OutputVertexData *vertex)
|
||||
{
|
||||
Vec4 &projected = vertex->projectedPosition;
|
||||
Vec3 &screen = vertex->screenPosition;
|
||||
|
||||
float wInverse = 1.0f/projected.w;
|
||||
screen.x = projected.x * wInverse * xfregs.viewport.wd + m_ViewOffset[0];
|
||||
screen.y = projected.y * wInverse * xfregs.viewport.ht + m_ViewOffset[1];
|
||||
screen.z = projected.z * wInverse + m_ViewOffset[2];
|
||||
}
|
||||
|
||||
}
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
/*
|
||||
Portions of this file are based off work by Markus Trenkwalder.
|
||||
Copyright (c) 2007, 2008 Markus Trenkwalder
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of the library's copyright owner nor the names of its
|
||||
contributors may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "Clipper.h"
|
||||
#include "Rasterizer.h"
|
||||
#include "NativeVertexFormat.h"
|
||||
#include "XFMemLoader.h"
|
||||
#include "BPMemLoader.h"
|
||||
#include "Statistics.h"
|
||||
#include "VideoConfig.h"
|
||||
|
||||
|
||||
namespace Clipper
|
||||
{
|
||||
float m_ViewOffset[3];
|
||||
OutputVertexData ClippedVertices[18];
|
||||
OutputVertexData *Vertices[21];
|
||||
|
||||
void Init()
|
||||
{
|
||||
for (int i = 0; i < 18; ++i)
|
||||
Vertices[i+3] = &ClippedVertices[i];
|
||||
}
|
||||
|
||||
void SetViewOffset()
|
||||
{
|
||||
m_ViewOffset[0] = xfregs.viewport.xOrig - 342;
|
||||
m_ViewOffset[1] = xfregs.viewport.yOrig - 342;
|
||||
m_ViewOffset[2] = xfregs.viewport.farZ - xfregs.viewport.farZ;
|
||||
}
|
||||
|
||||
|
||||
enum {
|
||||
SKIP_FLAG = -1,
|
||||
CLIP_POS_X_BIT = 0x01,
|
||||
CLIP_NEG_X_BIT = 0x02,
|
||||
CLIP_POS_Y_BIT = 0x04,
|
||||
CLIP_NEG_Y_BIT = 0x08,
|
||||
CLIP_POS_Z_BIT = 0x10,
|
||||
CLIP_NEG_Z_BIT = 0x20
|
||||
};
|
||||
|
||||
static inline int CalcClipMask(OutputVertexData *v)
|
||||
{
|
||||
int cmask = 0;
|
||||
Vec4 pos = v->projectedPosition;
|
||||
if (pos.w - pos.x < 0) cmask |= CLIP_POS_X_BIT;
|
||||
if (pos.x + pos.w < 0) cmask |= CLIP_NEG_X_BIT;
|
||||
if (pos.w - pos.y < 0) cmask |= CLIP_POS_Y_BIT;
|
||||
if (pos.y + pos.w < 0) cmask |= CLIP_NEG_Y_BIT;
|
||||
if (pos.w * pos.z > 0) cmask |= CLIP_POS_Z_BIT;
|
||||
if (pos.z + pos.w < 0) cmask |= CLIP_NEG_Z_BIT;
|
||||
return cmask;
|
||||
}
|
||||
|
||||
static inline void AddInterpolatedVertex(float t, int out, int in, int& numVertices)
|
||||
{
|
||||
Vertices[numVertices]->Lerp(t, Vertices[out], Vertices[in]);
|
||||
numVertices++;
|
||||
}
|
||||
|
||||
#define DIFFERENT_SIGNS(x,y) ((x <= 0 && y > 0) || (x > 0 && y <= 0))
|
||||
|
||||
#define CLIP_DOTPROD(I, A, B, C, D) \
|
||||
(Vertices[I]->projectedPosition.x * A + Vertices[I]->projectedPosition.y * B + Vertices[I]->projectedPosition.z * C + Vertices[I]->projectedPosition.w * D)
|
||||
|
||||
#define POLY_CLIP( PLANE_BIT, A, B, C, D ) \
|
||||
{ \
|
||||
if (mask & PLANE_BIT) { \
|
||||
int idxPrev = inlist[0]; \
|
||||
float dpPrev = CLIP_DOTPROD(idxPrev, A, B, C, D ); \
|
||||
int outcount = 0; \
|
||||
\
|
||||
inlist[n] = inlist[0]; \
|
||||
for (int j = 1; j <= n; j++) { \
|
||||
int idx = inlist[j]; \
|
||||
float dp = CLIP_DOTPROD(idx, A, B, C, D ); \
|
||||
if (dpPrev >= 0) { \
|
||||
outlist[outcount++] = idxPrev; \
|
||||
} \
|
||||
\
|
||||
if (DIFFERENT_SIGNS(dp, dpPrev)) { \
|
||||
if (dp < 0) { \
|
||||
float t = dp / (dp - dpPrev); \
|
||||
AddInterpolatedVertex(t, idx, idxPrev, numVertices); \
|
||||
} else { \
|
||||
float t = dpPrev / (dpPrev - dp); \
|
||||
AddInterpolatedVertex(t, idxPrev, idx, numVertices); \
|
||||
} \
|
||||
outlist[outcount++] = numVertices - 1; \
|
||||
} \
|
||||
\
|
||||
idxPrev = idx; \
|
||||
dpPrev = dp; \
|
||||
} \
|
||||
\
|
||||
if (outcount < 3) \
|
||||
continue; \
|
||||
\
|
||||
{ \
|
||||
int *tmp = inlist; \
|
||||
inlist = outlist; \
|
||||
outlist = tmp; \
|
||||
n = outcount; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#define LINE_CLIP(PLANE_BIT, A, B, C, D ) \
|
||||
{ \
|
||||
if (mask & PLANE_BIT) { \
|
||||
const float dp0 = CLIP_DOTPROD( 0, A, B, C, D ); \
|
||||
const float dp1 = CLIP_DOTPROD( 1, A, B, C, D ); \
|
||||
const bool neg_dp0 = dp0 < 0; \
|
||||
const bool neg_dp1 = dp1 < 0; \
|
||||
\
|
||||
if (neg_dp0 && neg_dp1) \
|
||||
return; \
|
||||
\
|
||||
if (neg_dp1) { \
|
||||
float t = dp1 / (dp1 - dp0); \
|
||||
if (t > t1) t1 = t; \
|
||||
} else if (neg_dp0) { \
|
||||
float t = dp0 / (dp0 - dp1); \
|
||||
if (t > t0) t0 = t; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
void ClipTriangle(int *indices, int &numIndices)
|
||||
{
|
||||
int mask = 0;
|
||||
|
||||
mask |= CalcClipMask(Vertices[0]);
|
||||
mask |= CalcClipMask(Vertices[1]);
|
||||
mask |= CalcClipMask(Vertices[2]);
|
||||
|
||||
if (mask != 0)
|
||||
{
|
||||
for(int i = 0; i < 3; i += 3)
|
||||
{
|
||||
int vlist[2][2*6+1];
|
||||
int *inlist = vlist[0], *outlist = vlist[1];
|
||||
int n = 3;
|
||||
int numVertices = 3;
|
||||
|
||||
inlist[0] = 0;
|
||||
inlist[1] = 1;
|
||||
inlist[2] = 2;
|
||||
|
||||
// mark this triangle as unused in case it should be completely
|
||||
// clipped
|
||||
indices[0] = SKIP_FLAG;
|
||||
indices[1] = SKIP_FLAG;
|
||||
indices[2] = SKIP_FLAG;
|
||||
|
||||
POLY_CLIP(CLIP_POS_X_BIT, -1, 0, 0, 1);
|
||||
POLY_CLIP(CLIP_NEG_X_BIT, 1, 0, 0, 1);
|
||||
POLY_CLIP(CLIP_POS_Y_BIT, 0, -1, 0, 1);
|
||||
POLY_CLIP(CLIP_NEG_Y_BIT, 0, 1, 0, 1);
|
||||
POLY_CLIP(CLIP_POS_Z_BIT, 0, 0, 0, 1);
|
||||
POLY_CLIP(CLIP_NEG_Z_BIT, 0, 0, 1, 1);
|
||||
|
||||
INCSTAT(stats.thisFrame.numTrianglesClipped);
|
||||
|
||||
// transform the poly in inlist into triangles
|
||||
indices[0] = inlist[0];
|
||||
indices[1] = inlist[1];
|
||||
indices[2] = inlist[2];
|
||||
for (int j = 3; j < n; ++j) {
|
||||
indices[numIndices++] = inlist[0];
|
||||
indices[numIndices++] = inlist[j - 1];
|
||||
indices[numIndices++] = inlist[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ClipLine(int *indices)
|
||||
{
|
||||
int mask = 0;
|
||||
int clip_mask[2] = { 0, 0 };
|
||||
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
clip_mask[i] = CalcClipMask(Vertices[i]);
|
||||
mask |= clip_mask[i];
|
||||
}
|
||||
|
||||
if (mask == 0)
|
||||
return;
|
||||
|
||||
float t0 = 0;
|
||||
float t1 = 0;
|
||||
|
||||
// Mark unused in case of early termination
|
||||
// of the macros below. (When fully clipped)
|
||||
indices[0] = SKIP_FLAG;
|
||||
indices[1] = SKIP_FLAG;
|
||||
|
||||
LINE_CLIP(CLIP_POS_X_BIT, -1, 0, 0, 1);
|
||||
LINE_CLIP(CLIP_NEG_X_BIT, 1, 0, 0, 1);
|
||||
LINE_CLIP(CLIP_POS_Y_BIT, 0, -1, 0, 1);
|
||||
LINE_CLIP(CLIP_NEG_Y_BIT, 0, 1, 0, 1);
|
||||
LINE_CLIP(CLIP_POS_Z_BIT, 0, 0, -1, 1);
|
||||
LINE_CLIP(CLIP_NEG_Z_BIT, 0, 0, 1, 1);
|
||||
|
||||
// Restore the old values as this line
|
||||
// was not fully clipped.
|
||||
indices[0] = 0;
|
||||
indices[1] = 1;
|
||||
|
||||
int numVertices = 2;
|
||||
|
||||
if (clip_mask[0]) {
|
||||
indices[0] = numVertices;
|
||||
AddInterpolatedVertex(t0, 0, 1, numVertices);
|
||||
}
|
||||
|
||||
if (clip_mask[1]) {
|
||||
indices[1] = numVertices;
|
||||
AddInterpolatedVertex(t1, 1, 0, numVertices);
|
||||
}
|
||||
}
|
||||
|
||||
void ProcessTriangle(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2)
|
||||
{
|
||||
if (stats.thisFrame.numDrawnObjects < g_Config.drawStart || stats.thisFrame.numDrawnObjects >= g_Config.drawEnd )
|
||||
return;
|
||||
|
||||
INCSTAT(stats.thisFrame.numTrianglesIn)
|
||||
|
||||
bool backface;
|
||||
|
||||
if(!CullTest(v0, v1, v2, backface))
|
||||
return;
|
||||
|
||||
int indices[21] = { 0, 1, 2, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG,
|
||||
SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG,
|
||||
SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG };
|
||||
int numIndices = 3;
|
||||
|
||||
if (backface)
|
||||
{
|
||||
Vertices[0] = v0;
|
||||
Vertices[1] = v2;
|
||||
Vertices[2] = v1;
|
||||
}
|
||||
else
|
||||
{
|
||||
Vertices[0] = v0;
|
||||
Vertices[1] = v1;
|
||||
Vertices[2] = v2;
|
||||
}
|
||||
|
||||
ClipTriangle(indices, numIndices);
|
||||
|
||||
for(int i = 0; i+3 <= numIndices; i+=3)
|
||||
{
|
||||
if(indices[i] != SKIP_FLAG)
|
||||
{
|
||||
PerspectiveDivide(Vertices[indices[i]]);
|
||||
PerspectiveDivide(Vertices[indices[i+1]]);
|
||||
PerspectiveDivide(Vertices[indices[i+2]]);
|
||||
|
||||
Rasterizer::DrawTriangleFrontFace(Vertices[indices[i]], Vertices[indices[i+1]], Vertices[indices[i+2]]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CopyVertex(OutputVertexData *dst, OutputVertexData *src, float dx, float dy, unsigned int sOffset)
|
||||
{
|
||||
dst->screenPosition.x = src->screenPosition.x + dx;
|
||||
dst->screenPosition.y = src->screenPosition.y + dy;
|
||||
dst->screenPosition.z = src->screenPosition.z;
|
||||
|
||||
for (int i = 0; i < 3; ++i)
|
||||
dst->normal[i] = src->normal[i];
|
||||
|
||||
for (int i = 0; i < 4; ++i)
|
||||
dst->color[0][i] = src->color[0][i];
|
||||
|
||||
// todo - s offset
|
||||
for (int i = 0; i < 8; ++i)
|
||||
dst->texCoords[i] = src->texCoords[i];
|
||||
}
|
||||
|
||||
void ProcessLine(OutputVertexData *lineV0, OutputVertexData *lineV1)
|
||||
{
|
||||
int indices[4] = { 0, 1, SKIP_FLAG, SKIP_FLAG };
|
||||
|
||||
Vertices[0] = lineV0;
|
||||
Vertices[1] = lineV1;
|
||||
|
||||
// point to a valid vertex to store to when clipping
|
||||
Vertices[2] = &ClippedVertices[17];
|
||||
|
||||
ClipLine(indices);
|
||||
|
||||
if(indices[0] != SKIP_FLAG)
|
||||
{
|
||||
OutputVertexData *v0 = Vertices[indices[0]];
|
||||
OutputVertexData *v1 = Vertices[indices[1]];
|
||||
|
||||
PerspectiveDivide(v0);
|
||||
PerspectiveDivide(v1);
|
||||
|
||||
float dx = v1->screenPosition.x - v0->screenPosition.x;
|
||||
float dy = v1->screenPosition.y - v0->screenPosition.y;
|
||||
|
||||
float screenDx = 0;
|
||||
float screenDy = 0;
|
||||
|
||||
if(abs(dx) > abs(dy))
|
||||
{
|
||||
if(dx > 0)
|
||||
screenDy = bpmem.lineptwidth.linesize / -12.0f;
|
||||
else
|
||||
screenDy = bpmem.lineptwidth.linesize / 12.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(dy > 0)
|
||||
screenDx = bpmem.lineptwidth.linesize / 12.0f;
|
||||
else
|
||||
screenDx = bpmem.lineptwidth.linesize / -12.0f;
|
||||
}
|
||||
|
||||
OutputVertexData triangle[3];
|
||||
|
||||
CopyVertex(&triangle[0], v0, screenDx, screenDy, 0);
|
||||
CopyVertex(&triangle[1], v1, screenDx, screenDy, 0);
|
||||
CopyVertex(&triangle[2], v1, -screenDx, -screenDy, bpmem.lineptwidth.lineoff);
|
||||
|
||||
// ccw winding
|
||||
Rasterizer::DrawTriangleFrontFace(&triangle[2], &triangle[1], &triangle[0]);
|
||||
|
||||
CopyVertex(&triangle[1], v0, -screenDx, -screenDy, bpmem.lineptwidth.lineoff);
|
||||
|
||||
Rasterizer::DrawTriangleFrontFace(&triangle[0], &triangle[1], &triangle[2]);
|
||||
}
|
||||
}
|
||||
|
||||
bool CullTest(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2, bool &backface)
|
||||
{
|
||||
int mask = CalcClipMask(v0);
|
||||
mask &= CalcClipMask(v1);
|
||||
mask &= CalcClipMask(v2);
|
||||
|
||||
if(mask)
|
||||
{
|
||||
INCSTAT(stats.thisFrame.numTrianglesRejected)
|
||||
return false;
|
||||
}
|
||||
|
||||
float x0 = v0->projectedPosition.x;
|
||||
float x1 = v1->projectedPosition.x;
|
||||
float x2 = v2->projectedPosition.x;
|
||||
float y1 = v1->projectedPosition.y;
|
||||
float y0 = v0->projectedPosition.y;
|
||||
float y2 = v2->projectedPosition.y;
|
||||
float w0 = v0->projectedPosition.w;
|
||||
float w1 = v1->projectedPosition.w;
|
||||
float w2 = v2->projectedPosition.w;
|
||||
|
||||
float normalZDir = (x0*w2 - x2*w0)*y1 + (x2*y0 - x0*y2)*w1 + (y2*w0 - y0*w2)*x1;
|
||||
|
||||
backface = normalZDir <= 0.0f;
|
||||
|
||||
if ((bpmem.genMode.cullmode & 1) && !backface) // cull frontfacing
|
||||
{
|
||||
INCSTAT(stats.thisFrame.numTrianglesCulled)
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((bpmem.genMode.cullmode & 2) && backface) // cull backfacing
|
||||
{
|
||||
INCSTAT(stats.thisFrame.numTrianglesCulled)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PerspectiveDivide(OutputVertexData *vertex)
|
||||
{
|
||||
Vec4 &projected = vertex->projectedPosition;
|
||||
Vec3 &screen = vertex->screenPosition;
|
||||
|
||||
float wInverse = 1.0f/projected.w;
|
||||
screen.x = projected.x * wInverse * xfregs.viewport.wd + m_ViewOffset[0];
|
||||
screen.y = projected.y * wInverse * xfregs.viewport.ht + m_ViewOffset[1];
|
||||
screen.z = projected.z * wInverse + m_ViewOffset[2];
|
||||
}
|
||||
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,170 +1,170 @@
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _COMMANDPROCESSOR_H_
|
||||
#define _COMMANDPROCESSOR_H_
|
||||
|
||||
#include "Common.h"
|
||||
#include "pluginspecs_video.h"
|
||||
class PointerWrap;
|
||||
|
||||
extern volatile bool g_bSkipCurrentFrame;
|
||||
|
||||
// for compatibility with video common
|
||||
void Fifo_Init();
|
||||
void Fifo_Shutdown();
|
||||
void Fifo_DoState(PointerWrap &p);
|
||||
|
||||
void Fifo_EnterLoop(const SVideoInitialize &video_initialize);
|
||||
void Fifo_ExitLoop();
|
||||
void Fifo_SetRendering(bool bEnabled);
|
||||
|
||||
// Implemented by the Video Plugin
|
||||
void VideoFifo_CheckSwapRequest();
|
||||
void VideoFifo_CheckSwapRequestAt(u32 xfbAddr, u32 fbWidth, u32 fbHeight);
|
||||
void VideoFifo_CheckEFBAccess();
|
||||
|
||||
namespace CommandProcessor
|
||||
{
|
||||
// internal hardware addresses
|
||||
enum
|
||||
{
|
||||
STATUS_REGISTER = 0x00,
|
||||
CTRL_REGISTER = 0x02,
|
||||
CLEAR_REGISTER = 0x04,
|
||||
FIFO_TOKEN_REGISTER = 0x0E,
|
||||
FIFO_BOUNDING_BOX_LEFT = 0x10,
|
||||
FIFO_BOUNDING_BOX_RIGHT = 0x12,
|
||||
FIFO_BOUNDING_BOX_TOP = 0x14,
|
||||
FIFO_BOUNDING_BOX_BOTTOM = 0x16,
|
||||
FIFO_BASE_LO = 0x20,
|
||||
FIFO_BASE_HI = 0x22,
|
||||
FIFO_END_LO = 0x24,
|
||||
FIFO_END_HI = 0x26,
|
||||
FIFO_HI_WATERMARK_LO = 0x28,
|
||||
FIFO_HI_WATERMARK_HI = 0x2a,
|
||||
FIFO_LO_WATERMARK_LO = 0x2c,
|
||||
FIFO_LO_WATERMARK_HI = 0x2e,
|
||||
FIFO_RW_DISTANCE_LO = 0x30,
|
||||
FIFO_RW_DISTANCE_HI = 0x32,
|
||||
FIFO_WRITE_POINTER_LO = 0x34,
|
||||
FIFO_WRITE_POINTER_HI = 0x36,
|
||||
FIFO_READ_POINTER_LO = 0x38,
|
||||
FIFO_READ_POINTER_HI = 0x3A,
|
||||
FIFO_BP_LO = 0x3C,
|
||||
FIFO_BP_HI = 0x3E
|
||||
};
|
||||
|
||||
// Fifo Status Register
|
||||
union UCPStatusReg
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned OverflowHiWatermark : 1;
|
||||
unsigned UnderflowLoWatermark : 1;
|
||||
unsigned ReadIdle : 1; // done reading
|
||||
unsigned CommandIdle : 1; // done processing commands
|
||||
unsigned Breakpoint : 1;
|
||||
unsigned : 11;
|
||||
};
|
||||
u16 Hex;
|
||||
UCPStatusReg() {Hex = 0; }
|
||||
UCPStatusReg(u16 _hex) {Hex = _hex; }
|
||||
};
|
||||
|
||||
// Fifo Control Register
|
||||
union UCPCtrlReg
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned GPReadEnable : 1;
|
||||
unsigned BPEnable : 1;
|
||||
unsigned FifoOverflowIntEnable : 1;
|
||||
unsigned FifoUnderflowIntEnable : 1;
|
||||
unsigned GPLinkEnable : 1;
|
||||
unsigned BreakPointIntEnable : 1;
|
||||
unsigned : 10;
|
||||
};
|
||||
u16 Hex;
|
||||
UCPCtrlReg() {Hex = 0; }
|
||||
UCPCtrlReg(u16 _hex) {Hex = _hex; }
|
||||
};
|
||||
|
||||
// Fifo Control Register
|
||||
union UCPClearReg
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned ClearFifoOverflow : 1;
|
||||
unsigned ClearFifoUnderflow : 1;
|
||||
unsigned ClearMetrices : 1;
|
||||
unsigned : 13;
|
||||
};
|
||||
u16 Hex;
|
||||
UCPClearReg() {Hex = 0; }
|
||||
UCPClearReg(u16 _hex) {Hex = _hex; }
|
||||
};
|
||||
|
||||
struct CPReg
|
||||
{
|
||||
UCPStatusReg status; // 0x00
|
||||
UCPCtrlReg ctrl; // 0x02
|
||||
UCPClearReg clear; // 0x04
|
||||
u32 unk0; // 0x06
|
||||
u32 unk1; // 0x0a
|
||||
u16 token; // 0x0e
|
||||
u16 bboxleft; // 0x10
|
||||
u16 bboxtop; // 0x12
|
||||
u16 bboxright; // 0x14
|
||||
u16 bboxbottom; // 0x16
|
||||
u16 unk2; // 0x18
|
||||
u32 fifobase; // 0x20
|
||||
u32 fifoend; // 0x24
|
||||
u32 hiwatermark; // 0x28
|
||||
u32 lowatermark; // 0x2c
|
||||
u32 rwdistance; // 0x30
|
||||
u32 writeptr; // 0x34
|
||||
u32 readptr; // 0x38
|
||||
u32 breakpt; // 0x3c
|
||||
};
|
||||
|
||||
extern CPReg cpreg;
|
||||
|
||||
// Init
|
||||
void Init();
|
||||
void Shutdown();
|
||||
void DoState(PointerWrap &p);
|
||||
|
||||
bool RunBuffer();
|
||||
void RunGpu();
|
||||
|
||||
// Read
|
||||
void Read16(u16& _rReturnValue, const u32 _Address);
|
||||
void Write16(const u16 _Data, const u32 _Address);
|
||||
void Read32(u32& _rReturnValue, const u32 _Address);
|
||||
void Write32(const u32 _Data, const u32 _Address);
|
||||
|
||||
// for CGPFIFO
|
||||
void GatherPipeBursted();
|
||||
void UpdateInterrupts(u64 userdata);
|
||||
void UpdateInterruptsFromVideoPlugin(u64 userdata);
|
||||
|
||||
|
||||
} // end of namespace CommandProcessor
|
||||
|
||||
|
||||
#endif
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _COMMANDPROCESSOR_H_
|
||||
#define _COMMANDPROCESSOR_H_
|
||||
|
||||
#include "Common.h"
|
||||
#include "pluginspecs_video.h"
|
||||
class PointerWrap;
|
||||
|
||||
extern volatile bool g_bSkipCurrentFrame;
|
||||
|
||||
// for compatibility with video common
|
||||
void Fifo_Init();
|
||||
void Fifo_Shutdown();
|
||||
void Fifo_DoState(PointerWrap &p);
|
||||
|
||||
void Fifo_EnterLoop(const SVideoInitialize &video_initialize);
|
||||
void Fifo_ExitLoop();
|
||||
void Fifo_SetRendering(bool bEnabled);
|
||||
|
||||
// Implemented by the Video Plugin
|
||||
void VideoFifo_CheckSwapRequest();
|
||||
void VideoFifo_CheckSwapRequestAt(u32 xfbAddr, u32 fbWidth, u32 fbHeight);
|
||||
void VideoFifo_CheckEFBAccess();
|
||||
|
||||
namespace CommandProcessor
|
||||
{
|
||||
// internal hardware addresses
|
||||
enum
|
||||
{
|
||||
STATUS_REGISTER = 0x00,
|
||||
CTRL_REGISTER = 0x02,
|
||||
CLEAR_REGISTER = 0x04,
|
||||
FIFO_TOKEN_REGISTER = 0x0E,
|
||||
FIFO_BOUNDING_BOX_LEFT = 0x10,
|
||||
FIFO_BOUNDING_BOX_RIGHT = 0x12,
|
||||
FIFO_BOUNDING_BOX_TOP = 0x14,
|
||||
FIFO_BOUNDING_BOX_BOTTOM = 0x16,
|
||||
FIFO_BASE_LO = 0x20,
|
||||
FIFO_BASE_HI = 0x22,
|
||||
FIFO_END_LO = 0x24,
|
||||
FIFO_END_HI = 0x26,
|
||||
FIFO_HI_WATERMARK_LO = 0x28,
|
||||
FIFO_HI_WATERMARK_HI = 0x2a,
|
||||
FIFO_LO_WATERMARK_LO = 0x2c,
|
||||
FIFO_LO_WATERMARK_HI = 0x2e,
|
||||
FIFO_RW_DISTANCE_LO = 0x30,
|
||||
FIFO_RW_DISTANCE_HI = 0x32,
|
||||
FIFO_WRITE_POINTER_LO = 0x34,
|
||||
FIFO_WRITE_POINTER_HI = 0x36,
|
||||
FIFO_READ_POINTER_LO = 0x38,
|
||||
FIFO_READ_POINTER_HI = 0x3A,
|
||||
FIFO_BP_LO = 0x3C,
|
||||
FIFO_BP_HI = 0x3E
|
||||
};
|
||||
|
||||
// Fifo Status Register
|
||||
union UCPStatusReg
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned OverflowHiWatermark : 1;
|
||||
unsigned UnderflowLoWatermark : 1;
|
||||
unsigned ReadIdle : 1; // done reading
|
||||
unsigned CommandIdle : 1; // done processing commands
|
||||
unsigned Breakpoint : 1;
|
||||
unsigned : 11;
|
||||
};
|
||||
u16 Hex;
|
||||
UCPStatusReg() {Hex = 0; }
|
||||
UCPStatusReg(u16 _hex) {Hex = _hex; }
|
||||
};
|
||||
|
||||
// Fifo Control Register
|
||||
union UCPCtrlReg
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned GPReadEnable : 1;
|
||||
unsigned BPEnable : 1;
|
||||
unsigned FifoOverflowIntEnable : 1;
|
||||
unsigned FifoUnderflowIntEnable : 1;
|
||||
unsigned GPLinkEnable : 1;
|
||||
unsigned BreakPointIntEnable : 1;
|
||||
unsigned : 10;
|
||||
};
|
||||
u16 Hex;
|
||||
UCPCtrlReg() {Hex = 0; }
|
||||
UCPCtrlReg(u16 _hex) {Hex = _hex; }
|
||||
};
|
||||
|
||||
// Fifo Control Register
|
||||
union UCPClearReg
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned ClearFifoOverflow : 1;
|
||||
unsigned ClearFifoUnderflow : 1;
|
||||
unsigned ClearMetrices : 1;
|
||||
unsigned : 13;
|
||||
};
|
||||
u16 Hex;
|
||||
UCPClearReg() {Hex = 0; }
|
||||
UCPClearReg(u16 _hex) {Hex = _hex; }
|
||||
};
|
||||
|
||||
struct CPReg
|
||||
{
|
||||
UCPStatusReg status; // 0x00
|
||||
UCPCtrlReg ctrl; // 0x02
|
||||
UCPClearReg clear; // 0x04
|
||||
u32 unk0; // 0x06
|
||||
u32 unk1; // 0x0a
|
||||
u16 token; // 0x0e
|
||||
u16 bboxleft; // 0x10
|
||||
u16 bboxtop; // 0x12
|
||||
u16 bboxright; // 0x14
|
||||
u16 bboxbottom; // 0x16
|
||||
u16 unk2; // 0x18
|
||||
u32 fifobase; // 0x20
|
||||
u32 fifoend; // 0x24
|
||||
u32 hiwatermark; // 0x28
|
||||
u32 lowatermark; // 0x2c
|
||||
u32 rwdistance; // 0x30
|
||||
u32 writeptr; // 0x34
|
||||
u32 readptr; // 0x38
|
||||
u32 breakpt; // 0x3c
|
||||
};
|
||||
|
||||
extern CPReg cpreg;
|
||||
|
||||
// Init
|
||||
void Init();
|
||||
void Shutdown();
|
||||
void DoState(PointerWrap &p);
|
||||
|
||||
bool RunBuffer();
|
||||
void RunGpu();
|
||||
|
||||
// Read
|
||||
void Read16(u16& _rReturnValue, const u32 _Address);
|
||||
void Write16(const u16 _Data, const u32 _Address);
|
||||
void Read32(u32& _rReturnValue, const u32 _Address);
|
||||
void Write32(const u32 _Data, const u32 _Address);
|
||||
|
||||
// for CGPFIFO
|
||||
void GatherPipeBursted();
|
||||
void UpdateInterrupts(u64 userdata);
|
||||
void UpdateInterruptsFromVideoPlugin(u64 userdata);
|
||||
|
||||
|
||||
} // end of namespace CommandProcessor
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -1,233 +1,233 @@
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
#include "main.h"
|
||||
#include "DebugUtil.h"
|
||||
#include "BPMemLoader.h"
|
||||
#include "TextureSampler.h"
|
||||
#include "VideoConfig.h"
|
||||
#include "EfbInterface.h"
|
||||
#include "Statistics.h"
|
||||
#include "HwRasterizer.h"
|
||||
#include "StringUtil.h"
|
||||
#include "CommandProcessor.h"
|
||||
#include "../../../Core/VideoCommon/Src/ImageWrite.h"
|
||||
#include "FileUtil.h"
|
||||
|
||||
namespace DebugUtil
|
||||
{
|
||||
|
||||
u32 skipFrames = 0;
|
||||
const int NumObjectBuffers = 32;
|
||||
u8 ObjectBuffer[NumObjectBuffers][EFB_WIDTH*EFB_HEIGHT*4];
|
||||
bool DrawnToBuffer[NumObjectBuffers];
|
||||
const char* ObjectBufferName[NumObjectBuffers];
|
||||
|
||||
void Init()
|
||||
{
|
||||
for (int i = 0; i < NumObjectBuffers; i++)
|
||||
{
|
||||
memset(ObjectBuffer[i], 0, sizeof(ObjectBuffer[i]));
|
||||
DrawnToBuffer[i] = false;
|
||||
ObjectBufferName[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void SaveTexture(const char* filename, u32 texmap, s32 mip)
|
||||
{
|
||||
FourTexUnits& texUnit = bpmem.tex[(texmap >> 2) & 1];
|
||||
u8 subTexmap = texmap & 3;
|
||||
|
||||
TexImage0& ti0 = texUnit.texImage0[subTexmap];
|
||||
|
||||
int width = ti0.width + 1;
|
||||
int height = ti0.height + 1;
|
||||
|
||||
u8 *data = new u8[width * height * 4];
|
||||
|
||||
GetTextureBGRA(data, texmap, mip, width, height);
|
||||
|
||||
(void)SaveTGA(filename, width, height, data);
|
||||
|
||||
delete []data;
|
||||
}
|
||||
|
||||
void GetTextureBGRA(u8 *dst, u32 texmap, s32 mip, int width, int height)
|
||||
{
|
||||
u8 sample[4];
|
||||
|
||||
for (int y = 0; y < height; y++)
|
||||
for (int x = 0; x < width; x++) {
|
||||
TextureSampler::SampleMip(x << 7, y << 7, mip, false, texmap, sample);
|
||||
// rgba to bgra
|
||||
*(dst++) = sample[2];
|
||||
*(dst++) = sample[1];
|
||||
*(dst++) = sample[0];
|
||||
*(dst++) = sample[3];
|
||||
}
|
||||
}
|
||||
|
||||
s32 GetMaxTextureLod(u32 texmap)
|
||||
{
|
||||
FourTexUnits& texUnit = bpmem.tex[(texmap >> 2) & 1];
|
||||
u8 subTexmap = texmap & 3;
|
||||
|
||||
u8 maxLod = texUnit.texMode1[subTexmap].max_lod;
|
||||
u8 mip = maxLod >> 4;
|
||||
u8 fract = maxLod & 0xf;
|
||||
|
||||
if(fract)
|
||||
++mip;
|
||||
|
||||
return (s32)mip;
|
||||
}
|
||||
|
||||
void DumpActiveTextures()
|
||||
{
|
||||
for (unsigned int stageNum = 0; stageNum < bpmem.genMode.numindstages; stageNum++)
|
||||
{
|
||||
u32 texmap = bpmem.tevindref.getTexMap(stageNum);
|
||||
|
||||
s32 maxLod = GetMaxTextureLod(texmap);
|
||||
for (s32 mip = 0; mip <= maxLod; ++mip)
|
||||
{
|
||||
SaveTexture(StringFromFormat("%star%i_ind%i_map%i_mip%i.tga", File::GetUserPath(D_DUMPTEXTURES_IDX), stats.thisFrame.numDrawnObjects, stageNum, texmap, mip).c_str(), texmap, mip);
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned int stageNum = 0; stageNum <= bpmem.genMode.numtevstages; stageNum++)
|
||||
{
|
||||
int stageNum2 = stageNum >> 1;
|
||||
int stageOdd = stageNum&1;
|
||||
TwoTevStageOrders &order = bpmem.tevorders[stageNum2];
|
||||
|
||||
int texmap = order.getTexMap(stageOdd);
|
||||
|
||||
s32 maxLod = GetMaxTextureLod(texmap);
|
||||
for (s32 mip = 0; mip <= maxLod; ++mip)
|
||||
{
|
||||
SaveTexture(StringFromFormat("%star%i_stage%i_map%i_mip%i.tga", File::GetUserPath(D_DUMPTEXTURES_IDX), stats.thisFrame.numDrawnObjects, stageNum, texmap, mip).c_str(), texmap, mip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DumpEfb(const char* filename)
|
||||
{
|
||||
u8 *data = new u8[EFB_WIDTH * EFB_HEIGHT * 4];
|
||||
u8 *writePtr = data;
|
||||
u8 sample[4];
|
||||
|
||||
for (int y = 0; y < EFB_HEIGHT; y++)
|
||||
for (int x = 0; x < EFB_WIDTH; x++) {
|
||||
EfbInterface::GetColor(x, y, sample);
|
||||
// rgba to bgra
|
||||
*(writePtr++) = sample[2];
|
||||
*(writePtr++) = sample[1];
|
||||
*(writePtr++) = sample[0];
|
||||
*(writePtr++) = sample[3];
|
||||
}
|
||||
|
||||
(void)SaveTGA(filename, EFB_WIDTH, EFB_HEIGHT, data);
|
||||
|
||||
delete []data;
|
||||
}
|
||||
|
||||
void DumpDepth(const char* filename)
|
||||
{
|
||||
u8 *data = new u8[EFB_WIDTH * EFB_HEIGHT * 4];
|
||||
u8 *writePtr = data;
|
||||
|
||||
for (int y = 0; y < EFB_HEIGHT; y++)
|
||||
for (int x = 0; x < EFB_WIDTH; x++) {
|
||||
u32 depth = EfbInterface::GetDepth(x, y);
|
||||
// depth to bgra
|
||||
*(writePtr++) = (depth >> 16) & 0xff;
|
||||
*(writePtr++) = (depth >> 8) & 0xff;
|
||||
*(writePtr++) = depth & 0xff;
|
||||
*(writePtr++) = 255;
|
||||
}
|
||||
|
||||
(void)SaveTGA(filename, EFB_WIDTH, EFB_HEIGHT, data);
|
||||
|
||||
delete []data;
|
||||
}
|
||||
|
||||
void DrawObjectBuffer(s16 x, s16 y, u8 *color, int buffer, const char *name)
|
||||
{
|
||||
u32 offset = (x + y * EFB_WIDTH) * 4;
|
||||
u8 *dst = &ObjectBuffer[buffer][offset];
|
||||
*(dst++) = color[2];
|
||||
*(dst++) = color[1];
|
||||
*(dst++) = color[0];
|
||||
*(dst++) = color[3];
|
||||
|
||||
DrawnToBuffer[buffer] = true;
|
||||
ObjectBufferName[buffer] = name;
|
||||
}
|
||||
|
||||
void OnObjectBegin()
|
||||
{
|
||||
if (!g_bSkipCurrentFrame)
|
||||
{
|
||||
if (g_Config.bDumpTextures && stats.thisFrame.numDrawnObjects >= g_Config.drawStart && stats.thisFrame.numDrawnObjects < g_Config.drawEnd)
|
||||
DumpActiveTextures();
|
||||
|
||||
if (g_Config.bHwRasterizer)
|
||||
HwRasterizer::BeginTriangles();
|
||||
}
|
||||
}
|
||||
|
||||
void OnObjectEnd()
|
||||
{
|
||||
if (!g_bSkipCurrentFrame)
|
||||
{
|
||||
if (g_Config.bDumpObjects && stats.thisFrame.numDrawnObjects >= g_Config.drawStart && stats.thisFrame.numDrawnObjects < g_Config.drawEnd)
|
||||
DumpEfb(StringFromFormat("%sobject%i.tga", File::GetUserPath(D_DUMPFRAMES_IDX), stats.thisFrame.numDrawnObjects).c_str());
|
||||
|
||||
if (g_Config.bHwRasterizer)
|
||||
HwRasterizer::EndTriangles();
|
||||
|
||||
for (int i = 0; i < NumObjectBuffers; i++)
|
||||
{
|
||||
if (DrawnToBuffer[i])
|
||||
{
|
||||
DrawnToBuffer[i] = false;
|
||||
(void)SaveTGA(StringFromFormat("%sobject%i_%s(%i).tga", File::GetUserPath(D_DUMPFRAMES_IDX),
|
||||
stats.thisFrame.numDrawnObjects, ObjectBufferName[i], i).c_str(), EFB_WIDTH, EFB_HEIGHT, ObjectBuffer[i]);
|
||||
memset(ObjectBuffer[i], 0, sizeof(ObjectBuffer[i]));
|
||||
}
|
||||
}
|
||||
|
||||
stats.thisFrame.numDrawnObjects++;
|
||||
}
|
||||
}
|
||||
|
||||
void OnFrameEnd()
|
||||
{
|
||||
if (!g_bSkipCurrentFrame)
|
||||
{
|
||||
if (g_Config.bDumpFrames)
|
||||
{
|
||||
DumpEfb(StringFromFormat("%sframe%i_color.tga", File::GetUserPath(D_DUMPFRAMES_IDX), stats.frameCount).c_str());
|
||||
DumpDepth(StringFromFormat("%sframe%i_depth.tga", File::GetUserPath(D_DUMPFRAMES_IDX), stats.frameCount).c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
#include "main.h"
|
||||
#include "DebugUtil.h"
|
||||
#include "BPMemLoader.h"
|
||||
#include "TextureSampler.h"
|
||||
#include "VideoConfig.h"
|
||||
#include "EfbInterface.h"
|
||||
#include "Statistics.h"
|
||||
#include "HwRasterizer.h"
|
||||
#include "StringUtil.h"
|
||||
#include "CommandProcessor.h"
|
||||
#include "../../../Core/VideoCommon/Src/ImageWrite.h"
|
||||
#include "FileUtil.h"
|
||||
|
||||
namespace DebugUtil
|
||||
{
|
||||
|
||||
u32 skipFrames = 0;
|
||||
const int NumObjectBuffers = 32;
|
||||
u8 ObjectBuffer[NumObjectBuffers][EFB_WIDTH*EFB_HEIGHT*4];
|
||||
bool DrawnToBuffer[NumObjectBuffers];
|
||||
const char* ObjectBufferName[NumObjectBuffers];
|
||||
|
||||
void Init()
|
||||
{
|
||||
for (int i = 0; i < NumObjectBuffers; i++)
|
||||
{
|
||||
memset(ObjectBuffer[i], 0, sizeof(ObjectBuffer[i]));
|
||||
DrawnToBuffer[i] = false;
|
||||
ObjectBufferName[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void SaveTexture(const char* filename, u32 texmap, s32 mip)
|
||||
{
|
||||
FourTexUnits& texUnit = bpmem.tex[(texmap >> 2) & 1];
|
||||
u8 subTexmap = texmap & 3;
|
||||
|
||||
TexImage0& ti0 = texUnit.texImage0[subTexmap];
|
||||
|
||||
int width = ti0.width + 1;
|
||||
int height = ti0.height + 1;
|
||||
|
||||
u8 *data = new u8[width * height * 4];
|
||||
|
||||
GetTextureBGRA(data, texmap, mip, width, height);
|
||||
|
||||
(void)SaveTGA(filename, width, height, data);
|
||||
|
||||
delete []data;
|
||||
}
|
||||
|
||||
void GetTextureBGRA(u8 *dst, u32 texmap, s32 mip, int width, int height)
|
||||
{
|
||||
u8 sample[4];
|
||||
|
||||
for (int y = 0; y < height; y++)
|
||||
for (int x = 0; x < width; x++) {
|
||||
TextureSampler::SampleMip(x << 7, y << 7, mip, false, texmap, sample);
|
||||
// rgba to bgra
|
||||
*(dst++) = sample[2];
|
||||
*(dst++) = sample[1];
|
||||
*(dst++) = sample[0];
|
||||
*(dst++) = sample[3];
|
||||
}
|
||||
}
|
||||
|
||||
s32 GetMaxTextureLod(u32 texmap)
|
||||
{
|
||||
FourTexUnits& texUnit = bpmem.tex[(texmap >> 2) & 1];
|
||||
u8 subTexmap = texmap & 3;
|
||||
|
||||
u8 maxLod = texUnit.texMode1[subTexmap].max_lod;
|
||||
u8 mip = maxLod >> 4;
|
||||
u8 fract = maxLod & 0xf;
|
||||
|
||||
if(fract)
|
||||
++mip;
|
||||
|
||||
return (s32)mip;
|
||||
}
|
||||
|
||||
void DumpActiveTextures()
|
||||
{
|
||||
for (unsigned int stageNum = 0; stageNum < bpmem.genMode.numindstages; stageNum++)
|
||||
{
|
||||
u32 texmap = bpmem.tevindref.getTexMap(stageNum);
|
||||
|
||||
s32 maxLod = GetMaxTextureLod(texmap);
|
||||
for (s32 mip = 0; mip <= maxLod; ++mip)
|
||||
{
|
||||
SaveTexture(StringFromFormat("%star%i_ind%i_map%i_mip%i.tga", File::GetUserPath(D_DUMPTEXTURES_IDX), stats.thisFrame.numDrawnObjects, stageNum, texmap, mip).c_str(), texmap, mip);
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned int stageNum = 0; stageNum <= bpmem.genMode.numtevstages; stageNum++)
|
||||
{
|
||||
int stageNum2 = stageNum >> 1;
|
||||
int stageOdd = stageNum&1;
|
||||
TwoTevStageOrders &order = bpmem.tevorders[stageNum2];
|
||||
|
||||
int texmap = order.getTexMap(stageOdd);
|
||||
|
||||
s32 maxLod = GetMaxTextureLod(texmap);
|
||||
for (s32 mip = 0; mip <= maxLod; ++mip)
|
||||
{
|
||||
SaveTexture(StringFromFormat("%star%i_stage%i_map%i_mip%i.tga", File::GetUserPath(D_DUMPTEXTURES_IDX), stats.thisFrame.numDrawnObjects, stageNum, texmap, mip).c_str(), texmap, mip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DumpEfb(const char* filename)
|
||||
{
|
||||
u8 *data = new u8[EFB_WIDTH * EFB_HEIGHT * 4];
|
||||
u8 *writePtr = data;
|
||||
u8 sample[4];
|
||||
|
||||
for (int y = 0; y < EFB_HEIGHT; y++)
|
||||
for (int x = 0; x < EFB_WIDTH; x++) {
|
||||
EfbInterface::GetColor(x, y, sample);
|
||||
// rgba to bgra
|
||||
*(writePtr++) = sample[2];
|
||||
*(writePtr++) = sample[1];
|
||||
*(writePtr++) = sample[0];
|
||||
*(writePtr++) = sample[3];
|
||||
}
|
||||
|
||||
(void)SaveTGA(filename, EFB_WIDTH, EFB_HEIGHT, data);
|
||||
|
||||
delete []data;
|
||||
}
|
||||
|
||||
void DumpDepth(const char* filename)
|
||||
{
|
||||
u8 *data = new u8[EFB_WIDTH * EFB_HEIGHT * 4];
|
||||
u8 *writePtr = data;
|
||||
|
||||
for (int y = 0; y < EFB_HEIGHT; y++)
|
||||
for (int x = 0; x < EFB_WIDTH; x++) {
|
||||
u32 depth = EfbInterface::GetDepth(x, y);
|
||||
// depth to bgra
|
||||
*(writePtr++) = (depth >> 16) & 0xff;
|
||||
*(writePtr++) = (depth >> 8) & 0xff;
|
||||
*(writePtr++) = depth & 0xff;
|
||||
*(writePtr++) = 255;
|
||||
}
|
||||
|
||||
(void)SaveTGA(filename, EFB_WIDTH, EFB_HEIGHT, data);
|
||||
|
||||
delete []data;
|
||||
}
|
||||
|
||||
void DrawObjectBuffer(s16 x, s16 y, u8 *color, int buffer, const char *name)
|
||||
{
|
||||
u32 offset = (x + y * EFB_WIDTH) * 4;
|
||||
u8 *dst = &ObjectBuffer[buffer][offset];
|
||||
*(dst++) = color[2];
|
||||
*(dst++) = color[1];
|
||||
*(dst++) = color[0];
|
||||
*(dst++) = color[3];
|
||||
|
||||
DrawnToBuffer[buffer] = true;
|
||||
ObjectBufferName[buffer] = name;
|
||||
}
|
||||
|
||||
void OnObjectBegin()
|
||||
{
|
||||
if (!g_bSkipCurrentFrame)
|
||||
{
|
||||
if (g_Config.bDumpTextures && stats.thisFrame.numDrawnObjects >= g_Config.drawStart && stats.thisFrame.numDrawnObjects < g_Config.drawEnd)
|
||||
DumpActiveTextures();
|
||||
|
||||
if (g_Config.bHwRasterizer)
|
||||
HwRasterizer::BeginTriangles();
|
||||
}
|
||||
}
|
||||
|
||||
void OnObjectEnd()
|
||||
{
|
||||
if (!g_bSkipCurrentFrame)
|
||||
{
|
||||
if (g_Config.bDumpObjects && stats.thisFrame.numDrawnObjects >= g_Config.drawStart && stats.thisFrame.numDrawnObjects < g_Config.drawEnd)
|
||||
DumpEfb(StringFromFormat("%sobject%i.tga", File::GetUserPath(D_DUMPFRAMES_IDX), stats.thisFrame.numDrawnObjects).c_str());
|
||||
|
||||
if (g_Config.bHwRasterizer)
|
||||
HwRasterizer::EndTriangles();
|
||||
|
||||
for (int i = 0; i < NumObjectBuffers; i++)
|
||||
{
|
||||
if (DrawnToBuffer[i])
|
||||
{
|
||||
DrawnToBuffer[i] = false;
|
||||
(void)SaveTGA(StringFromFormat("%sobject%i_%s(%i).tga", File::GetUserPath(D_DUMPFRAMES_IDX),
|
||||
stats.thisFrame.numDrawnObjects, ObjectBufferName[i], i).c_str(), EFB_WIDTH, EFB_HEIGHT, ObjectBuffer[i]);
|
||||
memset(ObjectBuffer[i], 0, sizeof(ObjectBuffer[i]));
|
||||
}
|
||||
}
|
||||
|
||||
stats.thisFrame.numDrawnObjects++;
|
||||
}
|
||||
}
|
||||
|
||||
void OnFrameEnd()
|
||||
{
|
||||
if (!g_bSkipCurrentFrame)
|
||||
{
|
||||
if (g_Config.bDumpFrames)
|
||||
{
|
||||
DumpEfb(StringFromFormat("%sframe%i_color.tga", File::GetUserPath(D_DUMPFRAMES_IDX), stats.frameCount).c_str());
|
||||
DumpDepth(StringFromFormat("%sframe%i_depth.tga", File::GetUserPath(D_DUMPFRAMES_IDX), stats.frameCount).c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,108 +1,108 @@
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "main.h"
|
||||
#include "BPMemLoader.h"
|
||||
#include "EfbCopy.h"
|
||||
#include "EfbInterface.h"
|
||||
#include "Renderer.h"
|
||||
#include "TextureEncoder.h"
|
||||
#include "Statistics.h"
|
||||
#include "VideoConfig.h"
|
||||
#include "DebugUtil.h"
|
||||
#include "HwRasterizer.h"
|
||||
#include "CommandProcessor.h"
|
||||
|
||||
|
||||
namespace EfbCopy
|
||||
{
|
||||
void CopyToXfb()
|
||||
{
|
||||
if (!g_Config.bHwRasterizer)
|
||||
{
|
||||
// copy to open gl for rendering
|
||||
EfbInterface::UpdateColorTexture();
|
||||
Renderer::DrawTexture(EfbInterface::efbColorTexture, EFB_WIDTH, EFB_HEIGHT);
|
||||
}
|
||||
|
||||
Renderer::SwapBuffer();
|
||||
|
||||
}
|
||||
|
||||
void CopyToRam()
|
||||
{
|
||||
u8 *dest_ptr = g_VideoInitialize.pGetMemoryPointer(bpmem.copyTexDest << 5);
|
||||
|
||||
TextureEncoder::Encode(dest_ptr);
|
||||
}
|
||||
|
||||
void ClearEfb()
|
||||
{
|
||||
u32 clearColor = (bpmem.clearcolorAR & 0xff) | Common::swap16(bpmem.clearcolorGB) << 8 | (bpmem.clearcolorAR & 0xff00) << 16;
|
||||
|
||||
int left = bpmem.copyTexSrcXY.x;
|
||||
int top = bpmem.copyTexSrcXY.y;
|
||||
int right = left + bpmem.copyTexSrcWH.x;
|
||||
int bottom = top + bpmem.copyTexSrcWH.y;
|
||||
|
||||
for (u16 y = top; y <= bottom; y++)
|
||||
{
|
||||
for (u16 x = left; x <= right; x++)
|
||||
{
|
||||
EfbInterface::SetColor(x, y, (u8*)(&clearColor));
|
||||
EfbInterface::SetDepth(x, y, bpmem.clearZValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CopyEfb()
|
||||
{
|
||||
if (bpmem.triggerEFBCopy.copy_to_xfb)
|
||||
DebugUtil::OnFrameEnd();
|
||||
|
||||
if (!g_bSkipCurrentFrame)
|
||||
{
|
||||
if (bpmem.triggerEFBCopy.copy_to_xfb)
|
||||
{
|
||||
CopyToXfb();
|
||||
g_VideoInitialize.pCopiedToXFB(false);
|
||||
|
||||
stats.frameCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
CopyToRam();
|
||||
}
|
||||
|
||||
if (bpmem.triggerEFBCopy.clear)
|
||||
{
|
||||
if (g_Config.bHwRasterizer)
|
||||
HwRasterizer::Clear();
|
||||
else
|
||||
ClearEfb();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bpmem.triggerEFBCopy.copy_to_xfb)
|
||||
{
|
||||
// no frame rendered but tell that a frame has finished for frame skip counter
|
||||
g_VideoInitialize.pCopiedToXFB(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "main.h"
|
||||
#include "BPMemLoader.h"
|
||||
#include "EfbCopy.h"
|
||||
#include "EfbInterface.h"
|
||||
#include "Renderer.h"
|
||||
#include "TextureEncoder.h"
|
||||
#include "Statistics.h"
|
||||
#include "VideoConfig.h"
|
||||
#include "DebugUtil.h"
|
||||
#include "HwRasterizer.h"
|
||||
#include "CommandProcessor.h"
|
||||
|
||||
|
||||
namespace EfbCopy
|
||||
{
|
||||
void CopyToXfb()
|
||||
{
|
||||
if (!g_Config.bHwRasterizer)
|
||||
{
|
||||
// copy to open gl for rendering
|
||||
EfbInterface::UpdateColorTexture();
|
||||
Renderer::DrawTexture(EfbInterface::efbColorTexture, EFB_WIDTH, EFB_HEIGHT);
|
||||
}
|
||||
|
||||
Renderer::SwapBuffer();
|
||||
|
||||
}
|
||||
|
||||
void CopyToRam()
|
||||
{
|
||||
u8 *dest_ptr = g_VideoInitialize.pGetMemoryPointer(bpmem.copyTexDest << 5);
|
||||
|
||||
TextureEncoder::Encode(dest_ptr);
|
||||
}
|
||||
|
||||
void ClearEfb()
|
||||
{
|
||||
u32 clearColor = (bpmem.clearcolorAR & 0xff) | Common::swap16(bpmem.clearcolorGB) << 8 | (bpmem.clearcolorAR & 0xff00) << 16;
|
||||
|
||||
int left = bpmem.copyTexSrcXY.x;
|
||||
int top = bpmem.copyTexSrcXY.y;
|
||||
int right = left + bpmem.copyTexSrcWH.x;
|
||||
int bottom = top + bpmem.copyTexSrcWH.y;
|
||||
|
||||
for (u16 y = top; y <= bottom; y++)
|
||||
{
|
||||
for (u16 x = left; x <= right; x++)
|
||||
{
|
||||
EfbInterface::SetColor(x, y, (u8*)(&clearColor));
|
||||
EfbInterface::SetDepth(x, y, bpmem.clearZValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CopyEfb()
|
||||
{
|
||||
if (bpmem.triggerEFBCopy.copy_to_xfb)
|
||||
DebugUtil::OnFrameEnd();
|
||||
|
||||
if (!g_bSkipCurrentFrame)
|
||||
{
|
||||
if (bpmem.triggerEFBCopy.copy_to_xfb)
|
||||
{
|
||||
CopyToXfb();
|
||||
g_VideoInitialize.pCopiedToXFB(false);
|
||||
|
||||
stats.frameCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
CopyToRam();
|
||||
}
|
||||
|
||||
if (bpmem.triggerEFBCopy.clear)
|
||||
{
|
||||
if (g_Config.bHwRasterizer)
|
||||
HwRasterizer::Clear();
|
||||
else
|
||||
ClearEfb();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bpmem.triggerEFBCopy.copy_to_xfb)
|
||||
{
|
||||
// no frame rendered but tell that a frame has finished for frame skip counter
|
||||
g_VideoInitialize.pCopiedToXFB(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,50 +1,50 @@
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _EFB_INTERFACE_H_
|
||||
#define _EFB_INTERFACE_H_
|
||||
|
||||
#include "VideoCommon.h"
|
||||
|
||||
namespace EfbInterface
|
||||
{
|
||||
const int DEPTH_BUFFER_START = EFB_WIDTH * EFB_HEIGHT * 3;
|
||||
|
||||
// color order is RGBA
|
||||
|
||||
// does full blending of an incoming pixel
|
||||
void BlendTev(u16 x, u16 y, u8 *color);
|
||||
|
||||
// compare z at location x,y
|
||||
// writes it if it passes
|
||||
// returns result of compare.
|
||||
bool ZCompare(u16 x, u16 y, u32 z);
|
||||
|
||||
// sets the color and alpha
|
||||
void SetColor(u16 x, u16 y, u8 *color);
|
||||
void SetDepth(u16 x, u16 y, u32 depth);
|
||||
|
||||
void GetColor(u16 x, u16 y, u8 *color);
|
||||
u32 GetDepth(u16 x, u16 y);
|
||||
|
||||
u8* GetPixelPointer(u16 x, u16 y, bool depth);
|
||||
|
||||
void UpdateColorTexture();
|
||||
extern u8 efbColorTexture[EFB_WIDTH*EFB_HEIGHT*4]; // rgba format
|
||||
}
|
||||
|
||||
#endif
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _EFB_INTERFACE_H_
|
||||
#define _EFB_INTERFACE_H_
|
||||
|
||||
#include "VideoCommon.h"
|
||||
|
||||
namespace EfbInterface
|
||||
{
|
||||
const int DEPTH_BUFFER_START = EFB_WIDTH * EFB_HEIGHT * 3;
|
||||
|
||||
// color order is RGBA
|
||||
|
||||
// does full blending of an incoming pixel
|
||||
void BlendTev(u16 x, u16 y, u8 *color);
|
||||
|
||||
// compare z at location x,y
|
||||
// writes it if it passes
|
||||
// returns result of compare.
|
||||
bool ZCompare(u16 x, u16 y, u32 z);
|
||||
|
||||
// sets the color and alpha
|
||||
void SetColor(u16 x, u16 y, u8 *color);
|
||||
void SetDepth(u16 x, u16 y, u32 depth);
|
||||
|
||||
void GetColor(u16 x, u16 y, u8 *color);
|
||||
u32 GetDepth(u16 x, u16 y);
|
||||
|
||||
u8* GetPixelPointer(u16 x, u16 y, bool depth);
|
||||
|
||||
void UpdateColorTexture();
|
||||
extern u8 efbColorTexture[EFB_WIDTH*EFB_HEIGHT*4]; // rgba format
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,191 +1,191 @@
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "Common.h"
|
||||
#include "MemoryUtil.h"
|
||||
|
||||
#include <VideoCommon.h>
|
||||
|
||||
#include "BPMemLoader.h"
|
||||
#include "HwRasterizer.h"
|
||||
#include "GLUtil.h"
|
||||
#include "NativeVertexFormat.h"
|
||||
#include "DebugUtil.h"
|
||||
|
||||
#define TEMP_SIZE (1024*1024*4)
|
||||
|
||||
namespace HwRasterizer
|
||||
{
|
||||
float efbHalfWidth;
|
||||
float efbHalfHeight;
|
||||
float texWidth;
|
||||
float texHeight;
|
||||
bool hasTexture;
|
||||
|
||||
u8 *temp;
|
||||
|
||||
void Init()
|
||||
{
|
||||
efbHalfWidth = EFB_WIDTH / 2.0f;
|
||||
efbHalfHeight = 480 / 2.0f;
|
||||
|
||||
temp = (u8*)AllocateMemoryPages(TEMP_SIZE);
|
||||
}
|
||||
|
||||
void LoadTexture()
|
||||
{
|
||||
FourTexUnits &texUnit = bpmem.tex[0];
|
||||
u32 imageAddr = texUnit.texImage3[0].image_base;
|
||||
|
||||
TexCacheEntry &cacheEntry = textures[imageAddr];
|
||||
cacheEntry.Update();
|
||||
|
||||
texWidth = (float)(bpmem.texcoords[0].s.scale_minus_1 + 1);
|
||||
texHeight = (float)(bpmem.texcoords[0].t.scale_minus_1 + 1);
|
||||
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, cacheEntry.texture);
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, texUnit.texMode0[0].mag_filter ? GL_LINEAR : GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, (texUnit.texMode0[0].min_filter >= 4) ? GL_LINEAR : GL_NEAREST);
|
||||
}
|
||||
|
||||
void BeginTriangles()
|
||||
{
|
||||
// disabling depth test sometimes allows more things to be visible
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
hasTexture = bpmem.tevorders[0].enable0;
|
||||
|
||||
if (hasTexture)
|
||||
LoadTexture();
|
||||
}
|
||||
|
||||
void EndTriangles()
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
void DrawColorVertex(OutputVertexData *v)
|
||||
{
|
||||
glColor3ub(v->color[0][0], v->color[0][1], v->color[0][2]);
|
||||
glVertex3f(v->screenPosition.x / efbHalfWidth - 1.0f, 1.0f - v->screenPosition.y / efbHalfHeight, v->screenPosition.z);
|
||||
}
|
||||
|
||||
void DrawTextureVertex(OutputVertexData *v)
|
||||
{
|
||||
glTexCoord2f(v->texCoords[0].x * texWidth, v->texCoords[0].y * texHeight);
|
||||
glVertex3f(v->screenPosition.x / efbHalfWidth - 1.0f, 1.0f - v->screenPosition.y / efbHalfHeight, v->screenPosition.z);
|
||||
}
|
||||
|
||||
void DrawTriangleFrontFace(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2)
|
||||
{
|
||||
glBegin(GL_TRIANGLES);
|
||||
if (hasTexture)
|
||||
{
|
||||
DrawTextureVertex(v0);
|
||||
DrawTextureVertex(v1);
|
||||
DrawTextureVertex(v2);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawColorVertex(v0);
|
||||
DrawColorVertex(v1);
|
||||
DrawColorVertex(v2);
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
u8 r = (bpmem.clearcolorAR & 0x00ff);
|
||||
u8 g = (bpmem.clearcolorGB & 0xff00) >> 8;
|
||||
u8 b = (bpmem.clearcolorGB & 0x00ff);
|
||||
u8 a = (bpmem.clearcolorAR & 0xff00) >> 8;
|
||||
|
||||
GLfloat left = (GLfloat)bpmem.copyTexSrcXY.x / efbHalfWidth - 1.0f;
|
||||
GLfloat top = 1.0f - (GLfloat)bpmem.copyTexSrcXY.y / efbHalfHeight;
|
||||
GLfloat right = (GLfloat)(left + bpmem.copyTexSrcWH.x + 1) / efbHalfWidth - 1.0f;
|
||||
GLfloat bottom = 1.0f - (GLfloat)(top + bpmem.copyTexSrcWH.y + 1) / efbHalfHeight;
|
||||
GLfloat depth = (GLfloat)bpmem.clearZValue / (GLfloat)0x00ffffff;
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glColor4ub(r, g, b, a);
|
||||
glVertex3f(left, top, depth);
|
||||
glColor4ub(r, g, b, a);
|
||||
glVertex3f(right, top, depth);
|
||||
glColor4ub(r, g, b, a);
|
||||
glVertex3f(right, bottom, depth);
|
||||
glColor4ub(r, g, b, a);
|
||||
glVertex3f(left, bottom, depth);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
TexCacheEntry::TexCacheEntry()
|
||||
{
|
||||
Create();
|
||||
}
|
||||
|
||||
void TexCacheEntry::Create()
|
||||
{
|
||||
FourTexUnits &texUnit = bpmem.tex[0];
|
||||
|
||||
texImage0.hex = texUnit.texImage0[0].hex;
|
||||
texImage1.hex = texUnit.texImage1[0].hex;
|
||||
texImage2.hex = texUnit.texImage2[0].hex;
|
||||
texImage3.hex = texUnit.texImage3[0].hex;
|
||||
texTlut.hex = texUnit.texTlut[0].hex;
|
||||
|
||||
int width = texImage0.width;
|
||||
int height = texImage0.height;
|
||||
|
||||
DebugUtil::GetTextureBGRA(temp, 0, 0, width, height);
|
||||
|
||||
glGenTextures(1, (GLuint *)&texture);
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture);
|
||||
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, (GLsizei)width, (GLsizei)height, 0, GL_BGRA, GL_UNSIGNED_BYTE, temp);
|
||||
}
|
||||
|
||||
void TexCacheEntry::Destroy()
|
||||
{
|
||||
if (texture == 0)
|
||||
return;
|
||||
|
||||
glDeleteTextures(1, &texture);
|
||||
texture = 0;
|
||||
}
|
||||
|
||||
void TexCacheEntry::Update()
|
||||
{
|
||||
FourTexUnits &texUnit = bpmem.tex[0];
|
||||
|
||||
// extra checks cause textures to be reloaded much more
|
||||
if (texUnit.texImage0[0].hex != texImage0.hex ||
|
||||
//texUnit.texImage1[0].hex != texImage1.hex ||
|
||||
//texUnit.texImage2[0].hex != texImage2.hex ||
|
||||
texUnit.texImage3[0].hex != texImage3.hex ||
|
||||
texUnit.texTlut[0].hex != texTlut.hex)
|
||||
{
|
||||
Destroy();
|
||||
Create();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "Common.h"
|
||||
#include "MemoryUtil.h"
|
||||
|
||||
#include <VideoCommon.h>
|
||||
|
||||
#include "BPMemLoader.h"
|
||||
#include "HwRasterizer.h"
|
||||
#include "GLUtil.h"
|
||||
#include "NativeVertexFormat.h"
|
||||
#include "DebugUtil.h"
|
||||
|
||||
#define TEMP_SIZE (1024*1024*4)
|
||||
|
||||
namespace HwRasterizer
|
||||
{
|
||||
float efbHalfWidth;
|
||||
float efbHalfHeight;
|
||||
float texWidth;
|
||||
float texHeight;
|
||||
bool hasTexture;
|
||||
|
||||
u8 *temp;
|
||||
|
||||
void Init()
|
||||
{
|
||||
efbHalfWidth = EFB_WIDTH / 2.0f;
|
||||
efbHalfHeight = 480 / 2.0f;
|
||||
|
||||
temp = (u8*)AllocateMemoryPages(TEMP_SIZE);
|
||||
}
|
||||
|
||||
void LoadTexture()
|
||||
{
|
||||
FourTexUnits &texUnit = bpmem.tex[0];
|
||||
u32 imageAddr = texUnit.texImage3[0].image_base;
|
||||
|
||||
TexCacheEntry &cacheEntry = textures[imageAddr];
|
||||
cacheEntry.Update();
|
||||
|
||||
texWidth = (float)(bpmem.texcoords[0].s.scale_minus_1 + 1);
|
||||
texHeight = (float)(bpmem.texcoords[0].t.scale_minus_1 + 1);
|
||||
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, cacheEntry.texture);
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, texUnit.texMode0[0].mag_filter ? GL_LINEAR : GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, (texUnit.texMode0[0].min_filter >= 4) ? GL_LINEAR : GL_NEAREST);
|
||||
}
|
||||
|
||||
void BeginTriangles()
|
||||
{
|
||||
// disabling depth test sometimes allows more things to be visible
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
hasTexture = bpmem.tevorders[0].enable0;
|
||||
|
||||
if (hasTexture)
|
||||
LoadTexture();
|
||||
}
|
||||
|
||||
void EndTriangles()
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
void DrawColorVertex(OutputVertexData *v)
|
||||
{
|
||||
glColor3ub(v->color[0][0], v->color[0][1], v->color[0][2]);
|
||||
glVertex3f(v->screenPosition.x / efbHalfWidth - 1.0f, 1.0f - v->screenPosition.y / efbHalfHeight, v->screenPosition.z);
|
||||
}
|
||||
|
||||
void DrawTextureVertex(OutputVertexData *v)
|
||||
{
|
||||
glTexCoord2f(v->texCoords[0].x * texWidth, v->texCoords[0].y * texHeight);
|
||||
glVertex3f(v->screenPosition.x / efbHalfWidth - 1.0f, 1.0f - v->screenPosition.y / efbHalfHeight, v->screenPosition.z);
|
||||
}
|
||||
|
||||
void DrawTriangleFrontFace(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2)
|
||||
{
|
||||
glBegin(GL_TRIANGLES);
|
||||
if (hasTexture)
|
||||
{
|
||||
DrawTextureVertex(v0);
|
||||
DrawTextureVertex(v1);
|
||||
DrawTextureVertex(v2);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawColorVertex(v0);
|
||||
DrawColorVertex(v1);
|
||||
DrawColorVertex(v2);
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
u8 r = (bpmem.clearcolorAR & 0x00ff);
|
||||
u8 g = (bpmem.clearcolorGB & 0xff00) >> 8;
|
||||
u8 b = (bpmem.clearcolorGB & 0x00ff);
|
||||
u8 a = (bpmem.clearcolorAR & 0xff00) >> 8;
|
||||
|
||||
GLfloat left = (GLfloat)bpmem.copyTexSrcXY.x / efbHalfWidth - 1.0f;
|
||||
GLfloat top = 1.0f - (GLfloat)bpmem.copyTexSrcXY.y / efbHalfHeight;
|
||||
GLfloat right = (GLfloat)(left + bpmem.copyTexSrcWH.x + 1) / efbHalfWidth - 1.0f;
|
||||
GLfloat bottom = 1.0f - (GLfloat)(top + bpmem.copyTexSrcWH.y + 1) / efbHalfHeight;
|
||||
GLfloat depth = (GLfloat)bpmem.clearZValue / (GLfloat)0x00ffffff;
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glColor4ub(r, g, b, a);
|
||||
glVertex3f(left, top, depth);
|
||||
glColor4ub(r, g, b, a);
|
||||
glVertex3f(right, top, depth);
|
||||
glColor4ub(r, g, b, a);
|
||||
glVertex3f(right, bottom, depth);
|
||||
glColor4ub(r, g, b, a);
|
||||
glVertex3f(left, bottom, depth);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
TexCacheEntry::TexCacheEntry()
|
||||
{
|
||||
Create();
|
||||
}
|
||||
|
||||
void TexCacheEntry::Create()
|
||||
{
|
||||
FourTexUnits &texUnit = bpmem.tex[0];
|
||||
|
||||
texImage0.hex = texUnit.texImage0[0].hex;
|
||||
texImage1.hex = texUnit.texImage1[0].hex;
|
||||
texImage2.hex = texUnit.texImage2[0].hex;
|
||||
texImage3.hex = texUnit.texImage3[0].hex;
|
||||
texTlut.hex = texUnit.texTlut[0].hex;
|
||||
|
||||
int width = texImage0.width;
|
||||
int height = texImage0.height;
|
||||
|
||||
DebugUtil::GetTextureBGRA(temp, 0, 0, width, height);
|
||||
|
||||
glGenTextures(1, (GLuint *)&texture);
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture);
|
||||
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, (GLsizei)width, (GLsizei)height, 0, GL_BGRA, GL_UNSIGNED_BYTE, temp);
|
||||
}
|
||||
|
||||
void TexCacheEntry::Destroy()
|
||||
{
|
||||
if (texture == 0)
|
||||
return;
|
||||
|
||||
glDeleteTextures(1, &texture);
|
||||
texture = 0;
|
||||
}
|
||||
|
||||
void TexCacheEntry::Update()
|
||||
{
|
||||
FourTexUnits &texUnit = bpmem.tex[0];
|
||||
|
||||
// extra checks cause textures to be reloaded much more
|
||||
if (texUnit.texImage0[0].hex != texImage0.hex ||
|
||||
//texUnit.texImage1[0].hex != texImage1.hex ||
|
||||
//texUnit.texImage2[0].hex != texImage2.hex ||
|
||||
texUnit.texImage3[0].hex != texImage3.hex ||
|
||||
texUnit.texTlut[0].hex != texTlut.hex)
|
||||
{
|
||||
Destroy();
|
||||
Create();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -1,60 +1,60 @@
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _HW_RASTERIZER_H
|
||||
#define _HW_RASTERIZER_H
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "BPMemLoader.h"
|
||||
#include "GLUtil.h"
|
||||
|
||||
struct OutputVertexData;
|
||||
|
||||
namespace HwRasterizer
|
||||
{
|
||||
void Init();
|
||||
|
||||
void BeginTriangles();
|
||||
void EndTriangles();
|
||||
|
||||
void DrawTriangleFrontFace(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2);
|
||||
|
||||
void Clear();
|
||||
|
||||
struct TexCacheEntry
|
||||
{
|
||||
TexImage0 texImage0;
|
||||
TexImage1 texImage1;
|
||||
TexImage2 texImage2;
|
||||
TexImage3 texImage3;
|
||||
TexTLUT texTlut;
|
||||
|
||||
GLuint texture;
|
||||
|
||||
TexCacheEntry();
|
||||
|
||||
void Create();
|
||||
void Destroy();
|
||||
void Update();
|
||||
};
|
||||
|
||||
typedef std::map<u32, TexCacheEntry> TextureCache;
|
||||
static TextureCache textures;
|
||||
}
|
||||
|
||||
#endif
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _HW_RASTERIZER_H
|
||||
#define _HW_RASTERIZER_H
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "BPMemLoader.h"
|
||||
#include "GLUtil.h"
|
||||
|
||||
struct OutputVertexData;
|
||||
|
||||
namespace HwRasterizer
|
||||
{
|
||||
void Init();
|
||||
|
||||
void BeginTriangles();
|
||||
void EndTriangles();
|
||||
|
||||
void DrawTriangleFrontFace(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2);
|
||||
|
||||
void Clear();
|
||||
|
||||
struct TexCacheEntry
|
||||
{
|
||||
TexImage0 texImage0;
|
||||
TexImage1 texImage1;
|
||||
TexImage2 texImage2;
|
||||
TexImage3 texImage3;
|
||||
TexTLUT texTlut;
|
||||
|
||||
GLuint texture;
|
||||
|
||||
TexCacheEntry();
|
||||
|
||||
void Create();
|
||||
void Destroy();
|
||||
void Update();
|
||||
};
|
||||
|
||||
typedef std::map<u32, TexCacheEntry> TextureCache;
|
||||
static TextureCache textures;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,94 +1,94 @@
|
||||
// Copyright (C) 2003-2008 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _NATIVEVERTEXFORMAT_H
|
||||
#define _NATIVEVERTEXFORMAT_H
|
||||
|
||||
#include "../../Plugin_VideoDX9/Src/Vec3.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#define LOADERDECL __cdecl
|
||||
#else
|
||||
#define LOADERDECL
|
||||
#endif
|
||||
|
||||
typedef void (LOADERDECL *TPipelineFunction)();
|
||||
|
||||
struct Vec4
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
float w;
|
||||
};
|
||||
|
||||
struct InputVertexData
|
||||
{
|
||||
u8 posMtx;
|
||||
u8 texMtx[8];
|
||||
|
||||
Vec3 position;
|
||||
Vec3 normal[3];
|
||||
u8 color[2][4];
|
||||
float texCoords[8][2];
|
||||
};
|
||||
|
||||
struct OutputVertexData
|
||||
{
|
||||
Vec3 mvPosition;
|
||||
Vec4 projectedPosition;
|
||||
Vec3 screenPosition;
|
||||
Vec3 normal[3];
|
||||
u8 color[2][4];
|
||||
Vec3 texCoords[8];
|
||||
|
||||
void Lerp(float t, OutputVertexData *a, OutputVertexData *b)
|
||||
{
|
||||
#define LINTERP(T, OUT, IN) (OUT) + ((IN - OUT) * T)
|
||||
|
||||
#define LINTERP_INT(T, OUT, IN) (OUT) + (((IN - OUT) * T) >> 8)
|
||||
|
||||
mvPosition = LINTERP(t, a->mvPosition, b->mvPosition);
|
||||
|
||||
projectedPosition.x = LINTERP(t, a->projectedPosition.x, b->projectedPosition.x);
|
||||
projectedPosition.y = LINTERP(t, a->projectedPosition.y, b->projectedPosition.y);
|
||||
projectedPosition.z = LINTERP(t, a->projectedPosition.z, b->projectedPosition.z);
|
||||
projectedPosition.w = LINTERP(t, a->projectedPosition.w, b->projectedPosition.w);
|
||||
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
normal[i] = LINTERP(t, a->normal[i], b->normal[i]);
|
||||
}
|
||||
|
||||
u16 t_int = (u16)(t * 256);
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
color[0][i] = LINTERP_INT(t_int, a->color[0][i], b->color[0][i]);
|
||||
color[1][i] = LINTERP_INT(t_int, a->color[1][i], b->color[1][i]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 8; ++i)
|
||||
{
|
||||
texCoords[i] = LINTERP(t, a->texCoords[i], b->texCoords[i]);
|
||||
}
|
||||
|
||||
#undef LINTERP
|
||||
#undef LINTERP_INT
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
// Copyright (C) 2003-2008 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _NATIVEVERTEXFORMAT_H
|
||||
#define _NATIVEVERTEXFORMAT_H
|
||||
|
||||
#include "../../Plugin_VideoDX9/Src/Vec3.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#define LOADERDECL __cdecl
|
||||
#else
|
||||
#define LOADERDECL
|
||||
#endif
|
||||
|
||||
typedef void (LOADERDECL *TPipelineFunction)();
|
||||
|
||||
struct Vec4
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
float w;
|
||||
};
|
||||
|
||||
struct InputVertexData
|
||||
{
|
||||
u8 posMtx;
|
||||
u8 texMtx[8];
|
||||
|
||||
Vec3 position;
|
||||
Vec3 normal[3];
|
||||
u8 color[2][4];
|
||||
float texCoords[8][2];
|
||||
};
|
||||
|
||||
struct OutputVertexData
|
||||
{
|
||||
Vec3 mvPosition;
|
||||
Vec4 projectedPosition;
|
||||
Vec3 screenPosition;
|
||||
Vec3 normal[3];
|
||||
u8 color[2][4];
|
||||
Vec3 texCoords[8];
|
||||
|
||||
void Lerp(float t, OutputVertexData *a, OutputVertexData *b)
|
||||
{
|
||||
#define LINTERP(T, OUT, IN) (OUT) + ((IN - OUT) * T)
|
||||
|
||||
#define LINTERP_INT(T, OUT, IN) (OUT) + (((IN - OUT) * T) >> 8)
|
||||
|
||||
mvPosition = LINTERP(t, a->mvPosition, b->mvPosition);
|
||||
|
||||
projectedPosition.x = LINTERP(t, a->projectedPosition.x, b->projectedPosition.x);
|
||||
projectedPosition.y = LINTERP(t, a->projectedPosition.y, b->projectedPosition.y);
|
||||
projectedPosition.z = LINTERP(t, a->projectedPosition.z, b->projectedPosition.z);
|
||||
projectedPosition.w = LINTERP(t, a->projectedPosition.w, b->projectedPosition.w);
|
||||
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
normal[i] = LINTERP(t, a->normal[i], b->normal[i]);
|
||||
}
|
||||
|
||||
u16 t_int = (u16)(t * 256);
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
color[0][i] = LINTERP_INT(t_int, a->color[0][i], b->color[0][i]);
|
||||
color[1][i] = LINTERP_INT(t_int, a->color[1][i], b->color[1][i]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 8; ++i)
|
||||
{
|
||||
texCoords[i] = LINTERP(t, a->texCoords[i], b->texCoords[i]);
|
||||
}
|
||||
|
||||
#undef LINTERP
|
||||
#undef LINTERP_INT
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -1,30 +1,30 @@
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _NATIVE_VERTEX_WRITER
|
||||
#define _NATIVE_VERTEX_WRITER
|
||||
|
||||
// TODO: rename
|
||||
namespace VertexManager
|
||||
{
|
||||
|
||||
// TODO: move, rename.
|
||||
extern u8* s_pCurBufferPointer;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _NATIVE_VERTEX_WRITER
|
||||
#define _NATIVE_VERTEX_WRITER
|
||||
|
||||
// TODO: rename
|
||||
namespace VertexManager
|
||||
{
|
||||
|
||||
// TODO: move, rename.
|
||||
extern u8* s_pCurBufferPointer;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,297 +1,297 @@
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
#include "../../../Core/VideoCommon/Src/DataReader.h"
|
||||
|
||||
#include "main.h"
|
||||
#include "OpcodeDecoder.h"
|
||||
#include "BPMemLoader.h"
|
||||
#include "CPMemLoader.h"
|
||||
#include "XFMemLoader.h"
|
||||
#include "VertexLoader.h"
|
||||
#include "Statistics.h"
|
||||
#include "DebugUtil.h"
|
||||
#include "CommandProcessor.h"
|
||||
|
||||
typedef void (*DecodingFunction)(u32);
|
||||
DecodingFunction currentFunction = NULL;
|
||||
|
||||
u32 minCommandSize;
|
||||
u16 streamSize;
|
||||
u16 streamAddress;
|
||||
bool readOpcode;
|
||||
VertexLoader vertexLoader;
|
||||
bool inObjectStream;
|
||||
u8 lastPrimCmd;
|
||||
|
||||
|
||||
namespace OpcodeDecoder
|
||||
{
|
||||
|
||||
void DecodePrimitiveStream(u32 iBufferSize)
|
||||
{
|
||||
u32 vertexSize = vertexLoader.GetVertexSize();
|
||||
|
||||
if(g_bSkipCurrentFrame)
|
||||
{
|
||||
while (streamSize > 0 && iBufferSize >= vertexSize)
|
||||
{
|
||||
g_pVideoData += vertexSize;
|
||||
iBufferSize -= vertexSize;
|
||||
streamSize--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (streamSize > 0 && iBufferSize >= vertexSize)
|
||||
{
|
||||
vertexLoader.LoadVertex();
|
||||
iBufferSize -= vertexSize;
|
||||
streamSize--;
|
||||
}
|
||||
}
|
||||
|
||||
if (streamSize == 0)
|
||||
{
|
||||
// return to normal command processing
|
||||
ResetDecoding();
|
||||
}
|
||||
}
|
||||
|
||||
void ReadXFData(u32 iBufferSize)
|
||||
{
|
||||
_assert_msg_(VIDEO, iBufferSize >= (u32)(streamSize * 4), "Underflow during standard opcode decoding");
|
||||
|
||||
u32 pData[16];
|
||||
for (int i = 0; i < streamSize; i++)
|
||||
pData[i] = DataReadU32();
|
||||
LoadXFReg(streamSize, streamAddress, pData);
|
||||
|
||||
// return to normal command processing
|
||||
ResetDecoding();
|
||||
}
|
||||
|
||||
void ExecuteDisplayList(u32 addr, u32 count)
|
||||
{
|
||||
u8 *videoDataSave = g_pVideoData;
|
||||
|
||||
u8 *dlStart = g_VideoInitialize.pGetMemoryPointer(addr);
|
||||
|
||||
g_pVideoData = dlStart;
|
||||
|
||||
while (OpcodeDecoder::CommandRunnable(count))
|
||||
{
|
||||
OpcodeDecoder::Run(count);
|
||||
|
||||
// if data was read by the opcode decoder then the video data pointer changed
|
||||
u32 readCount = g_pVideoData - dlStart;
|
||||
dlStart = g_pVideoData;
|
||||
|
||||
_assert_msg_(VIDEO, count >= readCount, "Display list underrun");
|
||||
|
||||
count -= readCount;
|
||||
}
|
||||
|
||||
g_pVideoData = videoDataSave;
|
||||
}
|
||||
|
||||
void DecodeStandard(u32 bufferSize)
|
||||
{
|
||||
_assert_msg_(VIDEO, CommandRunnable(bufferSize), "Underflow during standard opcode decoding");
|
||||
|
||||
int Cmd = DataReadU8();
|
||||
|
||||
if (Cmd == GX_NOP)
|
||||
return;
|
||||
|
||||
// check if switching in or out of an object
|
||||
// only used for debuggging
|
||||
if (inObjectStream && (Cmd & 0x87) != lastPrimCmd)
|
||||
{
|
||||
inObjectStream = false;
|
||||
DebugUtil::OnObjectEnd();
|
||||
}
|
||||
if (Cmd & 0x80 && !inObjectStream)
|
||||
{
|
||||
inObjectStream = true;
|
||||
lastPrimCmd = Cmd & 0x87;
|
||||
DebugUtil::OnObjectBegin();
|
||||
}
|
||||
|
||||
switch(Cmd)
|
||||
{
|
||||
case GX_NOP:
|
||||
break;
|
||||
|
||||
case GX_LOAD_CP_REG: //0x08
|
||||
{
|
||||
u32 SubCmd = DataReadU8();
|
||||
u32 Value = DataReadU32();
|
||||
LoadCPReg(SubCmd, Value);
|
||||
}
|
||||
break;
|
||||
|
||||
case GX_LOAD_XF_REG:
|
||||
{
|
||||
u32 Cmd2 = DataReadU32();
|
||||
streamSize = ((Cmd2 >> 16) & 15) + 1;
|
||||
streamAddress = Cmd2 & 0xFFFF;
|
||||
currentFunction = ReadXFData;
|
||||
minCommandSize = streamSize * 4;
|
||||
readOpcode = false;
|
||||
}
|
||||
break;
|
||||
|
||||
case GX_LOAD_INDX_A: //used for position matrices
|
||||
LoadIndexedXF(DataReadU32(), 0xC);
|
||||
break;
|
||||
case GX_LOAD_INDX_B: //used for normal matrices
|
||||
LoadIndexedXF(DataReadU32(), 0xD);
|
||||
break;
|
||||
case GX_LOAD_INDX_C: //used for postmatrices
|
||||
LoadIndexedXF(DataReadU32(), 0xE);
|
||||
break;
|
||||
case GX_LOAD_INDX_D: //used for lights
|
||||
LoadIndexedXF(DataReadU32(), 0xF);
|
||||
break;
|
||||
|
||||
case GX_CMD_CALL_DL:
|
||||
{
|
||||
u32 dwAddr = DataReadU32();
|
||||
u32 dwCount = DataReadU32();
|
||||
ExecuteDisplayList(dwAddr, dwCount);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x44:
|
||||
// zelda 4 swords calls it and checks the metrics registers after that
|
||||
break;
|
||||
|
||||
case GX_CMD_INVL_VC:// Invalidate (vertex cache?)
|
||||
DEBUG_LOG(VIDEO, "Invalidate (vertex cache?)");
|
||||
break;
|
||||
|
||||
case GX_LOAD_BP_REG: //0x61
|
||||
{
|
||||
u32 cmd = DataReadU32();
|
||||
LoadBPReg(cmd);
|
||||
}
|
||||
break;
|
||||
|
||||
// draw primitives
|
||||
default:
|
||||
if (Cmd & 0x80)
|
||||
{
|
||||
u8 vatIndex = Cmd & GX_VAT_MASK;
|
||||
u8 primitiveType = (Cmd & GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT;
|
||||
vertexLoader.SetFormat(vatIndex, primitiveType);
|
||||
|
||||
// switch to primitive processing
|
||||
streamSize = DataReadU16();
|
||||
currentFunction = DecodePrimitiveStream;
|
||||
minCommandSize = vertexLoader.GetVertexSize();
|
||||
readOpcode = false;
|
||||
|
||||
INCSTAT(stats.thisFrame.numPrimatives);
|
||||
DEBUG_LOG(VIDEO, "Draw begin");
|
||||
}
|
||||
else
|
||||
{
|
||||
PanicAlert("GFX: Unknown Opcode (0x%x).\n", Cmd);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Init()
|
||||
{
|
||||
inObjectStream = false;
|
||||
lastPrimCmd = 0;
|
||||
ResetDecoding();
|
||||
}
|
||||
|
||||
void ResetDecoding()
|
||||
{
|
||||
currentFunction = DecodeStandard;
|
||||
minCommandSize = 1;
|
||||
readOpcode = true;
|
||||
}
|
||||
|
||||
bool CommandRunnable(u32 iBufferSize)
|
||||
{
|
||||
if (iBufferSize < minCommandSize)
|
||||
return false;
|
||||
|
||||
if (readOpcode)
|
||||
{
|
||||
u8 Cmd = DataPeek8(0);
|
||||
u32 minSize = 1;
|
||||
|
||||
switch(Cmd)
|
||||
{
|
||||
case GX_LOAD_CP_REG: //0x08
|
||||
minSize = 6;
|
||||
break;
|
||||
|
||||
case GX_LOAD_XF_REG:
|
||||
minSize = 5;
|
||||
break;
|
||||
|
||||
case GX_LOAD_INDX_A: //used for position matrices
|
||||
minSize = 5;
|
||||
break;
|
||||
case GX_LOAD_INDX_B: //used for normal matrices
|
||||
minSize = 5;
|
||||
break;
|
||||
case GX_LOAD_INDX_C: //used for postmatrices
|
||||
minSize = 5;
|
||||
break;
|
||||
case GX_LOAD_INDX_D: //used for lights
|
||||
minSize = 5;
|
||||
break;
|
||||
|
||||
case GX_CMD_CALL_DL:
|
||||
minSize = 9;
|
||||
break;
|
||||
|
||||
case GX_LOAD_BP_REG: //0x61
|
||||
minSize = 5;
|
||||
break;
|
||||
|
||||
// draw primitives
|
||||
default:
|
||||
if (Cmd & 0x80)
|
||||
minSize = 3;
|
||||
break;
|
||||
}
|
||||
|
||||
return (iBufferSize >= minSize);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Run(u32 iBufferSize)
|
||||
{
|
||||
currentFunction(iBufferSize);
|
||||
}
|
||||
|
||||
}
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
#include "../../../Core/VideoCommon/Src/DataReader.h"
|
||||
|
||||
#include "main.h"
|
||||
#include "OpcodeDecoder.h"
|
||||
#include "BPMemLoader.h"
|
||||
#include "CPMemLoader.h"
|
||||
#include "XFMemLoader.h"
|
||||
#include "VertexLoader.h"
|
||||
#include "Statistics.h"
|
||||
#include "DebugUtil.h"
|
||||
#include "CommandProcessor.h"
|
||||
|
||||
typedef void (*DecodingFunction)(u32);
|
||||
DecodingFunction currentFunction = NULL;
|
||||
|
||||
u32 minCommandSize;
|
||||
u16 streamSize;
|
||||
u16 streamAddress;
|
||||
bool readOpcode;
|
||||
VertexLoader vertexLoader;
|
||||
bool inObjectStream;
|
||||
u8 lastPrimCmd;
|
||||
|
||||
|
||||
namespace OpcodeDecoder
|
||||
{
|
||||
|
||||
void DecodePrimitiveStream(u32 iBufferSize)
|
||||
{
|
||||
u32 vertexSize = vertexLoader.GetVertexSize();
|
||||
|
||||
if(g_bSkipCurrentFrame)
|
||||
{
|
||||
while (streamSize > 0 && iBufferSize >= vertexSize)
|
||||
{
|
||||
g_pVideoData += vertexSize;
|
||||
iBufferSize -= vertexSize;
|
||||
streamSize--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (streamSize > 0 && iBufferSize >= vertexSize)
|
||||
{
|
||||
vertexLoader.LoadVertex();
|
||||
iBufferSize -= vertexSize;
|
||||
streamSize--;
|
||||
}
|
||||
}
|
||||
|
||||
if (streamSize == 0)
|
||||
{
|
||||
// return to normal command processing
|
||||
ResetDecoding();
|
||||
}
|
||||
}
|
||||
|
||||
void ReadXFData(u32 iBufferSize)
|
||||
{
|
||||
_assert_msg_(VIDEO, iBufferSize >= (u32)(streamSize * 4), "Underflow during standard opcode decoding");
|
||||
|
||||
u32 pData[16];
|
||||
for (int i = 0; i < streamSize; i++)
|
||||
pData[i] = DataReadU32();
|
||||
LoadXFReg(streamSize, streamAddress, pData);
|
||||
|
||||
// return to normal command processing
|
||||
ResetDecoding();
|
||||
}
|
||||
|
||||
void ExecuteDisplayList(u32 addr, u32 count)
|
||||
{
|
||||
u8 *videoDataSave = g_pVideoData;
|
||||
|
||||
u8 *dlStart = g_VideoInitialize.pGetMemoryPointer(addr);
|
||||
|
||||
g_pVideoData = dlStart;
|
||||
|
||||
while (OpcodeDecoder::CommandRunnable(count))
|
||||
{
|
||||
OpcodeDecoder::Run(count);
|
||||
|
||||
// if data was read by the opcode decoder then the video data pointer changed
|
||||
u32 readCount = g_pVideoData - dlStart;
|
||||
dlStart = g_pVideoData;
|
||||
|
||||
_assert_msg_(VIDEO, count >= readCount, "Display list underrun");
|
||||
|
||||
count -= readCount;
|
||||
}
|
||||
|
||||
g_pVideoData = videoDataSave;
|
||||
}
|
||||
|
||||
void DecodeStandard(u32 bufferSize)
|
||||
{
|
||||
_assert_msg_(VIDEO, CommandRunnable(bufferSize), "Underflow during standard opcode decoding");
|
||||
|
||||
int Cmd = DataReadU8();
|
||||
|
||||
if (Cmd == GX_NOP)
|
||||
return;
|
||||
|
||||
// check if switching in or out of an object
|
||||
// only used for debuggging
|
||||
if (inObjectStream && (Cmd & 0x87) != lastPrimCmd)
|
||||
{
|
||||
inObjectStream = false;
|
||||
DebugUtil::OnObjectEnd();
|
||||
}
|
||||
if (Cmd & 0x80 && !inObjectStream)
|
||||
{
|
||||
inObjectStream = true;
|
||||
lastPrimCmd = Cmd & 0x87;
|
||||
DebugUtil::OnObjectBegin();
|
||||
}
|
||||
|
||||
switch(Cmd)
|
||||
{
|
||||
case GX_NOP:
|
||||
break;
|
||||
|
||||
case GX_LOAD_CP_REG: //0x08
|
||||
{
|
||||
u32 SubCmd = DataReadU8();
|
||||
u32 Value = DataReadU32();
|
||||
LoadCPReg(SubCmd, Value);
|
||||
}
|
||||
break;
|
||||
|
||||
case GX_LOAD_XF_REG:
|
||||
{
|
||||
u32 Cmd2 = DataReadU32();
|
||||
streamSize = ((Cmd2 >> 16) & 15) + 1;
|
||||
streamAddress = Cmd2 & 0xFFFF;
|
||||
currentFunction = ReadXFData;
|
||||
minCommandSize = streamSize * 4;
|
||||
readOpcode = false;
|
||||
}
|
||||
break;
|
||||
|
||||
case GX_LOAD_INDX_A: //used for position matrices
|
||||
LoadIndexedXF(DataReadU32(), 0xC);
|
||||
break;
|
||||
case GX_LOAD_INDX_B: //used for normal matrices
|
||||
LoadIndexedXF(DataReadU32(), 0xD);
|
||||
break;
|
||||
case GX_LOAD_INDX_C: //used for postmatrices
|
||||
LoadIndexedXF(DataReadU32(), 0xE);
|
||||
break;
|
||||
case GX_LOAD_INDX_D: //used for lights
|
||||
LoadIndexedXF(DataReadU32(), 0xF);
|
||||
break;
|
||||
|
||||
case GX_CMD_CALL_DL:
|
||||
{
|
||||
u32 dwAddr = DataReadU32();
|
||||
u32 dwCount = DataReadU32();
|
||||
ExecuteDisplayList(dwAddr, dwCount);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x44:
|
||||
// zelda 4 swords calls it and checks the metrics registers after that
|
||||
break;
|
||||
|
||||
case GX_CMD_INVL_VC:// Invalidate (vertex cache?)
|
||||
DEBUG_LOG(VIDEO, "Invalidate (vertex cache?)");
|
||||
break;
|
||||
|
||||
case GX_LOAD_BP_REG: //0x61
|
||||
{
|
||||
u32 cmd = DataReadU32();
|
||||
LoadBPReg(cmd);
|
||||
}
|
||||
break;
|
||||
|
||||
// draw primitives
|
||||
default:
|
||||
if (Cmd & 0x80)
|
||||
{
|
||||
u8 vatIndex = Cmd & GX_VAT_MASK;
|
||||
u8 primitiveType = (Cmd & GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT;
|
||||
vertexLoader.SetFormat(vatIndex, primitiveType);
|
||||
|
||||
// switch to primitive processing
|
||||
streamSize = DataReadU16();
|
||||
currentFunction = DecodePrimitiveStream;
|
||||
minCommandSize = vertexLoader.GetVertexSize();
|
||||
readOpcode = false;
|
||||
|
||||
INCSTAT(stats.thisFrame.numPrimatives);
|
||||
DEBUG_LOG(VIDEO, "Draw begin");
|
||||
}
|
||||
else
|
||||
{
|
||||
PanicAlert("GFX: Unknown Opcode (0x%x).\n", Cmd);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Init()
|
||||
{
|
||||
inObjectStream = false;
|
||||
lastPrimCmd = 0;
|
||||
ResetDecoding();
|
||||
}
|
||||
|
||||
void ResetDecoding()
|
||||
{
|
||||
currentFunction = DecodeStandard;
|
||||
minCommandSize = 1;
|
||||
readOpcode = true;
|
||||
}
|
||||
|
||||
bool CommandRunnable(u32 iBufferSize)
|
||||
{
|
||||
if (iBufferSize < minCommandSize)
|
||||
return false;
|
||||
|
||||
if (readOpcode)
|
||||
{
|
||||
u8 Cmd = DataPeek8(0);
|
||||
u32 minSize = 1;
|
||||
|
||||
switch(Cmd)
|
||||
{
|
||||
case GX_LOAD_CP_REG: //0x08
|
||||
minSize = 6;
|
||||
break;
|
||||
|
||||
case GX_LOAD_XF_REG:
|
||||
minSize = 5;
|
||||
break;
|
||||
|
||||
case GX_LOAD_INDX_A: //used for position matrices
|
||||
minSize = 5;
|
||||
break;
|
||||
case GX_LOAD_INDX_B: //used for normal matrices
|
||||
minSize = 5;
|
||||
break;
|
||||
case GX_LOAD_INDX_C: //used for postmatrices
|
||||
minSize = 5;
|
||||
break;
|
||||
case GX_LOAD_INDX_D: //used for lights
|
||||
minSize = 5;
|
||||
break;
|
||||
|
||||
case GX_CMD_CALL_DL:
|
||||
minSize = 9;
|
||||
break;
|
||||
|
||||
case GX_LOAD_BP_REG: //0x61
|
||||
minSize = 5;
|
||||
break;
|
||||
|
||||
// draw primitives
|
||||
default:
|
||||
if (Cmd & 0x80)
|
||||
minSize = 3;
|
||||
break;
|
||||
}
|
||||
|
||||
return (iBufferSize >= minSize);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Run(u32 iBufferSize)
|
||||
{
|
||||
currentFunction(iBufferSize);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,62 +1,62 @@
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
|
||||
#ifndef _OPCODEDECODER_H_
|
||||
#define _OPCODEDECODER_H_
|
||||
|
||||
#include "pluginspecs_video.h"
|
||||
|
||||
namespace OpcodeDecoder
|
||||
{
|
||||
|
||||
#define GX_NOP 0x00
|
||||
|
||||
#define GX_LOAD_BP_REG 0x61
|
||||
#define GX_LOAD_CP_REG 0x08
|
||||
#define GX_LOAD_XF_REG 0x10
|
||||
#define GX_LOAD_INDX_A 0x20
|
||||
#define GX_LOAD_INDX_B 0x28
|
||||
#define GX_LOAD_INDX_C 0x30
|
||||
#define GX_LOAD_INDX_D 0x38
|
||||
|
||||
#define GX_CMD_CALL_DL 0x40
|
||||
#define GX_CMD_INVL_VC 0x48
|
||||
|
||||
#define GX_PRIMITIVE_MASK 0x78
|
||||
#define GX_PRIMITIVE_SHIFT 3
|
||||
#define GX_VAT_MASK 0x07
|
||||
|
||||
//these are defined 1/8th of their real values and without their top bit
|
||||
#define GX_DRAW_QUADS 0x0 //0x80
|
||||
#define GX_DRAW_TRIANGLES 0x2 //0x90
|
||||
#define GX_DRAW_TRIANGLE_STRIP 0x3 //0x98
|
||||
#define GX_DRAW_TRIANGLE_FAN 0x4 //0xA0
|
||||
#define GX_DRAW_LINES 0x5 //0xA8
|
||||
#define GX_DRAW_LINE_STRIP 0x6 //0xB0
|
||||
#define GX_DRAW_POINTS 0x7 //0xB8
|
||||
|
||||
void Init();
|
||||
|
||||
void ResetDecoding();
|
||||
|
||||
bool CommandRunnable(u32 iBufferSize);
|
||||
|
||||
void Run(u32 iBufferSize);
|
||||
}
|
||||
|
||||
#endif
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
|
||||
#ifndef _OPCODEDECODER_H_
|
||||
#define _OPCODEDECODER_H_
|
||||
|
||||
#include "pluginspecs_video.h"
|
||||
|
||||
namespace OpcodeDecoder
|
||||
{
|
||||
|
||||
#define GX_NOP 0x00
|
||||
|
||||
#define GX_LOAD_BP_REG 0x61
|
||||
#define GX_LOAD_CP_REG 0x08
|
||||
#define GX_LOAD_XF_REG 0x10
|
||||
#define GX_LOAD_INDX_A 0x20
|
||||
#define GX_LOAD_INDX_B 0x28
|
||||
#define GX_LOAD_INDX_C 0x30
|
||||
#define GX_LOAD_INDX_D 0x38
|
||||
|
||||
#define GX_CMD_CALL_DL 0x40
|
||||
#define GX_CMD_INVL_VC 0x48
|
||||
|
||||
#define GX_PRIMITIVE_MASK 0x78
|
||||
#define GX_PRIMITIVE_SHIFT 3
|
||||
#define GX_VAT_MASK 0x07
|
||||
|
||||
//these are defined 1/8th of their real values and without their top bit
|
||||
#define GX_DRAW_QUADS 0x0 //0x80
|
||||
#define GX_DRAW_TRIANGLES 0x2 //0x90
|
||||
#define GX_DRAW_TRIANGLE_STRIP 0x3 //0x98
|
||||
#define GX_DRAW_TRIANGLE_FAN 0x4 //0xA0
|
||||
#define GX_DRAW_LINES 0x5 //0xA8
|
||||
#define GX_DRAW_LINE_STRIP 0x6 //0xB0
|
||||
#define GX_DRAW_POINTS 0x7 //0xB8
|
||||
|
||||
void Init();
|
||||
|
||||
void ResetDecoding();
|
||||
|
||||
bool CommandRunnable(u32 iBufferSize);
|
||||
|
||||
void Run(u32 iBufferSize);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,171 +1,171 @@
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
|
||||
// http://developer.nvidia.com/object/General_FAQ.html#t6 !!!!!
|
||||
|
||||
|
||||
|
||||
#include "Common.h"
|
||||
#include "ChunkFile.h"
|
||||
|
||||
#include "PixelEngine.h"
|
||||
#include "CommandProcessor.h"
|
||||
|
||||
|
||||
namespace PixelEngine
|
||||
{
|
||||
|
||||
enum
|
||||
{
|
||||
INT_CAUSE_PE_TOKEN = 0x200, // GP Token
|
||||
INT_CAUSE_PE_FINISH = 0x400, // GP Finished
|
||||
};
|
||||
|
||||
// STATE_TO_SAVE
|
||||
PEReg pereg;
|
||||
|
||||
static bool g_bSignalTokenInterrupt;
|
||||
static bool g_bSignalFinishInterrupt;
|
||||
|
||||
static int et_SetTokenOnMainThread;
|
||||
static int et_SetFinishOnMainThread;
|
||||
|
||||
void DoState(PointerWrap &p)
|
||||
{
|
||||
p.Do(pereg);
|
||||
p.Do(g_bSignalTokenInterrupt);
|
||||
p.Do(g_bSignalFinishInterrupt);
|
||||
}
|
||||
|
||||
void UpdateInterrupts();
|
||||
|
||||
void SetToken_OnMainThread(u64 userdata, int cyclesLate);
|
||||
void SetFinish_OnMainThread(u64 userdata, int cyclesLate);
|
||||
|
||||
void Init()
|
||||
{
|
||||
memset(&pereg, 0, sizeof(pereg));
|
||||
|
||||
et_SetTokenOnMainThread = false;
|
||||
g_bSignalFinishInterrupt = false;
|
||||
|
||||
et_SetTokenOnMainThread = g_VideoInitialize.pRegisterEvent("SetToken", SetToken_OnMainThread);
|
||||
et_SetFinishOnMainThread = g_VideoInitialize.pRegisterEvent("SetFinish", SetFinish_OnMainThread);
|
||||
}
|
||||
|
||||
void Read16(u16& _uReturnValue, const u32 _iAddress)
|
||||
{
|
||||
DEBUG_LOG(PIXELENGINE, "(r16): 0x%08x", _iAddress);
|
||||
|
||||
u16 address = _iAddress & 0xFFF;
|
||||
|
||||
if (address <= 0x16)
|
||||
_uReturnValue = ((u16*)&pereg)[address >> 1];
|
||||
}
|
||||
|
||||
void Write32(const u32 _iValue, const u32 _iAddress)
|
||||
{
|
||||
WARN_LOG(PIXELENGINE, "(w32): 0x%08x @ 0x%08x",_iValue,_iAddress);
|
||||
}
|
||||
|
||||
void Write16(const u16 _iValue, const u32 _iAddress)
|
||||
{
|
||||
u16 address = _iAddress & 0xFFF;
|
||||
|
||||
switch (address)
|
||||
{
|
||||
case PE_CTRL_REGISTER:
|
||||
{
|
||||
UPECtrlReg tmpCtrl(_iValue);
|
||||
|
||||
if (tmpCtrl.PEToken) g_bSignalTokenInterrupt = false;
|
||||
if (tmpCtrl.PEFinish) g_bSignalFinishInterrupt = false;
|
||||
|
||||
pereg.ctrl.PETokenEnable = tmpCtrl.PETokenEnable;
|
||||
pereg.ctrl.PEFinishEnable = tmpCtrl.PEFinishEnable;
|
||||
pereg.ctrl.PEToken = 0; // this flag is write only
|
||||
pereg.ctrl.PEFinish = 0; // this flag is write only
|
||||
|
||||
DEBUG_LOG(PIXELENGINE, "(w16): PE_CTRL_REGISTER: 0x%04x", _iValue);
|
||||
UpdateInterrupts();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (address <= 0x16)
|
||||
((u16*)&pereg)[address >> 1] = _iValue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool AllowIdleSkipping()
|
||||
{
|
||||
return !g_VideoInitialize.bOnThread || (!pereg.ctrl.PETokenEnable && !pereg.ctrl.PEFinishEnable);
|
||||
}
|
||||
|
||||
void UpdateInterrupts()
|
||||
{
|
||||
// check if there is a token-interrupt
|
||||
if (g_bSignalTokenInterrupt & pereg.ctrl.PETokenEnable)
|
||||
g_VideoInitialize.pSetInterrupt(INT_CAUSE_PE_TOKEN, true);
|
||||
else
|
||||
g_VideoInitialize.pSetInterrupt(INT_CAUSE_PE_TOKEN, false);
|
||||
|
||||
// check if there is a finish-interrupt
|
||||
if (g_bSignalFinishInterrupt & pereg.ctrl.PEFinishEnable)
|
||||
g_VideoInitialize.pSetInterrupt(INT_CAUSE_PE_FINISH, true);
|
||||
else
|
||||
g_VideoInitialize.pSetInterrupt(INT_CAUSE_PE_FINISH, false);
|
||||
}
|
||||
|
||||
|
||||
// Called only if BPMEM_PE_TOKEN_INT_ID is ack by GP
|
||||
void SetToken_OnMainThread(u64 userdata, int cyclesLate)
|
||||
{
|
||||
g_bSignalTokenInterrupt = true;
|
||||
INFO_LOG(PIXELENGINE, "VIDEO Plugin raises INT_CAUSE_PE_TOKEN (btw, token: %04x)", pereg.token);
|
||||
UpdateInterrupts();
|
||||
}
|
||||
|
||||
void SetFinish_OnMainThread(u64 userdata, int cyclesLate)
|
||||
{
|
||||
g_bSignalFinishInterrupt = true;
|
||||
UpdateInterrupts();
|
||||
}
|
||||
|
||||
// SetToken
|
||||
// THIS IS EXECUTED FROM VIDEO THREAD
|
||||
void SetToken(const u16 _token, const int _bSetTokenAcknowledge)
|
||||
{
|
||||
pereg.token = _token;
|
||||
if (_bSetTokenAcknowledge) // set token INT
|
||||
{
|
||||
g_VideoInitialize.pScheduleEvent_Threadsafe(
|
||||
0, et_SetTokenOnMainThread, _token | (_bSetTokenAcknowledge << 16));
|
||||
}
|
||||
}
|
||||
|
||||
// SetFinish
|
||||
// THIS IS EXECUTED FROM VIDEO THREAD
|
||||
void SetFinish()
|
||||
{
|
||||
g_VideoInitialize.pScheduleEvent_Threadsafe(
|
||||
0, et_SetFinishOnMainThread, 0);
|
||||
INFO_LOG(PIXELENGINE, "VIDEO Set Finish");
|
||||
}
|
||||
|
||||
} // end of namespace PixelEngine
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
|
||||
// http://developer.nvidia.com/object/General_FAQ.html#t6 !!!!!
|
||||
|
||||
|
||||
|
||||
#include "Common.h"
|
||||
#include "ChunkFile.h"
|
||||
|
||||
#include "PixelEngine.h"
|
||||
#include "CommandProcessor.h"
|
||||
|
||||
|
||||
namespace PixelEngine
|
||||
{
|
||||
|
||||
enum
|
||||
{
|
||||
INT_CAUSE_PE_TOKEN = 0x200, // GP Token
|
||||
INT_CAUSE_PE_FINISH = 0x400, // GP Finished
|
||||
};
|
||||
|
||||
// STATE_TO_SAVE
|
||||
PEReg pereg;
|
||||
|
||||
static bool g_bSignalTokenInterrupt;
|
||||
static bool g_bSignalFinishInterrupt;
|
||||
|
||||
static int et_SetTokenOnMainThread;
|
||||
static int et_SetFinishOnMainThread;
|
||||
|
||||
void DoState(PointerWrap &p)
|
||||
{
|
||||
p.Do(pereg);
|
||||
p.Do(g_bSignalTokenInterrupt);
|
||||
p.Do(g_bSignalFinishInterrupt);
|
||||
}
|
||||
|
||||
void UpdateInterrupts();
|
||||
|
||||
void SetToken_OnMainThread(u64 userdata, int cyclesLate);
|
||||
void SetFinish_OnMainThread(u64 userdata, int cyclesLate);
|
||||
|
||||
void Init()
|
||||
{
|
||||
memset(&pereg, 0, sizeof(pereg));
|
||||
|
||||
et_SetTokenOnMainThread = false;
|
||||
g_bSignalFinishInterrupt = false;
|
||||
|
||||
et_SetTokenOnMainThread = g_VideoInitialize.pRegisterEvent("SetToken", SetToken_OnMainThread);
|
||||
et_SetFinishOnMainThread = g_VideoInitialize.pRegisterEvent("SetFinish", SetFinish_OnMainThread);
|
||||
}
|
||||
|
||||
void Read16(u16& _uReturnValue, const u32 _iAddress)
|
||||
{
|
||||
DEBUG_LOG(PIXELENGINE, "(r16): 0x%08x", _iAddress);
|
||||
|
||||
u16 address = _iAddress & 0xFFF;
|
||||
|
||||
if (address <= 0x16)
|
||||
_uReturnValue = ((u16*)&pereg)[address >> 1];
|
||||
}
|
||||
|
||||
void Write32(const u32 _iValue, const u32 _iAddress)
|
||||
{
|
||||
WARN_LOG(PIXELENGINE, "(w32): 0x%08x @ 0x%08x",_iValue,_iAddress);
|
||||
}
|
||||
|
||||
void Write16(const u16 _iValue, const u32 _iAddress)
|
||||
{
|
||||
u16 address = _iAddress & 0xFFF;
|
||||
|
||||
switch (address)
|
||||
{
|
||||
case PE_CTRL_REGISTER:
|
||||
{
|
||||
UPECtrlReg tmpCtrl(_iValue);
|
||||
|
||||
if (tmpCtrl.PEToken) g_bSignalTokenInterrupt = false;
|
||||
if (tmpCtrl.PEFinish) g_bSignalFinishInterrupt = false;
|
||||
|
||||
pereg.ctrl.PETokenEnable = tmpCtrl.PETokenEnable;
|
||||
pereg.ctrl.PEFinishEnable = tmpCtrl.PEFinishEnable;
|
||||
pereg.ctrl.PEToken = 0; // this flag is write only
|
||||
pereg.ctrl.PEFinish = 0; // this flag is write only
|
||||
|
||||
DEBUG_LOG(PIXELENGINE, "(w16): PE_CTRL_REGISTER: 0x%04x", _iValue);
|
||||
UpdateInterrupts();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (address <= 0x16)
|
||||
((u16*)&pereg)[address >> 1] = _iValue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool AllowIdleSkipping()
|
||||
{
|
||||
return !g_VideoInitialize.bOnThread || (!pereg.ctrl.PETokenEnable && !pereg.ctrl.PEFinishEnable);
|
||||
}
|
||||
|
||||
void UpdateInterrupts()
|
||||
{
|
||||
// check if there is a token-interrupt
|
||||
if (g_bSignalTokenInterrupt & pereg.ctrl.PETokenEnable)
|
||||
g_VideoInitialize.pSetInterrupt(INT_CAUSE_PE_TOKEN, true);
|
||||
else
|
||||
g_VideoInitialize.pSetInterrupt(INT_CAUSE_PE_TOKEN, false);
|
||||
|
||||
// check if there is a finish-interrupt
|
||||
if (g_bSignalFinishInterrupt & pereg.ctrl.PEFinishEnable)
|
||||
g_VideoInitialize.pSetInterrupt(INT_CAUSE_PE_FINISH, true);
|
||||
else
|
||||
g_VideoInitialize.pSetInterrupt(INT_CAUSE_PE_FINISH, false);
|
||||
}
|
||||
|
||||
|
||||
// Called only if BPMEM_PE_TOKEN_INT_ID is ack by GP
|
||||
void SetToken_OnMainThread(u64 userdata, int cyclesLate)
|
||||
{
|
||||
g_bSignalTokenInterrupt = true;
|
||||
INFO_LOG(PIXELENGINE, "VIDEO Plugin raises INT_CAUSE_PE_TOKEN (btw, token: %04x)", pereg.token);
|
||||
UpdateInterrupts();
|
||||
}
|
||||
|
||||
void SetFinish_OnMainThread(u64 userdata, int cyclesLate)
|
||||
{
|
||||
g_bSignalFinishInterrupt = true;
|
||||
UpdateInterrupts();
|
||||
}
|
||||
|
||||
// SetToken
|
||||
// THIS IS EXECUTED FROM VIDEO THREAD
|
||||
void SetToken(const u16 _token, const int _bSetTokenAcknowledge)
|
||||
{
|
||||
pereg.token = _token;
|
||||
if (_bSetTokenAcknowledge) // set token INT
|
||||
{
|
||||
g_VideoInitialize.pScheduleEvent_Threadsafe(
|
||||
0, et_SetTokenOnMainThread, _token | (_bSetTokenAcknowledge << 16));
|
||||
}
|
||||
}
|
||||
|
||||
// SetFinish
|
||||
// THIS IS EXECUTED FROM VIDEO THREAD
|
||||
void SetFinish()
|
||||
{
|
||||
g_VideoInitialize.pScheduleEvent_Threadsafe(
|
||||
0, et_SetFinishOnMainThread, 0);
|
||||
INFO_LOG(PIXELENGINE, "VIDEO Set Finish");
|
||||
}
|
||||
|
||||
} // end of namespace PixelEngine
|
||||
|
@ -1,155 +1,155 @@
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
#ifndef _PIXELENGINE_H
|
||||
#define _PIXELENGINE_H
|
||||
|
||||
#include "Common.h"
|
||||
#include "pluginspecs_video.h"
|
||||
#include "VideoCommon.h"
|
||||
class PointerWrap;
|
||||
|
||||
namespace PixelEngine
|
||||
{
|
||||
// internal hardware addresses
|
||||
enum
|
||||
{
|
||||
PE_ZCONF = 0x000, // Z Config
|
||||
PE_ALPHACONF = 0x002, // Alpha Config
|
||||
PE_DSTALPHACONF = 0x004, // Destination Alpha Config
|
||||
PE_ALPHAMODE = 0x006, // Alpha Mode Config
|
||||
PE_ALPHAREAD = 0x008, // Alpha Read
|
||||
PE_CTRL_REGISTER = 0x00a, // Control
|
||||
PE_TOKEN_REG = 0x00e, // Token
|
||||
PE_BBOX_LEFT = 0x010, // Flip Left
|
||||
PE_BBOX_RIGHT = 0x012, // Flip Right
|
||||
PE_BBOX_TOP = 0x014, // Flip Top
|
||||
PE_BBOX_BOTTOM = 0x016, // Flip Bottom
|
||||
};
|
||||
|
||||
union UPEZConfReg
|
||||
{
|
||||
u16 Hex;
|
||||
struct
|
||||
{
|
||||
u16 ZCompEnable : 1; // Z Comparator Enable
|
||||
u16 Function : 3;
|
||||
u16 ZUpdEnable : 1;
|
||||
u16 : 11;
|
||||
};
|
||||
};
|
||||
|
||||
union UPEAlphaConfReg
|
||||
{
|
||||
u16 Hex;
|
||||
struct
|
||||
{
|
||||
u16 BMMath : 1; // GX_BM_BLEND || GX_BM_SUBSTRACT
|
||||
u16 BMLogic : 1; // GX_BM_LOGIC
|
||||
u16 Dither : 1;
|
||||
u16 ColorUpdEnable : 1;
|
||||
u16 AlphaUpdEnable : 1;
|
||||
u16 DstFactor : 3;
|
||||
u16 SrcFactor : 3;
|
||||
u16 Substract : 1; // Additive mode by default
|
||||
u16 BlendOperator : 4;
|
||||
};
|
||||
};
|
||||
|
||||
union UPEDstAlphaConfReg
|
||||
{
|
||||
u16 Hex;
|
||||
struct
|
||||
{
|
||||
u16 DstAlpha : 8;
|
||||
u16 Enable : 1;
|
||||
u16 : 7;
|
||||
};
|
||||
};
|
||||
|
||||
union UPEAlphaModeConfReg
|
||||
{
|
||||
u16 Hex;
|
||||
struct
|
||||
{
|
||||
u16 Threshold : 8;
|
||||
u16 CompareMode : 8;
|
||||
};
|
||||
};
|
||||
|
||||
union UPEAlphaReadReg
|
||||
{
|
||||
u16 Hex;
|
||||
struct
|
||||
{
|
||||
u16 ReadMode : 3;
|
||||
u16 : 13;
|
||||
};
|
||||
};
|
||||
|
||||
union UPECtrlReg
|
||||
{
|
||||
struct
|
||||
{
|
||||
u16 PETokenEnable : 1;
|
||||
u16 PEFinishEnable : 1;
|
||||
u16 PEToken : 1; // write only
|
||||
u16 PEFinish : 1; // write only
|
||||
u16 : 12;
|
||||
};
|
||||
u16 Hex;
|
||||
UPECtrlReg() {Hex = 0; }
|
||||
UPECtrlReg(u16 _hex) {Hex = _hex; }
|
||||
};
|
||||
|
||||
struct PEReg
|
||||
{
|
||||
UPEZConfReg zconf;
|
||||
UPEAlphaConfReg alphaConf;
|
||||
UPEDstAlphaConfReg dstAlpha;
|
||||
UPEAlphaModeConfReg alphaMode;
|
||||
UPEAlphaReadReg alphaRead;
|
||||
UPECtrlReg ctrl;
|
||||
u16 unk0;
|
||||
u16 token;
|
||||
u16 boxLeft;
|
||||
u16 boxRight;
|
||||
u16 boxTop;
|
||||
u16 boxBottom;
|
||||
};
|
||||
|
||||
extern PEReg pereg;
|
||||
|
||||
void Init();
|
||||
void DoState(PointerWrap &p);
|
||||
|
||||
// Read
|
||||
void Read16(u16& _uReturnValue, const u32 _iAddress);
|
||||
|
||||
// Write
|
||||
void Write16(const u16 _iValue, const u32 _iAddress);
|
||||
void Write32(const u32 _iValue, const u32 _iAddress);
|
||||
|
||||
// gfx plugin support
|
||||
void SetToken(const u16 _token, const int _bSetTokenAcknowledge);
|
||||
void SetFinish(void);
|
||||
bool AllowIdleSkipping();
|
||||
|
||||
} // end of namespace PixelEngine
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
#ifndef _PIXELENGINE_H
|
||||
#define _PIXELENGINE_H
|
||||
|
||||
#include "Common.h"
|
||||
#include "pluginspecs_video.h"
|
||||
#include "VideoCommon.h"
|
||||
class PointerWrap;
|
||||
|
||||
namespace PixelEngine
|
||||
{
|
||||
// internal hardware addresses
|
||||
enum
|
||||
{
|
||||
PE_ZCONF = 0x000, // Z Config
|
||||
PE_ALPHACONF = 0x002, // Alpha Config
|
||||
PE_DSTALPHACONF = 0x004, // Destination Alpha Config
|
||||
PE_ALPHAMODE = 0x006, // Alpha Mode Config
|
||||
PE_ALPHAREAD = 0x008, // Alpha Read
|
||||
PE_CTRL_REGISTER = 0x00a, // Control
|
||||
PE_TOKEN_REG = 0x00e, // Token
|
||||
PE_BBOX_LEFT = 0x010, // Flip Left
|
||||
PE_BBOX_RIGHT = 0x012, // Flip Right
|
||||
PE_BBOX_TOP = 0x014, // Flip Top
|
||||
PE_BBOX_BOTTOM = 0x016, // Flip Bottom
|
||||
};
|
||||
|
||||
union UPEZConfReg
|
||||
{
|
||||
u16 Hex;
|
||||
struct
|
||||
{
|
||||
u16 ZCompEnable : 1; // Z Comparator Enable
|
||||
u16 Function : 3;
|
||||
u16 ZUpdEnable : 1;
|
||||
u16 : 11;
|
||||
};
|
||||
};
|
||||
|
||||
union UPEAlphaConfReg
|
||||
{
|
||||
u16 Hex;
|
||||
struct
|
||||
{
|
||||
u16 BMMath : 1; // GX_BM_BLEND || GX_BM_SUBSTRACT
|
||||
u16 BMLogic : 1; // GX_BM_LOGIC
|
||||
u16 Dither : 1;
|
||||
u16 ColorUpdEnable : 1;
|
||||
u16 AlphaUpdEnable : 1;
|
||||
u16 DstFactor : 3;
|
||||
u16 SrcFactor : 3;
|
||||
u16 Substract : 1; // Additive mode by default
|
||||
u16 BlendOperator : 4;
|
||||
};
|
||||
};
|
||||
|
||||
union UPEDstAlphaConfReg
|
||||
{
|
||||
u16 Hex;
|
||||
struct
|
||||
{
|
||||
u16 DstAlpha : 8;
|
||||
u16 Enable : 1;
|
||||
u16 : 7;
|
||||
};
|
||||
};
|
||||
|
||||
union UPEAlphaModeConfReg
|
||||
{
|
||||
u16 Hex;
|
||||
struct
|
||||
{
|
||||
u16 Threshold : 8;
|
||||
u16 CompareMode : 8;
|
||||
};
|
||||
};
|
||||
|
||||
union UPEAlphaReadReg
|
||||
{
|
||||
u16 Hex;
|
||||
struct
|
||||
{
|
||||
u16 ReadMode : 3;
|
||||
u16 : 13;
|
||||
};
|
||||
};
|
||||
|
||||
union UPECtrlReg
|
||||
{
|
||||
struct
|
||||
{
|
||||
u16 PETokenEnable : 1;
|
||||
u16 PEFinishEnable : 1;
|
||||
u16 PEToken : 1; // write only
|
||||
u16 PEFinish : 1; // write only
|
||||
u16 : 12;
|
||||
};
|
||||
u16 Hex;
|
||||
UPECtrlReg() {Hex = 0; }
|
||||
UPECtrlReg(u16 _hex) {Hex = _hex; }
|
||||
};
|
||||
|
||||
struct PEReg
|
||||
{
|
||||
UPEZConfReg zconf;
|
||||
UPEAlphaConfReg alphaConf;
|
||||
UPEDstAlphaConfReg dstAlpha;
|
||||
UPEAlphaModeConfReg alphaMode;
|
||||
UPEAlphaReadReg alphaRead;
|
||||
UPECtrlReg ctrl;
|
||||
u16 unk0;
|
||||
u16 token;
|
||||
u16 boxLeft;
|
||||
u16 boxRight;
|
||||
u16 boxTop;
|
||||
u16 boxBottom;
|
||||
};
|
||||
|
||||
extern PEReg pereg;
|
||||
|
||||
void Init();
|
||||
void DoState(PointerWrap &p);
|
||||
|
||||
// Read
|
||||
void Read16(u16& _uReturnValue, const u32 _iAddress);
|
||||
|
||||
// Write
|
||||
void Write16(const u16 _iValue, const u32 _iAddress);
|
||||
void Write32(const u32 _iValue, const u32 _iAddress);
|
||||
|
||||
// gfx plugin support
|
||||
void SetToken(const u16 _token, const int _bSetTokenAcknowledge);
|
||||
void SetFinish(void);
|
||||
bool AllowIdleSkipping();
|
||||
|
||||
} // end of namespace PixelEngine
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -1,473 +1,473 @@
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
#include "Rasterizer.h"
|
||||
#include "HwRasterizer.h"
|
||||
#include "EfbInterface.h"
|
||||
#include "BPMemLoader.h"
|
||||
#include "XFMemLoader.h"
|
||||
#include "Tev.h"
|
||||
#include "Statistics.h"
|
||||
#include "VideoConfig.h"
|
||||
|
||||
|
||||
#define BLOCK_SIZE 2
|
||||
|
||||
#define CLAMP(x, a, b) (x>b)?b:(x<a)?a:x
|
||||
|
||||
// returns approximation of log2(f) in s28.4
|
||||
// results are close enough to use for LOD
|
||||
static inline s32 FixedLog2(float f)
|
||||
{
|
||||
u32 *x = (u32*)&f;
|
||||
s32 logInt = ((*x & 0x7F800000) >> 19) - 2032; // integer part
|
||||
s32 logFract = (*x & 0x007fffff) >> 19; // approximate fractional part
|
||||
|
||||
return logInt + logFract;
|
||||
}
|
||||
|
||||
namespace Rasterizer
|
||||
{
|
||||
Slope ZSlope;
|
||||
Slope WSlope;
|
||||
Slope ColorSlopes[2][4];
|
||||
Slope TexSlopes[8][3];
|
||||
|
||||
s32 vertex0X;
|
||||
s32 vertex0Y;
|
||||
float vertexOffsetX;
|
||||
float vertexOffsetY;
|
||||
|
||||
s32 scissorLeft = 0;
|
||||
s32 scissorTop = 0;
|
||||
s32 scissorRight = 0;
|
||||
s32 scissorBottom = 0;
|
||||
|
||||
Tev tev;
|
||||
RasterBlock rasterBlock;
|
||||
|
||||
void Init()
|
||||
{
|
||||
tev.Init();
|
||||
}
|
||||
|
||||
inline int iround(float x)
|
||||
{
|
||||
int t;
|
||||
|
||||
#if defined(_WIN32) && !defined(_M_X64)
|
||||
__asm
|
||||
{
|
||||
fld x
|
||||
fistp t
|
||||
}
|
||||
#else
|
||||
t = (int)x;
|
||||
if((x - t) >= 0.5)
|
||||
return t + 1;
|
||||
#endif
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
void SetScissor()
|
||||
{
|
||||
int xoff = bpmem.scissorOffset.x * 2 - 342;
|
||||
int yoff = bpmem.scissorOffset.y * 2 - 342;
|
||||
|
||||
scissorLeft = bpmem.scissorTL.x - xoff - 342;
|
||||
if (scissorLeft < 0) scissorLeft = 0;
|
||||
|
||||
scissorTop = bpmem.scissorTL.y - yoff - 342;
|
||||
if (scissorTop < 0) scissorTop = 0;
|
||||
|
||||
scissorRight = bpmem.scissorBR.x - xoff - 341;
|
||||
if (scissorRight > EFB_WIDTH) scissorRight = EFB_WIDTH;
|
||||
|
||||
scissorBottom = bpmem.scissorBR.y - yoff - 341;
|
||||
if (scissorBottom > EFB_HEIGHT) scissorBottom = EFB_HEIGHT;
|
||||
}
|
||||
|
||||
void SetTevReg(int reg, int comp, bool konst, s16 color)
|
||||
{
|
||||
tev.SetRegColor(reg, comp, konst, color);
|
||||
}
|
||||
|
||||
inline void Draw(s32 x, s32 y, s32 xi, s32 yi)
|
||||
{
|
||||
INCSTAT(stats.thisFrame.rasterizedPixels);
|
||||
|
||||
float dx = vertexOffsetX + (float)(x - vertex0X);
|
||||
float dy = vertexOffsetY + (float)(y - vertex0Y);
|
||||
|
||||
float zFloat = 1.0f + ZSlope.GetValue(dx, dy);
|
||||
if (zFloat < 0.0f || zFloat > 1.0f)
|
||||
return;
|
||||
|
||||
s32 z = (s32)(zFloat * 0x00ffffff);
|
||||
|
||||
if (bpmem.zcontrol.zcomploc && bpmem.zmode.testenable)
|
||||
{
|
||||
// early z
|
||||
if (!EfbInterface::ZCompare(x, y, z))
|
||||
return;
|
||||
}
|
||||
|
||||
RasterBlockPixel& pixel = rasterBlock.Pixel[xi][yi];
|
||||
|
||||
tev.Position[0] = x;
|
||||
tev.Position[1] = y;
|
||||
tev.Position[2] = z;
|
||||
|
||||
// colors
|
||||
for (unsigned int i = 0; i < bpmem.genMode.numcolchans; i++)
|
||||
{
|
||||
for(int comp = 0; comp < 4; comp++)
|
||||
tev.Color[i][comp] = (u8)ColorSlopes[i][comp].GetValue(dx, dy);
|
||||
}
|
||||
|
||||
// tex coords
|
||||
for (unsigned int i = 0; i < bpmem.genMode.numtexgens; i++)
|
||||
{
|
||||
// multiply by 128 because TEV stores stores UVs as s17.7
|
||||
tev.Uv[i].s = (s32)(pixel.Uv[i][0] * 128);
|
||||
tev.Uv[i].t = (s32)(pixel.Uv[i][1] * 128);
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < bpmem.genMode.numindstages; i++)
|
||||
{
|
||||
tev.IndirectLod[i] = rasterBlock.IndirectLod[i];
|
||||
tev.IndirectLinear[i] = rasterBlock.IndirectLinear[i];
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i <= bpmem.genMode.numtevstages; i++)
|
||||
{
|
||||
tev.TextureLod[i] = rasterBlock.TextureLod[i];
|
||||
tev.TextureLinear[i] = rasterBlock.TextureLinear[i];
|
||||
}
|
||||
|
||||
tev.Draw();
|
||||
}
|
||||
|
||||
void InitTriangle(float X1, float Y1, s32 xi, s32 yi)
|
||||
{
|
||||
vertex0X = xi;
|
||||
vertex0Y = yi;
|
||||
|
||||
// adjust a little less than 0.5
|
||||
const float adjust = 0.495f;
|
||||
|
||||
vertexOffsetX = ((float)xi - X1) + adjust;
|
||||
vertexOffsetY = ((float)yi - Y1) + adjust;
|
||||
}
|
||||
|
||||
void InitSlope(Slope *slope, float f1, float f2, float f3, float DX31, float DX12, float DY12, float DY31)
|
||||
{
|
||||
float DF31 = f3 - f1;
|
||||
float DF21 = f2 - f1;
|
||||
float a = DF31 * -DY12 - DF21 * DY31;
|
||||
float b = DX31 * DF21 + DX12 * DF31;
|
||||
float c = -DX12 * DY31 - DX31 * -DY12;
|
||||
slope->dfdx = -a / c;
|
||||
slope->dfdy = -b / c;
|
||||
slope->f0 = f1;
|
||||
}
|
||||
|
||||
inline void CalculateLOD(s32 &lod, bool &linear, u32 texmap, u32 texcoord)
|
||||
{
|
||||
FourTexUnits& texUnit = bpmem.tex[(texmap >> 2) & 1];
|
||||
u8 subTexmap = texmap & 3;
|
||||
|
||||
// LOD calculation requires data from the texture mode for bias, etc.
|
||||
// it does not seem to use the actual texture size
|
||||
TexMode0& tm0 = texUnit.texMode0[subTexmap];
|
||||
TexMode1& tm1 = texUnit.texMode1[subTexmap];
|
||||
|
||||
float sDelta, tDelta;
|
||||
if (tm0.diag_lod)
|
||||
{
|
||||
float *uv0 = rasterBlock.Pixel[0][0].Uv[texcoord];
|
||||
float *uv1 = rasterBlock.Pixel[1][1].Uv[texcoord];
|
||||
|
||||
sDelta = abs(uv0[0] - uv1[0]);
|
||||
tDelta = abs(uv0[1] - uv1[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
float *uv0 = rasterBlock.Pixel[0][0].Uv[texcoord];
|
||||
float *uv1 = rasterBlock.Pixel[1][0].Uv[texcoord];
|
||||
float *uv2 = rasterBlock.Pixel[0][1].Uv[texcoord];
|
||||
|
||||
sDelta = max(abs(uv0[0] - uv1[0]), abs(uv0[0] - uv2[0]));
|
||||
tDelta = max(abs(uv0[1] - uv1[1]), abs(uv0[1] - uv2[1]));
|
||||
}
|
||||
|
||||
// get LOD in s28.4
|
||||
lod = FixedLog2(max(sDelta, tDelta));
|
||||
|
||||
// bias is s2.5
|
||||
int bias = tm0.lod_bias;
|
||||
bias >>= 1;
|
||||
lod += bias;
|
||||
|
||||
linear = ((lod > 0 && (tm0.min_filter & 4)) || (lod <= 0 && tm0.mag_filter));
|
||||
|
||||
// order of checks matters
|
||||
// should be:
|
||||
// if lod > max then max
|
||||
// else if lod < min then min
|
||||
lod = CLAMP(lod, (s32)tm1.min_lod, (s32)tm1.max_lod);
|
||||
}
|
||||
|
||||
void BuildBlock(s32 blockX, s32 blockY)
|
||||
{
|
||||
for (s32 yi = 0; yi < BLOCK_SIZE; yi++)
|
||||
{
|
||||
for (s32 xi = 0; xi < BLOCK_SIZE; xi++)
|
||||
{
|
||||
RasterBlockPixel& pixel = rasterBlock.Pixel[xi][yi];
|
||||
|
||||
float dx = vertexOffsetX + (float)(xi + blockX - vertex0X);
|
||||
float dy = vertexOffsetY + (float)(yi + blockY - vertex0Y);
|
||||
|
||||
float invW = 1.0f / WSlope.GetValue(dx, dy);
|
||||
pixel.InvW = invW;
|
||||
|
||||
// tex coords
|
||||
for (unsigned int i = 0; i < bpmem.genMode.numtexgens; i++)
|
||||
{
|
||||
float projection;
|
||||
if (xfregs.texMtxInfo[i].projection)
|
||||
{
|
||||
float q = TexSlopes[i][2].GetValue(dx, dy) * invW;
|
||||
projection = invW / q;
|
||||
}
|
||||
else
|
||||
projection = invW;
|
||||
|
||||
pixel.Uv[i][0] = TexSlopes[i][0].GetValue(dx, dy) * projection;
|
||||
pixel.Uv[i][1] = TexSlopes[i][1].GetValue(dx, dy) * projection;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
u32 indref = bpmem.tevindref.hex;
|
||||
for (unsigned int i = 0; i < bpmem.genMode.numindstages; i++)
|
||||
{
|
||||
u32 texmap = indref & 3;
|
||||
indref >>= 3;
|
||||
u32 texcoord = indref & 3;
|
||||
indref >>= 3;
|
||||
|
||||
CalculateLOD(rasterBlock.IndirectLod[i], rasterBlock.IndirectLinear[i], texmap, texcoord);
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i <= bpmem.genMode.numtevstages; i++)
|
||||
{
|
||||
int stageOdd = i&1;
|
||||
TwoTevStageOrders &order = bpmem.tevorders[i >> 1];
|
||||
if(order.getEnable(stageOdd))
|
||||
{
|
||||
u32 texmap = order.getTexMap(stageOdd);
|
||||
u32 texcoord = order.getTexCoord(stageOdd);
|
||||
|
||||
CalculateLOD(rasterBlock.TextureLod[i], rasterBlock.TextureLinear[i], texmap, texcoord);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DrawTriangleFrontFace(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2)
|
||||
{
|
||||
INCSTAT(stats.thisFrame.numTrianglesDrawn);
|
||||
|
||||
if (g_Config.bHwRasterizer)
|
||||
{
|
||||
HwRasterizer::DrawTriangleFrontFace(v0, v1, v2);
|
||||
return;
|
||||
}
|
||||
|
||||
// adapted from http://www.devmaster.net/forums/showthread.php?t=1884
|
||||
|
||||
// 28.4 fixed-pou32 coordinates. rounded to nearest and adjusted to match hardware output
|
||||
// could also take floor and adjust -8
|
||||
const s32 Y1 = iround(16.0f * v0->screenPosition[1]) - 9;
|
||||
const s32 Y2 = iround(16.0f * v1->screenPosition[1]) - 9;
|
||||
const s32 Y3 = iround(16.0f * v2->screenPosition[1]) - 9;
|
||||
|
||||
const s32 X1 = iround(16.0f * v0->screenPosition[0]) - 9;
|
||||
const s32 X2 = iround(16.0f * v1->screenPosition[0]) - 9;
|
||||
const s32 X3 = iround(16.0f * v2->screenPosition[0]) - 9;
|
||||
|
||||
// Deltas
|
||||
const s32 DX12 = X1 - X2;
|
||||
const s32 DX23 = X2 - X3;
|
||||
const s32 DX31 = X3 - X1;
|
||||
|
||||
const s32 DY12 = Y1 - Y2;
|
||||
const s32 DY23 = Y2 - Y3;
|
||||
const s32 DY31 = Y3 - Y1;
|
||||
|
||||
// Fixed-pos32 deltas
|
||||
const s32 FDX12 = DX12 << 4;
|
||||
const s32 FDX23 = DX23 << 4;
|
||||
const s32 FDX31 = DX31 << 4;
|
||||
|
||||
const s32 FDY12 = DY12 << 4;
|
||||
const s32 FDY23 = DY23 << 4;
|
||||
const s32 FDY31 = DY31 << 4;
|
||||
|
||||
// Bounding rectangle
|
||||
s32 minx = (min(min(X1, X2), X3) + 0xF) >> 4;
|
||||
s32 maxx = (max(max(X1, X2), X3) + 0xF) >> 4;
|
||||
s32 miny = (min(min(Y1, Y2), Y3) + 0xF) >> 4;
|
||||
s32 maxy = (max(max(Y1, Y2), Y3) + 0xF) >> 4;
|
||||
|
||||
// scissor
|
||||
minx = max(minx, scissorLeft);
|
||||
maxx = min(maxx, scissorRight);
|
||||
miny = max(miny, scissorTop);
|
||||
maxy = min(maxy, scissorBottom);
|
||||
|
||||
if (minx >= maxx || miny >= maxy)
|
||||
return;
|
||||
|
||||
// Setup slopes
|
||||
float fltx1 = v0->screenPosition.x;
|
||||
float flty1 = v0->screenPosition.y;
|
||||
float fltdx31 = v2->screenPosition.x - fltx1;
|
||||
float fltdx12 = fltx1 - v1->screenPosition.x;
|
||||
float fltdy12 = flty1 - v1->screenPosition.y;
|
||||
float fltdy31 = v2->screenPosition.y - flty1;
|
||||
|
||||
InitTriangle(fltx1, flty1, (X1 + 0xF) >> 4, (Y1 + 0xF) >> 4);
|
||||
|
||||
float w[3] = { 1.0f / v0->projectedPosition.w, 1.0f / v1->projectedPosition.w, 1.0f / v2->projectedPosition.w };
|
||||
InitSlope(&WSlope, w[0], w[1], w[2], fltdx31, fltdx12, fltdy12, fltdy31);
|
||||
|
||||
InitSlope(&ZSlope, v0->screenPosition[2], v1->screenPosition[2], v2->screenPosition[2], fltdx31, fltdx12, fltdy12, fltdy31);
|
||||
|
||||
for(unsigned int i = 0; i < bpmem.genMode.numcolchans; i++)
|
||||
{
|
||||
for(int comp = 0; comp < 4; comp++)
|
||||
InitSlope(&ColorSlopes[i][comp], v0->color[i][comp], v1->color[i][comp], v2->color[i][comp], fltdx31, fltdx12, fltdy12, fltdy31);
|
||||
}
|
||||
|
||||
for(unsigned int i = 0; i < bpmem.genMode.numtexgens; i++)
|
||||
{
|
||||
for(int comp = 0; comp < 3; comp++)
|
||||
InitSlope(&TexSlopes[i][comp], v0->texCoords[i][comp] * w[0], v1->texCoords[i][comp] * w[1], v2->texCoords[i][comp] * w[2], fltdx31, fltdx12, fltdy12, fltdy31);
|
||||
}
|
||||
|
||||
// Start in corner of 8x8 block
|
||||
minx &= ~(BLOCK_SIZE - 1);
|
||||
miny &= ~(BLOCK_SIZE - 1);
|
||||
|
||||
// Half-edge constants
|
||||
s32 C1 = DY12 * X1 - DX12 * Y1;
|
||||
s32 C2 = DY23 * X2 - DX23 * Y2;
|
||||
s32 C3 = DY31 * X3 - DX31 * Y3;
|
||||
|
||||
// Correct for fill convention
|
||||
if(DY12 < 0 || (DY12 == 0 && DX12 > 0)) C1++;
|
||||
if(DY23 < 0 || (DY23 == 0 && DX23 > 0)) C2++;
|
||||
if(DY31 < 0 || (DY31 == 0 && DX31 > 0)) C3++;
|
||||
|
||||
// Loop through blocks
|
||||
for(s32 y = miny; y < maxy; y += BLOCK_SIZE)
|
||||
{
|
||||
for(s32 x = minx; x < maxx; x += BLOCK_SIZE)
|
||||
{
|
||||
// Corners of block
|
||||
s32 x0 = x << 4;
|
||||
s32 x1 = (x + BLOCK_SIZE - 1) << 4;
|
||||
s32 y0 = y << 4;
|
||||
s32 y1 = (y + BLOCK_SIZE - 1) << 4;
|
||||
|
||||
// Evaluate half-space functions
|
||||
bool a00 = C1 + DX12 * y0 - DY12 * x0 > 0;
|
||||
bool a10 = C1 + DX12 * y0 - DY12 * x1 > 0;
|
||||
bool a01 = C1 + DX12 * y1 - DY12 * x0 > 0;
|
||||
bool a11 = C1 + DX12 * y1 - DY12 * x1 > 0;
|
||||
int a = (a00 << 0) | (a10 << 1) | (a01 << 2) | (a11 << 3);
|
||||
|
||||
bool b00 = C2 + DX23 * y0 - DY23 * x0 > 0;
|
||||
bool b10 = C2 + DX23 * y0 - DY23 * x1 > 0;
|
||||
bool b01 = C2 + DX23 * y1 - DY23 * x0 > 0;
|
||||
bool b11 = C2 + DX23 * y1 - DY23 * x1 > 0;
|
||||
int b = (b00 << 0) | (b10 << 1) | (b01 << 2) | (b11 << 3);
|
||||
|
||||
bool c00 = C3 + DX31 * y0 - DY31 * x0 > 0;
|
||||
bool c10 = C3 + DX31 * y0 - DY31 * x1 > 0;
|
||||
bool c01 = C3 + DX31 * y1 - DY31 * x0 > 0;
|
||||
bool c11 = C3 + DX31 * y1 - DY31 * x1 > 0;
|
||||
int c = (c00 << 0) | (c10 << 1) | (c01 << 2) | (c11 << 3);
|
||||
|
||||
// Skip block when outside an edge
|
||||
if(a == 0x0 || b == 0x0 || c == 0x0) continue;
|
||||
|
||||
BuildBlock(x, y);
|
||||
|
||||
// Accept whole block when totally covered
|
||||
if(a == 0xF && b == 0xF && c == 0xF)
|
||||
{
|
||||
for(s32 iy = 0; iy < BLOCK_SIZE; iy++)
|
||||
{
|
||||
for(s32 ix = 0; ix < BLOCK_SIZE; ix++)
|
||||
{
|
||||
Draw(x + ix, y + iy, ix, iy);
|
||||
}
|
||||
}
|
||||
}
|
||||
else // Partially covered block
|
||||
{
|
||||
s32 CY1 = C1 + DX12 * y0 - DY12 * x0;
|
||||
s32 CY2 = C2 + DX23 * y0 - DY23 * x0;
|
||||
s32 CY3 = C3 + DX31 * y0 - DY31 * x0;
|
||||
|
||||
for(s32 iy = 0; iy < BLOCK_SIZE; iy++)
|
||||
{
|
||||
s32 CX1 = CY1;
|
||||
s32 CX2 = CY2;
|
||||
s32 CX3 = CY3;
|
||||
|
||||
for(s32 ix = 0; ix < BLOCK_SIZE; ix++)
|
||||
{
|
||||
if(CX1 > 0 && CX2 > 0 && CX3 > 0)
|
||||
{
|
||||
Draw(x + ix, y + iy, ix, iy);
|
||||
}
|
||||
|
||||
CX1 -= FDY12;
|
||||
CX2 -= FDY23;
|
||||
CX3 -= FDY31;
|
||||
}
|
||||
|
||||
CY1 += FDX12;
|
||||
CY2 += FDX23;
|
||||
CY3 += FDX31;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
#include "Rasterizer.h"
|
||||
#include "HwRasterizer.h"
|
||||
#include "EfbInterface.h"
|
||||
#include "BPMemLoader.h"
|
||||
#include "XFMemLoader.h"
|
||||
#include "Tev.h"
|
||||
#include "Statistics.h"
|
||||
#include "VideoConfig.h"
|
||||
|
||||
|
||||
#define BLOCK_SIZE 2
|
||||
|
||||
#define CLAMP(x, a, b) (x>b)?b:(x<a)?a:x
|
||||
|
||||
// returns approximation of log2(f) in s28.4
|
||||
// results are close enough to use for LOD
|
||||
static inline s32 FixedLog2(float f)
|
||||
{
|
||||
u32 *x = (u32*)&f;
|
||||
s32 logInt = ((*x & 0x7F800000) >> 19) - 2032; // integer part
|
||||
s32 logFract = (*x & 0x007fffff) >> 19; // approximate fractional part
|
||||
|
||||
return logInt + logFract;
|
||||
}
|
||||
|
||||
namespace Rasterizer
|
||||
{
|
||||
Slope ZSlope;
|
||||
Slope WSlope;
|
||||
Slope ColorSlopes[2][4];
|
||||
Slope TexSlopes[8][3];
|
||||
|
||||
s32 vertex0X;
|
||||
s32 vertex0Y;
|
||||
float vertexOffsetX;
|
||||
float vertexOffsetY;
|
||||
|
||||
s32 scissorLeft = 0;
|
||||
s32 scissorTop = 0;
|
||||
s32 scissorRight = 0;
|
||||
s32 scissorBottom = 0;
|
||||
|
||||
Tev tev;
|
||||
RasterBlock rasterBlock;
|
||||
|
||||
void Init()
|
||||
{
|
||||
tev.Init();
|
||||
}
|
||||
|
||||
inline int iround(float x)
|
||||
{
|
||||
int t;
|
||||
|
||||
#if defined(_WIN32) && !defined(_M_X64)
|
||||
__asm
|
||||
{
|
||||
fld x
|
||||
fistp t
|
||||
}
|
||||
#else
|
||||
t = (int)x;
|
||||
if((x - t) >= 0.5)
|
||||
return t + 1;
|
||||
#endif
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
void SetScissor()
|
||||
{
|
||||
int xoff = bpmem.scissorOffset.x * 2 - 342;
|
||||
int yoff = bpmem.scissorOffset.y * 2 - 342;
|
||||
|
||||
scissorLeft = bpmem.scissorTL.x - xoff - 342;
|
||||
if (scissorLeft < 0) scissorLeft = 0;
|
||||
|
||||
scissorTop = bpmem.scissorTL.y - yoff - 342;
|
||||
if (scissorTop < 0) scissorTop = 0;
|
||||
|
||||
scissorRight = bpmem.scissorBR.x - xoff - 341;
|
||||
if (scissorRight > EFB_WIDTH) scissorRight = EFB_WIDTH;
|
||||
|
||||
scissorBottom = bpmem.scissorBR.y - yoff - 341;
|
||||
if (scissorBottom > EFB_HEIGHT) scissorBottom = EFB_HEIGHT;
|
||||
}
|
||||
|
||||
void SetTevReg(int reg, int comp, bool konst, s16 color)
|
||||
{
|
||||
tev.SetRegColor(reg, comp, konst, color);
|
||||
}
|
||||
|
||||
inline void Draw(s32 x, s32 y, s32 xi, s32 yi)
|
||||
{
|
||||
INCSTAT(stats.thisFrame.rasterizedPixels);
|
||||
|
||||
float dx = vertexOffsetX + (float)(x - vertex0X);
|
||||
float dy = vertexOffsetY + (float)(y - vertex0Y);
|
||||
|
||||
float zFloat = 1.0f + ZSlope.GetValue(dx, dy);
|
||||
if (zFloat < 0.0f || zFloat > 1.0f)
|
||||
return;
|
||||
|
||||
s32 z = (s32)(zFloat * 0x00ffffff);
|
||||
|
||||
if (bpmem.zcontrol.zcomploc && bpmem.zmode.testenable)
|
||||
{
|
||||
// early z
|
||||
if (!EfbInterface::ZCompare(x, y, z))
|
||||
return;
|
||||
}
|
||||
|
||||
RasterBlockPixel& pixel = rasterBlock.Pixel[xi][yi];
|
||||
|
||||
tev.Position[0] = x;
|
||||
tev.Position[1] = y;
|
||||
tev.Position[2] = z;
|
||||
|
||||
// colors
|
||||
for (unsigned int i = 0; i < bpmem.genMode.numcolchans; i++)
|
||||
{
|
||||
for(int comp = 0; comp < 4; comp++)
|
||||
tev.Color[i][comp] = (u8)ColorSlopes[i][comp].GetValue(dx, dy);
|
||||
}
|
||||
|
||||
// tex coords
|
||||
for (unsigned int i = 0; i < bpmem.genMode.numtexgens; i++)
|
||||
{
|
||||
// multiply by 128 because TEV stores stores UVs as s17.7
|
||||
tev.Uv[i].s = (s32)(pixel.Uv[i][0] * 128);
|
||||
tev.Uv[i].t = (s32)(pixel.Uv[i][1] * 128);
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < bpmem.genMode.numindstages; i++)
|
||||
{
|
||||
tev.IndirectLod[i] = rasterBlock.IndirectLod[i];
|
||||
tev.IndirectLinear[i] = rasterBlock.IndirectLinear[i];
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i <= bpmem.genMode.numtevstages; i++)
|
||||
{
|
||||
tev.TextureLod[i] = rasterBlock.TextureLod[i];
|
||||
tev.TextureLinear[i] = rasterBlock.TextureLinear[i];
|
||||
}
|
||||
|
||||
tev.Draw();
|
||||
}
|
||||
|
||||
void InitTriangle(float X1, float Y1, s32 xi, s32 yi)
|
||||
{
|
||||
vertex0X = xi;
|
||||
vertex0Y = yi;
|
||||
|
||||
// adjust a little less than 0.5
|
||||
const float adjust = 0.495f;
|
||||
|
||||
vertexOffsetX = ((float)xi - X1) + adjust;
|
||||
vertexOffsetY = ((float)yi - Y1) + adjust;
|
||||
}
|
||||
|
||||
void InitSlope(Slope *slope, float f1, float f2, float f3, float DX31, float DX12, float DY12, float DY31)
|
||||
{
|
||||
float DF31 = f3 - f1;
|
||||
float DF21 = f2 - f1;
|
||||
float a = DF31 * -DY12 - DF21 * DY31;
|
||||
float b = DX31 * DF21 + DX12 * DF31;
|
||||
float c = -DX12 * DY31 - DX31 * -DY12;
|
||||
slope->dfdx = -a / c;
|
||||
slope->dfdy = -b / c;
|
||||
slope->f0 = f1;
|
||||
}
|
||||
|
||||
inline void CalculateLOD(s32 &lod, bool &linear, u32 texmap, u32 texcoord)
|
||||
{
|
||||
FourTexUnits& texUnit = bpmem.tex[(texmap >> 2) & 1];
|
||||
u8 subTexmap = texmap & 3;
|
||||
|
||||
// LOD calculation requires data from the texture mode for bias, etc.
|
||||
// it does not seem to use the actual texture size
|
||||
TexMode0& tm0 = texUnit.texMode0[subTexmap];
|
||||
TexMode1& tm1 = texUnit.texMode1[subTexmap];
|
||||
|
||||
float sDelta, tDelta;
|
||||
if (tm0.diag_lod)
|
||||
{
|
||||
float *uv0 = rasterBlock.Pixel[0][0].Uv[texcoord];
|
||||
float *uv1 = rasterBlock.Pixel[1][1].Uv[texcoord];
|
||||
|
||||
sDelta = abs(uv0[0] - uv1[0]);
|
||||
tDelta = abs(uv0[1] - uv1[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
float *uv0 = rasterBlock.Pixel[0][0].Uv[texcoord];
|
||||
float *uv1 = rasterBlock.Pixel[1][0].Uv[texcoord];
|
||||
float *uv2 = rasterBlock.Pixel[0][1].Uv[texcoord];
|
||||
|
||||
sDelta = max(abs(uv0[0] - uv1[0]), abs(uv0[0] - uv2[0]));
|
||||
tDelta = max(abs(uv0[1] - uv1[1]), abs(uv0[1] - uv2[1]));
|
||||
}
|
||||
|
||||
// get LOD in s28.4
|
||||
lod = FixedLog2(max(sDelta, tDelta));
|
||||
|
||||
// bias is s2.5
|
||||
int bias = tm0.lod_bias;
|
||||
bias >>= 1;
|
||||
lod += bias;
|
||||
|
||||
linear = ((lod > 0 && (tm0.min_filter & 4)) || (lod <= 0 && tm0.mag_filter));
|
||||
|
||||
// order of checks matters
|
||||
// should be:
|
||||
// if lod > max then max
|
||||
// else if lod < min then min
|
||||
lod = CLAMP(lod, (s32)tm1.min_lod, (s32)tm1.max_lod);
|
||||
}
|
||||
|
||||
void BuildBlock(s32 blockX, s32 blockY)
|
||||
{
|
||||
for (s32 yi = 0; yi < BLOCK_SIZE; yi++)
|
||||
{
|
||||
for (s32 xi = 0; xi < BLOCK_SIZE; xi++)
|
||||
{
|
||||
RasterBlockPixel& pixel = rasterBlock.Pixel[xi][yi];
|
||||
|
||||
float dx = vertexOffsetX + (float)(xi + blockX - vertex0X);
|
||||
float dy = vertexOffsetY + (float)(yi + blockY - vertex0Y);
|
||||
|
||||
float invW = 1.0f / WSlope.GetValue(dx, dy);
|
||||
pixel.InvW = invW;
|
||||
|
||||
// tex coords
|
||||
for (unsigned int i = 0; i < bpmem.genMode.numtexgens; i++)
|
||||
{
|
||||
float projection;
|
||||
if (xfregs.texMtxInfo[i].projection)
|
||||
{
|
||||
float q = TexSlopes[i][2].GetValue(dx, dy) * invW;
|
||||
projection = invW / q;
|
||||
}
|
||||
else
|
||||
projection = invW;
|
||||
|
||||
pixel.Uv[i][0] = TexSlopes[i][0].GetValue(dx, dy) * projection;
|
||||
pixel.Uv[i][1] = TexSlopes[i][1].GetValue(dx, dy) * projection;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
u32 indref = bpmem.tevindref.hex;
|
||||
for (unsigned int i = 0; i < bpmem.genMode.numindstages; i++)
|
||||
{
|
||||
u32 texmap = indref & 3;
|
||||
indref >>= 3;
|
||||
u32 texcoord = indref & 3;
|
||||
indref >>= 3;
|
||||
|
||||
CalculateLOD(rasterBlock.IndirectLod[i], rasterBlock.IndirectLinear[i], texmap, texcoord);
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i <= bpmem.genMode.numtevstages; i++)
|
||||
{
|
||||
int stageOdd = i&1;
|
||||
TwoTevStageOrders &order = bpmem.tevorders[i >> 1];
|
||||
if(order.getEnable(stageOdd))
|
||||
{
|
||||
u32 texmap = order.getTexMap(stageOdd);
|
||||
u32 texcoord = order.getTexCoord(stageOdd);
|
||||
|
||||
CalculateLOD(rasterBlock.TextureLod[i], rasterBlock.TextureLinear[i], texmap, texcoord);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DrawTriangleFrontFace(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2)
|
||||
{
|
||||
INCSTAT(stats.thisFrame.numTrianglesDrawn);
|
||||
|
||||
if (g_Config.bHwRasterizer)
|
||||
{
|
||||
HwRasterizer::DrawTriangleFrontFace(v0, v1, v2);
|
||||
return;
|
||||
}
|
||||
|
||||
// adapted from http://www.devmaster.net/forums/showthread.php?t=1884
|
||||
|
||||
// 28.4 fixed-pou32 coordinates. rounded to nearest and adjusted to match hardware output
|
||||
// could also take floor and adjust -8
|
||||
const s32 Y1 = iround(16.0f * v0->screenPosition[1]) - 9;
|
||||
const s32 Y2 = iround(16.0f * v1->screenPosition[1]) - 9;
|
||||
const s32 Y3 = iround(16.0f * v2->screenPosition[1]) - 9;
|
||||
|
||||
const s32 X1 = iround(16.0f * v0->screenPosition[0]) - 9;
|
||||
const s32 X2 = iround(16.0f * v1->screenPosition[0]) - 9;
|
||||
const s32 X3 = iround(16.0f * v2->screenPosition[0]) - 9;
|
||||
|
||||
// Deltas
|
||||
const s32 DX12 = X1 - X2;
|
||||
const s32 DX23 = X2 - X3;
|
||||
const s32 DX31 = X3 - X1;
|
||||
|
||||
const s32 DY12 = Y1 - Y2;
|
||||
const s32 DY23 = Y2 - Y3;
|
||||
const s32 DY31 = Y3 - Y1;
|
||||
|
||||
// Fixed-pos32 deltas
|
||||
const s32 FDX12 = DX12 << 4;
|
||||
const s32 FDX23 = DX23 << 4;
|
||||
const s32 FDX31 = DX31 << 4;
|
||||
|
||||
const s32 FDY12 = DY12 << 4;
|
||||
const s32 FDY23 = DY23 << 4;
|
||||
const s32 FDY31 = DY31 << 4;
|
||||
|
||||
// Bounding rectangle
|
||||
s32 minx = (min(min(X1, X2), X3) + 0xF) >> 4;
|
||||
s32 maxx = (max(max(X1, X2), X3) + 0xF) >> 4;
|
||||
s32 miny = (min(min(Y1, Y2), Y3) + 0xF) >> 4;
|
||||
s32 maxy = (max(max(Y1, Y2), Y3) + 0xF) >> 4;
|
||||
|
||||
// scissor
|
||||
minx = max(minx, scissorLeft);
|
||||
maxx = min(maxx, scissorRight);
|
||||
miny = max(miny, scissorTop);
|
||||
maxy = min(maxy, scissorBottom);
|
||||
|
||||
if (minx >= maxx || miny >= maxy)
|
||||
return;
|
||||
|
||||
// Setup slopes
|
||||
float fltx1 = v0->screenPosition.x;
|
||||
float flty1 = v0->screenPosition.y;
|
||||
float fltdx31 = v2->screenPosition.x - fltx1;
|
||||
float fltdx12 = fltx1 - v1->screenPosition.x;
|
||||
float fltdy12 = flty1 - v1->screenPosition.y;
|
||||
float fltdy31 = v2->screenPosition.y - flty1;
|
||||
|
||||
InitTriangle(fltx1, flty1, (X1 + 0xF) >> 4, (Y1 + 0xF) >> 4);
|
||||
|
||||
float w[3] = { 1.0f / v0->projectedPosition.w, 1.0f / v1->projectedPosition.w, 1.0f / v2->projectedPosition.w };
|
||||
InitSlope(&WSlope, w[0], w[1], w[2], fltdx31, fltdx12, fltdy12, fltdy31);
|
||||
|
||||
InitSlope(&ZSlope, v0->screenPosition[2], v1->screenPosition[2], v2->screenPosition[2], fltdx31, fltdx12, fltdy12, fltdy31);
|
||||
|
||||
for(unsigned int i = 0; i < bpmem.genMode.numcolchans; i++)
|
||||
{
|
||||
for(int comp = 0; comp < 4; comp++)
|
||||
InitSlope(&ColorSlopes[i][comp], v0->color[i][comp], v1->color[i][comp], v2->color[i][comp], fltdx31, fltdx12, fltdy12, fltdy31);
|
||||
}
|
||||
|
||||
for(unsigned int i = 0; i < bpmem.genMode.numtexgens; i++)
|
||||
{
|
||||
for(int comp = 0; comp < 3; comp++)
|
||||
InitSlope(&TexSlopes[i][comp], v0->texCoords[i][comp] * w[0], v1->texCoords[i][comp] * w[1], v2->texCoords[i][comp] * w[2], fltdx31, fltdx12, fltdy12, fltdy31);
|
||||
}
|
||||
|
||||
// Start in corner of 8x8 block
|
||||
minx &= ~(BLOCK_SIZE - 1);
|
||||
miny &= ~(BLOCK_SIZE - 1);
|
||||
|
||||
// Half-edge constants
|
||||
s32 C1 = DY12 * X1 - DX12 * Y1;
|
||||
s32 C2 = DY23 * X2 - DX23 * Y2;
|
||||
s32 C3 = DY31 * X3 - DX31 * Y3;
|
||||
|
||||
// Correct for fill convention
|
||||
if(DY12 < 0 || (DY12 == 0 && DX12 > 0)) C1++;
|
||||
if(DY23 < 0 || (DY23 == 0 && DX23 > 0)) C2++;
|
||||
if(DY31 < 0 || (DY31 == 0 && DX31 > 0)) C3++;
|
||||
|
||||
// Loop through blocks
|
||||
for(s32 y = miny; y < maxy; y += BLOCK_SIZE)
|
||||
{
|
||||
for(s32 x = minx; x < maxx; x += BLOCK_SIZE)
|
||||
{
|
||||
// Corners of block
|
||||
s32 x0 = x << 4;
|
||||
s32 x1 = (x + BLOCK_SIZE - 1) << 4;
|
||||
s32 y0 = y << 4;
|
||||
s32 y1 = (y + BLOCK_SIZE - 1) << 4;
|
||||
|
||||
// Evaluate half-space functions
|
||||
bool a00 = C1 + DX12 * y0 - DY12 * x0 > 0;
|
||||
bool a10 = C1 + DX12 * y0 - DY12 * x1 > 0;
|
||||
bool a01 = C1 + DX12 * y1 - DY12 * x0 > 0;
|
||||
bool a11 = C1 + DX12 * y1 - DY12 * x1 > 0;
|
||||
int a = (a00 << 0) | (a10 << 1) | (a01 << 2) | (a11 << 3);
|
||||
|
||||
bool b00 = C2 + DX23 * y0 - DY23 * x0 > 0;
|
||||
bool b10 = C2 + DX23 * y0 - DY23 * x1 > 0;
|
||||
bool b01 = C2 + DX23 * y1 - DY23 * x0 > 0;
|
||||
bool b11 = C2 + DX23 * y1 - DY23 * x1 > 0;
|
||||
int b = (b00 << 0) | (b10 << 1) | (b01 << 2) | (b11 << 3);
|
||||
|
||||
bool c00 = C3 + DX31 * y0 - DY31 * x0 > 0;
|
||||
bool c10 = C3 + DX31 * y0 - DY31 * x1 > 0;
|
||||
bool c01 = C3 + DX31 * y1 - DY31 * x0 > 0;
|
||||
bool c11 = C3 + DX31 * y1 - DY31 * x1 > 0;
|
||||
int c = (c00 << 0) | (c10 << 1) | (c01 << 2) | (c11 << 3);
|
||||
|
||||
// Skip block when outside an edge
|
||||
if(a == 0x0 || b == 0x0 || c == 0x0) continue;
|
||||
|
||||
BuildBlock(x, y);
|
||||
|
||||
// Accept whole block when totally covered
|
||||
if(a == 0xF && b == 0xF && c == 0xF)
|
||||
{
|
||||
for(s32 iy = 0; iy < BLOCK_SIZE; iy++)
|
||||
{
|
||||
for(s32 ix = 0; ix < BLOCK_SIZE; ix++)
|
||||
{
|
||||
Draw(x + ix, y + iy, ix, iy);
|
||||
}
|
||||
}
|
||||
}
|
||||
else // Partially covered block
|
||||
{
|
||||
s32 CY1 = C1 + DX12 * y0 - DY12 * x0;
|
||||
s32 CY2 = C2 + DX23 * y0 - DY23 * x0;
|
||||
s32 CY3 = C3 + DX31 * y0 - DY31 * x0;
|
||||
|
||||
for(s32 iy = 0; iy < BLOCK_SIZE; iy++)
|
||||
{
|
||||
s32 CX1 = CY1;
|
||||
s32 CX2 = CY2;
|
||||
s32 CX3 = CY3;
|
||||
|
||||
for(s32 ix = 0; ix < BLOCK_SIZE; ix++)
|
||||
{
|
||||
if(CX1 > 0 && CX2 > 0 && CX3 > 0)
|
||||
{
|
||||
Draw(x + ix, y + iy, ix, iy);
|
||||
}
|
||||
|
||||
CX1 -= FDY12;
|
||||
CX2 -= FDY23;
|
||||
CX3 -= FDY31;
|
||||
}
|
||||
|
||||
CY1 += FDX12;
|
||||
CY2 += FDX23;
|
||||
CY3 += FDX31;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -1,59 +1,59 @@
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _RASTERIZER_H_
|
||||
#define _RASTERIZER_H_
|
||||
|
||||
#include "NativeVertexFormat.h"
|
||||
|
||||
namespace Rasterizer
|
||||
{
|
||||
void Init();
|
||||
|
||||
void DrawTriangleFrontFace(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2);
|
||||
|
||||
void SetScissor();
|
||||
|
||||
void SetTevReg(int reg, int comp, bool konst, s16 color);
|
||||
|
||||
struct Slope
|
||||
{
|
||||
float dfdx;
|
||||
float dfdy;
|
||||
float f0;
|
||||
|
||||
float GetValue(float dx, float dy) { return f0 + (dfdx * dx) + (dfdy * dy); }
|
||||
};
|
||||
|
||||
struct RasterBlockPixel
|
||||
{
|
||||
float InvW;
|
||||
float Uv[8][2];
|
||||
};
|
||||
|
||||
struct RasterBlock
|
||||
{
|
||||
RasterBlockPixel Pixel[2][2];
|
||||
s32 IndirectLod[4];
|
||||
bool IndirectLinear[4];
|
||||
s32 TextureLod[16];
|
||||
bool TextureLinear[16];
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _RASTERIZER_H_
|
||||
#define _RASTERIZER_H_
|
||||
|
||||
#include "NativeVertexFormat.h"
|
||||
|
||||
namespace Rasterizer
|
||||
{
|
||||
void Init();
|
||||
|
||||
void DrawTriangleFrontFace(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2);
|
||||
|
||||
void SetScissor();
|
||||
|
||||
void SetTevReg(int reg, int comp, bool konst, s16 color);
|
||||
|
||||
struct Slope
|
||||
{
|
||||
float dfdx;
|
||||
float dfdy;
|
||||
float f0;
|
||||
|
||||
float GetValue(float dx, float dy) { return f0 + (dfdx * dx) + (dfdy * dy); }
|
||||
};
|
||||
|
||||
struct RasterBlockPixel
|
||||
{
|
||||
float InvW;
|
||||
float Uv[8][2];
|
||||
};
|
||||
|
||||
struct RasterBlock
|
||||
{
|
||||
RasterBlockPixel Pixel[2][2];
|
||||
s32 IndirectLod[4];
|
||||
bool IndirectLinear[4];
|
||||
s32 TextureLod[16];
|
||||
bool TextureLinear[16];
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,204 +1,204 @@
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
#include "GLUtil.h"
|
||||
#include "Renderer.h"
|
||||
#include "main.h"
|
||||
#include "Statistics.h"
|
||||
#include "RasterFont.h"
|
||||
|
||||
#define VSYNC_ENABLED 0
|
||||
|
||||
static GLuint s_RenderTarget = 0;
|
||||
|
||||
RasterFont* s_pfont = NULL;
|
||||
|
||||
void Renderer::Init(SVideoInitialize *_pVideoInitialize)
|
||||
{
|
||||
if (!OpenGL_Create(g_VideoInitialize, 640, 480)) // 640x480 will be the default if all else fails
|
||||
{
|
||||
g_VideoInitialize.pLog("Renderer::Create failed\n", TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
_pVideoInitialize->pPeekMessages = g_VideoInitialize.pPeekMessages;
|
||||
_pVideoInitialize->pUpdateFPSDisplay = g_VideoInitialize.pUpdateFPSDisplay;
|
||||
_pVideoInitialize->pWindowHandle = g_VideoInitialize.pWindowHandle;
|
||||
#if defined(HAVE_X11) && HAVE_X11
|
||||
_pVideoInitialize->pXWindow = g_VideoInitialize.pXWindow;
|
||||
#endif
|
||||
}
|
||||
|
||||
void Renderer::Shutdown()
|
||||
{
|
||||
glDeleteTextures(1, &s_RenderTarget);
|
||||
|
||||
delete s_pfont;
|
||||
s_pfont = 0;
|
||||
}
|
||||
|
||||
void Renderer::Prepare()
|
||||
{
|
||||
OpenGL_MakeCurrent();
|
||||
|
||||
// Init extension support.
|
||||
if (glewInit() != GLEW_OK) {
|
||||
ERROR_LOG(VIDEO, "glewInit() failed!Does your video card support OpenGL 2.x?");
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle VSync on/off
|
||||
#ifdef _WIN32
|
||||
if (WGLEW_EXT_swap_control)
|
||||
wglSwapIntervalEXT(VSYNC_ENABLED);
|
||||
else
|
||||
ERROR_LOG(VIDEO, "no support for SwapInterval (framerate clamped to monitor refresh rate)Does your video card support OpenGL 2.x?");
|
||||
#elif defined(HAVE_X11) && HAVE_X11
|
||||
if (glXSwapIntervalSGI)
|
||||
glXSwapIntervalSGI(VSYNC_ENABLED);
|
||||
else
|
||||
ERROR_LOG(VIDEO, "no support for SwapInterval (framerate clamped to monitor refresh rate)");
|
||||
#endif
|
||||
|
||||
glStencilFunc(GL_ALWAYS, 0, 0);
|
||||
// used by hw rasterizer if it enables blending and depth test
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
|
||||
glShadeModel(GL_SMOOTH);
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
glClearDepth(1.0f);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // 4-byte pixel alignment
|
||||
|
||||
glDisable(GL_LIGHTING);
|
||||
glDisable(GL_BLEND);
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
//glDisable(GL_SCISSOR_TEST);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
s_pfont = new RasterFont();
|
||||
|
||||
// legacy multitexturing: select texture channel only.
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glClientActiveTexture(GL_TEXTURE0);
|
||||
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
|
||||
glGenTextures(1, &s_RenderTarget);
|
||||
glEnable(GL_TEXTURE_RECTANGLE_ARB);
|
||||
}
|
||||
|
||||
void Renderer::RenderText(const char* pstr, int left, int top, u32 color)
|
||||
{
|
||||
int nBackbufferWidth = (int)OpenGL_GetBackbufferWidth();
|
||||
int nBackbufferHeight = (int)OpenGL_GetBackbufferHeight();
|
||||
glColor4f(((color>>16) & 0xff)/255.0f, ((color>> 8) & 0xff)/255.0f,
|
||||
((color>> 0) & 0xff)/255.0f, ((color>>24) & 0xFF)/255.0f);
|
||||
s_pfont->printMultilineText(pstr,
|
||||
left * 2.0f / (float)nBackbufferWidth - 1,
|
||||
1 - top * 2.0f / (float)nBackbufferHeight,
|
||||
0, nBackbufferWidth, nBackbufferHeight);
|
||||
}
|
||||
|
||||
void Renderer::DrawDebugText()
|
||||
{
|
||||
char debugtext_buffer[8192];
|
||||
char *p = debugtext_buffer;
|
||||
p[0] = 0;
|
||||
|
||||
if (g_Config.bShowStats)
|
||||
{
|
||||
p+=sprintf(p,"Objects: %i\n",stats.thisFrame.numDrawnObjects);
|
||||
p+=sprintf(p,"Primatives: %i\n",stats.thisFrame.numPrimatives);
|
||||
p+=sprintf(p,"Vertices Loaded: %i\n",stats.thisFrame.numVerticesLoaded);
|
||||
|
||||
p+=sprintf(p,"Triangles Input: %i\n",stats.thisFrame.numTrianglesIn);
|
||||
p+=sprintf(p,"Triangles Rejected: %i\n",stats.thisFrame.numTrianglesRejected);
|
||||
p+=sprintf(p,"Triangles Culled: %i\n",stats.thisFrame.numTrianglesCulled);
|
||||
p+=sprintf(p,"Triangles Clipped: %i\n",stats.thisFrame.numTrianglesClipped);
|
||||
p+=sprintf(p,"Triangles Drawn: %i\n",stats.thisFrame.numTrianglesDrawn);
|
||||
|
||||
p+=sprintf(p,"Rasterized Pix: %i\n",stats.thisFrame.rasterizedPixels);
|
||||
p+=sprintf(p,"TEV Pix In: %i\n",stats.thisFrame.tevPixelsIn);
|
||||
p+=sprintf(p,"TEV Pix Out: %i\n",stats.thisFrame.tevPixelsOut);
|
||||
}
|
||||
|
||||
// Render a shadow, and then the text.
|
||||
Renderer::RenderText(debugtext_buffer, 21, 21, 0xDD000000);
|
||||
Renderer::RenderText(debugtext_buffer, 20, 20, 0xFFFFFF00);
|
||||
}
|
||||
|
||||
void Renderer::DrawTexture(u8 *texture, int width, int height)
|
||||
{
|
||||
OpenGL_Update(); // just updates the render window position and the backbuffer size
|
||||
|
||||
GLsizei glWidth = (GLsizei)OpenGL_GetBackbufferWidth();
|
||||
GLsizei glHeight = (GLsizei)OpenGL_GetBackbufferHeight();
|
||||
|
||||
// Update GLViewPort
|
||||
glViewport(0, 0, glWidth, glHeight);
|
||||
glScissor(0, 0, glWidth, glHeight);
|
||||
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, s_RenderTarget);
|
||||
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, (GLsizei)width, (GLsizei)height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture);
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
|
||||
GL_REPORT_ERRORD();
|
||||
|
||||
GLfloat u_max = (GLfloat)width;
|
||||
GLfloat v_max = (GLfloat)glHeight;
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(0, v_max); glVertex2f(-1, -1);
|
||||
glTexCoord2f(0, 0); glVertex2f(-1, 1);
|
||||
glTexCoord2f(u_max, 0); glVertex2f( 1, 1);
|
||||
glTexCoord2f(u_max, v_max); glVertex2f( 1, -1);
|
||||
glEnd();
|
||||
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
|
||||
}
|
||||
|
||||
void Renderer::SwapBuffer()
|
||||
{
|
||||
DrawDebugText();
|
||||
|
||||
glFlush();
|
||||
|
||||
OpenGL_SwapBuffers();
|
||||
|
||||
GL_REPORT_ERRORD();
|
||||
|
||||
stats.ResetFrame();
|
||||
|
||||
// Clear framebuffer
|
||||
glClearColor(0, 0, 0, 0);
|
||||
glClearDepth(1.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
GL_REPORT_ERRORD();
|
||||
}
|
||||
|
||||
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
#include "GLUtil.h"
|
||||
#include "Renderer.h"
|
||||
#include "main.h"
|
||||
#include "Statistics.h"
|
||||
#include "RasterFont.h"
|
||||
|
||||
#define VSYNC_ENABLED 0
|
||||
|
||||
static GLuint s_RenderTarget = 0;
|
||||
|
||||
RasterFont* s_pfont = NULL;
|
||||
|
||||
void Renderer::Init(SVideoInitialize *_pVideoInitialize)
|
||||
{
|
||||
if (!OpenGL_Create(g_VideoInitialize, 640, 480)) // 640x480 will be the default if all else fails
|
||||
{
|
||||
g_VideoInitialize.pLog("Renderer::Create failed\n", TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
_pVideoInitialize->pPeekMessages = g_VideoInitialize.pPeekMessages;
|
||||
_pVideoInitialize->pUpdateFPSDisplay = g_VideoInitialize.pUpdateFPSDisplay;
|
||||
_pVideoInitialize->pWindowHandle = g_VideoInitialize.pWindowHandle;
|
||||
#if defined(HAVE_X11) && HAVE_X11
|
||||
_pVideoInitialize->pXWindow = g_VideoInitialize.pXWindow;
|
||||
#endif
|
||||
}
|
||||
|
||||
void Renderer::Shutdown()
|
||||
{
|
||||
glDeleteTextures(1, &s_RenderTarget);
|
||||
|
||||
delete s_pfont;
|
||||
s_pfont = 0;
|
||||
}
|
||||
|
||||
void Renderer::Prepare()
|
||||
{
|
||||
OpenGL_MakeCurrent();
|
||||
|
||||
// Init extension support.
|
||||
if (glewInit() != GLEW_OK) {
|
||||
ERROR_LOG(VIDEO, "glewInit() failed!Does your video card support OpenGL 2.x?");
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle VSync on/off
|
||||
#ifdef _WIN32
|
||||
if (WGLEW_EXT_swap_control)
|
||||
wglSwapIntervalEXT(VSYNC_ENABLED);
|
||||
else
|
||||
ERROR_LOG(VIDEO, "no support for SwapInterval (framerate clamped to monitor refresh rate)Does your video card support OpenGL 2.x?");
|
||||
#elif defined(HAVE_X11) && HAVE_X11
|
||||
if (glXSwapIntervalSGI)
|
||||
glXSwapIntervalSGI(VSYNC_ENABLED);
|
||||
else
|
||||
ERROR_LOG(VIDEO, "no support for SwapInterval (framerate clamped to monitor refresh rate)");
|
||||
#endif
|
||||
|
||||
glStencilFunc(GL_ALWAYS, 0, 0);
|
||||
// used by hw rasterizer if it enables blending and depth test
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
|
||||
glShadeModel(GL_SMOOTH);
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
glClearDepth(1.0f);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // 4-byte pixel alignment
|
||||
|
||||
glDisable(GL_LIGHTING);
|
||||
glDisable(GL_BLEND);
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
//glDisable(GL_SCISSOR_TEST);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
s_pfont = new RasterFont();
|
||||
|
||||
// legacy multitexturing: select texture channel only.
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glClientActiveTexture(GL_TEXTURE0);
|
||||
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
|
||||
glGenTextures(1, &s_RenderTarget);
|
||||
glEnable(GL_TEXTURE_RECTANGLE_ARB);
|
||||
}
|
||||
|
||||
void Renderer::RenderText(const char* pstr, int left, int top, u32 color)
|
||||
{
|
||||
int nBackbufferWidth = (int)OpenGL_GetBackbufferWidth();
|
||||
int nBackbufferHeight = (int)OpenGL_GetBackbufferHeight();
|
||||
glColor4f(((color>>16) & 0xff)/255.0f, ((color>> 8) & 0xff)/255.0f,
|
||||
((color>> 0) & 0xff)/255.0f, ((color>>24) & 0xFF)/255.0f);
|
||||
s_pfont->printMultilineText(pstr,
|
||||
left * 2.0f / (float)nBackbufferWidth - 1,
|
||||
1 - top * 2.0f / (float)nBackbufferHeight,
|
||||
0, nBackbufferWidth, nBackbufferHeight);
|
||||
}
|
||||
|
||||
void Renderer::DrawDebugText()
|
||||
{
|
||||
char debugtext_buffer[8192];
|
||||
char *p = debugtext_buffer;
|
||||
p[0] = 0;
|
||||
|
||||
if (g_Config.bShowStats)
|
||||
{
|
||||
p+=sprintf(p,"Objects: %i\n",stats.thisFrame.numDrawnObjects);
|
||||
p+=sprintf(p,"Primatives: %i\n",stats.thisFrame.numPrimatives);
|
||||
p+=sprintf(p,"Vertices Loaded: %i\n",stats.thisFrame.numVerticesLoaded);
|
||||
|
||||
p+=sprintf(p,"Triangles Input: %i\n",stats.thisFrame.numTrianglesIn);
|
||||
p+=sprintf(p,"Triangles Rejected: %i\n",stats.thisFrame.numTrianglesRejected);
|
||||
p+=sprintf(p,"Triangles Culled: %i\n",stats.thisFrame.numTrianglesCulled);
|
||||
p+=sprintf(p,"Triangles Clipped: %i\n",stats.thisFrame.numTrianglesClipped);
|
||||
p+=sprintf(p,"Triangles Drawn: %i\n",stats.thisFrame.numTrianglesDrawn);
|
||||
|
||||
p+=sprintf(p,"Rasterized Pix: %i\n",stats.thisFrame.rasterizedPixels);
|
||||
p+=sprintf(p,"TEV Pix In: %i\n",stats.thisFrame.tevPixelsIn);
|
||||
p+=sprintf(p,"TEV Pix Out: %i\n",stats.thisFrame.tevPixelsOut);
|
||||
}
|
||||
|
||||
// Render a shadow, and then the text.
|
||||
Renderer::RenderText(debugtext_buffer, 21, 21, 0xDD000000);
|
||||
Renderer::RenderText(debugtext_buffer, 20, 20, 0xFFFFFF00);
|
||||
}
|
||||
|
||||
void Renderer::DrawTexture(u8 *texture, int width, int height)
|
||||
{
|
||||
OpenGL_Update(); // just updates the render window position and the backbuffer size
|
||||
|
||||
GLsizei glWidth = (GLsizei)OpenGL_GetBackbufferWidth();
|
||||
GLsizei glHeight = (GLsizei)OpenGL_GetBackbufferHeight();
|
||||
|
||||
// Update GLViewPort
|
||||
glViewport(0, 0, glWidth, glHeight);
|
||||
glScissor(0, 0, glWidth, glHeight);
|
||||
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, s_RenderTarget);
|
||||
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, (GLsizei)width, (GLsizei)height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture);
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
|
||||
GL_REPORT_ERRORD();
|
||||
|
||||
GLfloat u_max = (GLfloat)width;
|
||||
GLfloat v_max = (GLfloat)glHeight;
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(0, v_max); glVertex2f(-1, -1);
|
||||
glTexCoord2f(0, 0); glVertex2f(-1, 1);
|
||||
glTexCoord2f(u_max, 0); glVertex2f( 1, 1);
|
||||
glTexCoord2f(u_max, v_max); glVertex2f( 1, -1);
|
||||
glEnd();
|
||||
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
|
||||
}
|
||||
|
||||
void Renderer::SwapBuffer()
|
||||
{
|
||||
DrawDebugText();
|
||||
|
||||
glFlush();
|
||||
|
||||
OpenGL_SwapBuffers();
|
||||
|
||||
GL_REPORT_ERRORD();
|
||||
|
||||
stats.ResetFrame();
|
||||
|
||||
// Clear framebuffer
|
||||
glClearColor(0, 0, 0, 0);
|
||||
glClearDepth(1.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
GL_REPORT_ERRORD();
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,37 +1,37 @@
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _RENDERER_H_
|
||||
#define _RENDERER_H_
|
||||
|
||||
#include "pluginspecs_video.h"
|
||||
|
||||
namespace Renderer
|
||||
{
|
||||
void Init(SVideoInitialize *_pVideoInitialize);
|
||||
void Prepare();
|
||||
void Shutdown();
|
||||
|
||||
void RenderText(const char* pstr, int left, int top, u32 color);
|
||||
void DrawDebugText();
|
||||
|
||||
void DrawTexture(u8 *texture, int width, int height);
|
||||
|
||||
void SwapBuffer();
|
||||
}
|
||||
|
||||
#endif
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _RENDERER_H_
|
||||
#define _RENDERER_H_
|
||||
|
||||
#include "pluginspecs_video.h"
|
||||
|
||||
namespace Renderer
|
||||
{
|
||||
void Init(SVideoInitialize *_pVideoInitialize);
|
||||
void Prepare();
|
||||
void Shutdown();
|
||||
|
||||
void RenderText(const char* pstr, int left, int top, u32 color);
|
||||
void DrawDebugText();
|
||||
|
||||
void DrawTexture(u8 *texture, int width, int height);
|
||||
|
||||
void SwapBuffer();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,171 +1,171 @@
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "SetupUnit.h"
|
||||
|
||||
#include "CPMemLoader.h"
|
||||
#include "OpcodeDecoder.h"
|
||||
#include "Statistics.h"
|
||||
#include "Clipper.h"
|
||||
|
||||
|
||||
void SetupUnit::Init(u8 primitiveType)
|
||||
{
|
||||
m_PrimType = primitiveType;
|
||||
|
||||
m_VertexCounter = 0;
|
||||
m_VertPointer[0] = &m_Vertices[0];
|
||||
m_VertPointer[1] = &m_Vertices[1];
|
||||
m_VertPointer[2] = &m_Vertices[2];
|
||||
m_VertWritePointer = m_VertPointer[0];
|
||||
}
|
||||
|
||||
void SetupUnit::SetupVertex()
|
||||
{
|
||||
switch(m_PrimType)
|
||||
{
|
||||
case GX_DRAW_QUADS:
|
||||
SetupQuad();
|
||||
break;
|
||||
case GX_DRAW_TRIANGLES:
|
||||
SetupTriangle();
|
||||
break;
|
||||
case GX_DRAW_TRIANGLE_STRIP:
|
||||
SetupTriStrip();
|
||||
break;
|
||||
case GX_DRAW_TRIANGLE_FAN:
|
||||
SetupTriFan();
|
||||
break;
|
||||
case GX_DRAW_LINES:
|
||||
SetupLine();
|
||||
break;
|
||||
case GX_DRAW_LINE_STRIP:
|
||||
SetupLineStrip();
|
||||
break;
|
||||
case GX_DRAW_POINTS:
|
||||
SetupPoint();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SetupUnit::SetupQuad()
|
||||
{
|
||||
if (m_VertexCounter < 2)
|
||||
{
|
||||
m_VertexCounter++;
|
||||
m_VertWritePointer = m_VertPointer[m_VertexCounter];
|
||||
return;
|
||||
}
|
||||
|
||||
Clipper::ProcessTriangle(m_VertPointer[0], m_VertPointer[1], m_VertPointer[2]);
|
||||
|
||||
m_VertexCounter++;
|
||||
m_VertexCounter &= 3;
|
||||
m_VertWritePointer = &m_Vertices[m_VertexCounter & 1];
|
||||
OutputVertexData* temp = m_VertPointer[1];
|
||||
m_VertPointer[1] = m_VertPointer[2];
|
||||
m_VertPointer[2] = temp;
|
||||
}
|
||||
|
||||
void SetupUnit::SetupTriangle()
|
||||
{
|
||||
if (m_VertexCounter < 2)
|
||||
{
|
||||
m_VertexCounter++;
|
||||
m_VertWritePointer = m_VertPointer[m_VertexCounter];
|
||||
return;
|
||||
}
|
||||
|
||||
Clipper::ProcessTriangle(m_VertPointer[0], m_VertPointer[1], m_VertPointer[2]);
|
||||
|
||||
m_VertexCounter = 0;
|
||||
m_VertWritePointer = m_VertPointer[0];
|
||||
}
|
||||
|
||||
void SetupUnit::SetupTriStrip()
|
||||
{
|
||||
if (m_VertexCounter < 2)
|
||||
{
|
||||
m_VertexCounter++;
|
||||
m_VertWritePointer = m_VertPointer[m_VertexCounter];
|
||||
return;
|
||||
}
|
||||
|
||||
Clipper::ProcessTriangle(m_VertPointer[0], m_VertPointer[1], m_VertPointer[2]);
|
||||
|
||||
m_VertexCounter++;
|
||||
m_VertPointer[2 - (m_VertexCounter & 1)] = m_VertPointer[0];
|
||||
m_VertWritePointer = m_VertPointer[0];
|
||||
|
||||
m_VertPointer[0] = &m_Vertices[(m_VertexCounter + 1) % 3];
|
||||
}
|
||||
|
||||
void SetupUnit::SetupTriFan()
|
||||
{
|
||||
if (m_VertexCounter < 2)
|
||||
{
|
||||
m_VertexCounter++;
|
||||
m_VertWritePointer = m_VertPointer[m_VertexCounter];
|
||||
return;
|
||||
}
|
||||
|
||||
Clipper::ProcessTriangle(m_VertPointer[0], m_VertPointer[1], m_VertPointer[2]);
|
||||
|
||||
m_VertexCounter++;
|
||||
m_VertPointer[1] = m_VertPointer[2];
|
||||
m_VertPointer[2] = &m_Vertices[2 - (m_VertexCounter & 1)];
|
||||
|
||||
m_VertWritePointer = m_VertPointer[2];
|
||||
}
|
||||
|
||||
void SetupUnit::SetupLine()
|
||||
{
|
||||
if (m_VertexCounter < 1)
|
||||
{
|
||||
m_VertexCounter++;
|
||||
m_VertWritePointer = m_VertPointer[m_VertexCounter];
|
||||
return;
|
||||
}
|
||||
|
||||
Clipper::ProcessLine(m_VertPointer[0], m_VertPointer[1]);
|
||||
|
||||
m_VertexCounter = 0;
|
||||
m_VertWritePointer = m_VertPointer[0];
|
||||
}
|
||||
|
||||
void SetupUnit::SetupLineStrip()
|
||||
{
|
||||
if (m_VertexCounter < 1)
|
||||
{
|
||||
m_VertexCounter++;
|
||||
m_VertWritePointer = m_VertPointer[m_VertexCounter];
|
||||
return;
|
||||
}
|
||||
|
||||
m_VertexCounter++;
|
||||
|
||||
Clipper::ProcessLine(m_VertPointer[0], m_VertPointer[1]);
|
||||
|
||||
m_VertWritePointer = m_VertPointer[0];
|
||||
|
||||
m_VertPointer[0] = m_VertPointer[1];
|
||||
m_VertPointer[1] = &m_Vertices[m_VertexCounter & 1];
|
||||
}
|
||||
|
||||
void SetupUnit::SetupPoint()
|
||||
{}
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "SetupUnit.h"
|
||||
|
||||
#include "CPMemLoader.h"
|
||||
#include "OpcodeDecoder.h"
|
||||
#include "Statistics.h"
|
||||
#include "Clipper.h"
|
||||
|
||||
|
||||
void SetupUnit::Init(u8 primitiveType)
|
||||
{
|
||||
m_PrimType = primitiveType;
|
||||
|
||||
m_VertexCounter = 0;
|
||||
m_VertPointer[0] = &m_Vertices[0];
|
||||
m_VertPointer[1] = &m_Vertices[1];
|
||||
m_VertPointer[2] = &m_Vertices[2];
|
||||
m_VertWritePointer = m_VertPointer[0];
|
||||
}
|
||||
|
||||
void SetupUnit::SetupVertex()
|
||||
{
|
||||
switch(m_PrimType)
|
||||
{
|
||||
case GX_DRAW_QUADS:
|
||||
SetupQuad();
|
||||
break;
|
||||
case GX_DRAW_TRIANGLES:
|
||||
SetupTriangle();
|
||||
break;
|
||||
case GX_DRAW_TRIANGLE_STRIP:
|
||||
SetupTriStrip();
|
||||
break;
|
||||
case GX_DRAW_TRIANGLE_FAN:
|
||||
SetupTriFan();
|
||||
break;
|
||||
case GX_DRAW_LINES:
|
||||
SetupLine();
|
||||
break;
|
||||
case GX_DRAW_LINE_STRIP:
|
||||
SetupLineStrip();
|
||||
break;
|
||||
case GX_DRAW_POINTS:
|
||||
SetupPoint();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SetupUnit::SetupQuad()
|
||||
{
|
||||
if (m_VertexCounter < 2)
|
||||
{
|
||||
m_VertexCounter++;
|
||||
m_VertWritePointer = m_VertPointer[m_VertexCounter];
|
||||
return;
|
||||
}
|
||||
|
||||
Clipper::ProcessTriangle(m_VertPointer[0], m_VertPointer[1], m_VertPointer[2]);
|
||||
|
||||
m_VertexCounter++;
|
||||
m_VertexCounter &= 3;
|
||||
m_VertWritePointer = &m_Vertices[m_VertexCounter & 1];
|
||||
OutputVertexData* temp = m_VertPointer[1];
|
||||
m_VertPointer[1] = m_VertPointer[2];
|
||||
m_VertPointer[2] = temp;
|
||||
}
|
||||
|
||||
void SetupUnit::SetupTriangle()
|
||||
{
|
||||
if (m_VertexCounter < 2)
|
||||
{
|
||||
m_VertexCounter++;
|
||||
m_VertWritePointer = m_VertPointer[m_VertexCounter];
|
||||
return;
|
||||
}
|
||||
|
||||
Clipper::ProcessTriangle(m_VertPointer[0], m_VertPointer[1], m_VertPointer[2]);
|
||||
|
||||
m_VertexCounter = 0;
|
||||
m_VertWritePointer = m_VertPointer[0];
|
||||
}
|
||||
|
||||
void SetupUnit::SetupTriStrip()
|
||||
{
|
||||
if (m_VertexCounter < 2)
|
||||
{
|
||||
m_VertexCounter++;
|
||||
m_VertWritePointer = m_VertPointer[m_VertexCounter];
|
||||
return;
|
||||
}
|
||||
|
||||
Clipper::ProcessTriangle(m_VertPointer[0], m_VertPointer[1], m_VertPointer[2]);
|
||||
|
||||
m_VertexCounter++;
|
||||
m_VertPointer[2 - (m_VertexCounter & 1)] = m_VertPointer[0];
|
||||
m_VertWritePointer = m_VertPointer[0];
|
||||
|
||||
m_VertPointer[0] = &m_Vertices[(m_VertexCounter + 1) % 3];
|
||||
}
|
||||
|
||||
void SetupUnit::SetupTriFan()
|
||||
{
|
||||
if (m_VertexCounter < 2)
|
||||
{
|
||||
m_VertexCounter++;
|
||||
m_VertWritePointer = m_VertPointer[m_VertexCounter];
|
||||
return;
|
||||
}
|
||||
|
||||
Clipper::ProcessTriangle(m_VertPointer[0], m_VertPointer[1], m_VertPointer[2]);
|
||||
|
||||
m_VertexCounter++;
|
||||
m_VertPointer[1] = m_VertPointer[2];
|
||||
m_VertPointer[2] = &m_Vertices[2 - (m_VertexCounter & 1)];
|
||||
|
||||
m_VertWritePointer = m_VertPointer[2];
|
||||
}
|
||||
|
||||
void SetupUnit::SetupLine()
|
||||
{
|
||||
if (m_VertexCounter < 1)
|
||||
{
|
||||
m_VertexCounter++;
|
||||
m_VertWritePointer = m_VertPointer[m_VertexCounter];
|
||||
return;
|
||||
}
|
||||
|
||||
Clipper::ProcessLine(m_VertPointer[0], m_VertPointer[1]);
|
||||
|
||||
m_VertexCounter = 0;
|
||||
m_VertWritePointer = m_VertPointer[0];
|
||||
}
|
||||
|
||||
void SetupUnit::SetupLineStrip()
|
||||
{
|
||||
if (m_VertexCounter < 1)
|
||||
{
|
||||
m_VertexCounter++;
|
||||
m_VertWritePointer = m_VertPointer[m_VertexCounter];
|
||||
return;
|
||||
}
|
||||
|
||||
m_VertexCounter++;
|
||||
|
||||
Clipper::ProcessLine(m_VertPointer[0], m_VertPointer[1]);
|
||||
|
||||
m_VertWritePointer = m_VertPointer[0];
|
||||
|
||||
m_VertPointer[0] = m_VertPointer[1];
|
||||
m_VertPointer[1] = &m_Vertices[m_VertexCounter & 1];
|
||||
}
|
||||
|
||||
void SetupUnit::SetupPoint()
|
||||
{}
|
||||
|
@ -1,38 +1,38 @@
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "Statistics.h"
|
||||
|
||||
Statistics stats;
|
||||
|
||||
template <class T>
|
||||
void Xchg(T& a, T&b)
|
||||
{
|
||||
T c = a;
|
||||
a = b;
|
||||
b = c;
|
||||
}
|
||||
|
||||
Statistics::Statistics()
|
||||
{
|
||||
frameCount = 0;
|
||||
}
|
||||
|
||||
void Statistics::ResetFrame()
|
||||
{
|
||||
memset(&thisFrame, 0, sizeof(ThisFrame));
|
||||
}
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "Statistics.h"
|
||||
|
||||
Statistics stats;
|
||||
|
||||
template <class T>
|
||||
void Xchg(T& a, T&b)
|
||||
{
|
||||
T c = a;
|
||||
a = b;
|
||||
b = c;
|
||||
}
|
||||
|
||||
Statistics::Statistics()
|
||||
{
|
||||
frameCount = 0;
|
||||
}
|
||||
|
||||
void Statistics::ResetFrame()
|
||||
{
|
||||
memset(&thisFrame, 0, sizeof(ThisFrame));
|
||||
}
|
||||
|
@ -1,63 +1,63 @@
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "CommonTypes.h"
|
||||
#include "VideoConfig.h"
|
||||
|
||||
#ifndef _STATISTICS_H
|
||||
#define _STATISTICS_H
|
||||
|
||||
struct Statistics
|
||||
{
|
||||
struct ThisFrame
|
||||
{
|
||||
u32 numDrawnObjects;
|
||||
u32 numPrimatives;
|
||||
u32 numVerticesLoaded;
|
||||
u32 numVerticesOut;
|
||||
|
||||
u32 numTrianglesIn;
|
||||
u32 numTrianglesRejected;
|
||||
u32 numTrianglesCulled;
|
||||
u32 numTrianglesClipped;
|
||||
u32 numTrianglesDrawn;
|
||||
|
||||
u32 rasterizedPixels;
|
||||
u32 tevPixelsIn;
|
||||
u32 tevPixelsOut;
|
||||
};
|
||||
|
||||
u32 frameCount;
|
||||
Statistics();
|
||||
|
||||
ThisFrame thisFrame;
|
||||
void ResetFrame();
|
||||
};
|
||||
|
||||
extern Statistics stats;
|
||||
|
||||
#if (STATISTICS)
|
||||
#define INCSTAT(a) (a)++;
|
||||
#define ADDSTAT(a,b) (a)+=(b);
|
||||
#define SETSTAT(a,x) (a)=(int)(x);
|
||||
#else
|
||||
#define INCSTAT(a) ;
|
||||
#define ADDSTAT(a,b) ;
|
||||
#define SETSTAT(a,x) ;
|
||||
#endif
|
||||
|
||||
#endif // _STATISTICS_H
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "CommonTypes.h"
|
||||
#include "VideoConfig.h"
|
||||
|
||||
#ifndef _STATISTICS_H
|
||||
#define _STATISTICS_H
|
||||
|
||||
struct Statistics
|
||||
{
|
||||
struct ThisFrame
|
||||
{
|
||||
u32 numDrawnObjects;
|
||||
u32 numPrimatives;
|
||||
u32 numVerticesLoaded;
|
||||
u32 numVerticesOut;
|
||||
|
||||
u32 numTrianglesIn;
|
||||
u32 numTrianglesRejected;
|
||||
u32 numTrianglesCulled;
|
||||
u32 numTrianglesClipped;
|
||||
u32 numTrianglesDrawn;
|
||||
|
||||
u32 rasterizedPixels;
|
||||
u32 tevPixelsIn;
|
||||
u32 tevPixelsOut;
|
||||
};
|
||||
|
||||
u32 frameCount;
|
||||
Statistics();
|
||||
|
||||
ThisFrame thisFrame;
|
||||
void ResetFrame();
|
||||
};
|
||||
|
||||
extern Statistics stats;
|
||||
|
||||
#if (STATISTICS)
|
||||
#define INCSTAT(a) (a)++;
|
||||
#define ADDSTAT(a,b) (a)+=(b);
|
||||
#define SETSTAT(a,x) (a)=(int)(x);
|
||||
#else
|
||||
#define INCSTAT(a) ;
|
||||
#define ADDSTAT(a,b) ;
|
||||
#define SETSTAT(a,x) ;
|
||||
#endif
|
||||
|
||||
#endif // _STATISTICS_H
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,85 +1,85 @@
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _TEV_H_
|
||||
#define _TEV_H_
|
||||
|
||||
#include "BPMemLoader.h"
|
||||
|
||||
class Tev
|
||||
{
|
||||
struct InputRegType {
|
||||
unsigned a : 8;
|
||||
unsigned b : 8;
|
||||
unsigned c : 8;
|
||||
signed d : 11;
|
||||
};
|
||||
|
||||
struct TextureCoordinateType
|
||||
{
|
||||
signed s : 24;
|
||||
signed t : 24;
|
||||
};
|
||||
|
||||
// color order: RGBA
|
||||
s16 Reg[4][4];
|
||||
s16 KonstantColors[4][4];
|
||||
s16 FixedConstants[9];
|
||||
s16 TexColor[4];
|
||||
s16 RasColor[4];
|
||||
s16 StageKonst[4];
|
||||
s16 Zero16[4];
|
||||
u8 AlphaBump;
|
||||
u8 IndirectTex[4][4];
|
||||
TextureCoordinateType TexCoord;
|
||||
|
||||
s16 *m_ColorInputLUT[16][3];
|
||||
s16 *m_AlphaInputLUT[8]; // values must point to RGBA color
|
||||
s16 *m_KonstLUT[32][4];
|
||||
u8 *m_RasColorLUT[8];
|
||||
s16 m_BiasLUT[4];
|
||||
u8 m_ScaleLShiftLUT[4];
|
||||
u8 m_ScaleRShiftLUT[4];
|
||||
|
||||
void SetRasColor(int colorChan, int swaptable);
|
||||
|
||||
void DrawColorRegular(TevStageCombiner::ColorCombiner &cc);
|
||||
void DrawColorCompare(TevStageCombiner::ColorCombiner &cc);
|
||||
void DrawAlphaRegular(TevStageCombiner::AlphaCombiner &ac);
|
||||
void DrawAlphaCompare(TevStageCombiner::AlphaCombiner &ac);
|
||||
|
||||
void Indirect(unsigned int stageNum, s32 s, s32 t);
|
||||
|
||||
public:
|
||||
s32 Position[3];
|
||||
u8 Color[2][4];
|
||||
TextureCoordinateType Uv[8];
|
||||
s32 IndirectLod[4];
|
||||
bool IndirectLinear[4];
|
||||
s32 TextureLod[16];
|
||||
bool TextureLinear[16];
|
||||
|
||||
void Init();
|
||||
|
||||
void Draw();
|
||||
|
||||
void SetRegColor(int reg, int comp, bool konst, s16 color);
|
||||
|
||||
enum { RED_C, GRN_C, BLU_C, ALP_C };
|
||||
};
|
||||
|
||||
#endif
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _TEV_H_
|
||||
#define _TEV_H_
|
||||
|
||||
#include "BPMemLoader.h"
|
||||
|
||||
class Tev
|
||||
{
|
||||
struct InputRegType {
|
||||
unsigned a : 8;
|
||||
unsigned b : 8;
|
||||
unsigned c : 8;
|
||||
signed d : 11;
|
||||
};
|
||||
|
||||
struct TextureCoordinateType
|
||||
{
|
||||
signed s : 24;
|
||||
signed t : 24;
|
||||
};
|
||||
|
||||
// color order: RGBA
|
||||
s16 Reg[4][4];
|
||||
s16 KonstantColors[4][4];
|
||||
s16 FixedConstants[9];
|
||||
s16 TexColor[4];
|
||||
s16 RasColor[4];
|
||||
s16 StageKonst[4];
|
||||
s16 Zero16[4];
|
||||
u8 AlphaBump;
|
||||
u8 IndirectTex[4][4];
|
||||
TextureCoordinateType TexCoord;
|
||||
|
||||
s16 *m_ColorInputLUT[16][3];
|
||||
s16 *m_AlphaInputLUT[8]; // values must point to RGBA color
|
||||
s16 *m_KonstLUT[32][4];
|
||||
u8 *m_RasColorLUT[8];
|
||||
s16 m_BiasLUT[4];
|
||||
u8 m_ScaleLShiftLUT[4];
|
||||
u8 m_ScaleRShiftLUT[4];
|
||||
|
||||
void SetRasColor(int colorChan, int swaptable);
|
||||
|
||||
void DrawColorRegular(TevStageCombiner::ColorCombiner &cc);
|
||||
void DrawColorCompare(TevStageCombiner::ColorCombiner &cc);
|
||||
void DrawAlphaRegular(TevStageCombiner::AlphaCombiner &ac);
|
||||
void DrawAlphaCompare(TevStageCombiner::AlphaCombiner &ac);
|
||||
|
||||
void Indirect(unsigned int stageNum, s32 s, s32 t);
|
||||
|
||||
public:
|
||||
s32 Position[3];
|
||||
u8 Color[2][4];
|
||||
TextureCoordinateType Uv[8];
|
||||
s32 IndirectLod[4];
|
||||
bool IndirectLinear[4];
|
||||
s32 TextureLod[16];
|
||||
bool TextureLinear[16];
|
||||
|
||||
void Init();
|
||||
|
||||
void Draw();
|
||||
|
||||
void SetRegColor(int reg, int comp, bool konst, s16 color);
|
||||
|
||||
enum { RED_C, GRN_C, BLU_C, ALP_C };
|
||||
};
|
||||
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,216 +1,216 @@
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
|
||||
#include "TextureSampler.h"
|
||||
#include "main.h"
|
||||
|
||||
#include "BPMemLoader.h"
|
||||
#include "../../../Core/VideoCommon/Src/TextureDecoder.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#define ALLOW_MIPMAP 1
|
||||
|
||||
namespace TextureSampler
|
||||
{
|
||||
|
||||
inline void WrapCoord(int &coord, int wrapMode, int imageSize)
|
||||
{
|
||||
switch (wrapMode)
|
||||
{
|
||||
case 0: // clamp
|
||||
coord = (coord>imageSize)?imageSize:(coord<0)?0:coord;
|
||||
break;
|
||||
case 1: // wrap
|
||||
coord = coord % (imageSize + 1);
|
||||
coord = (coord<0)?imageSize+coord:coord;
|
||||
break;
|
||||
case 2: // mirror
|
||||
{
|
||||
int sizePlus1 = imageSize + 1;
|
||||
int div = coord / sizePlus1;
|
||||
coord = coord - (div * sizePlus1);
|
||||
coord = (coord<0)?-coord:coord;
|
||||
coord = (div&1)?imageSize - coord:coord;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
inline void SetTexel(u8 *inTexel, u32 *outTexel, u32 fract)
|
||||
{
|
||||
outTexel[0] = inTexel[0] * fract;
|
||||
outTexel[1] = inTexel[1] * fract;
|
||||
outTexel[2] = inTexel[2] * fract;
|
||||
outTexel[3] = inTexel[3] * fract;
|
||||
}
|
||||
|
||||
inline void AddTexel(u8 *inTexel, u32 *outTexel, u32 fract)
|
||||
{
|
||||
outTexel[0] += inTexel[0] * fract;
|
||||
outTexel[1] += inTexel[1] * fract;
|
||||
outTexel[2] += inTexel[2] * fract;
|
||||
outTexel[3] += inTexel[3] * fract;
|
||||
}
|
||||
|
||||
void Sample(s32 s, s32 t, s32 lod, bool linear, u8 texmap, u8 *sample)
|
||||
{
|
||||
int baseMip = 0;
|
||||
bool mipLinear = false;
|
||||
|
||||
#if (ALLOW_MIPMAP)
|
||||
FourTexUnits& texUnit = bpmem.tex[(texmap >> 2) & 1];
|
||||
TexMode0& tm0 = texUnit.texMode0[texmap & 3];
|
||||
|
||||
s32 lodFract = lod & 0xf;
|
||||
|
||||
if (lod > 0 && tm0.min_filter & 3)
|
||||
{
|
||||
// use mipmap
|
||||
baseMip = lod >> 4;
|
||||
mipLinear = (lodFract && tm0.min_filter & 2);
|
||||
|
||||
// if using nearest mip filter and lodFract >= 0.5 round up to next mip
|
||||
baseMip += (lodFract >> 3) & (tm0.min_filter & 1);
|
||||
}
|
||||
|
||||
if (mipLinear)
|
||||
{
|
||||
u8 sampledTex[4];
|
||||
u32 texel[4];
|
||||
|
||||
SampleMip(s, t, baseMip, linear, texmap, sampledTex);
|
||||
SetTexel(sampledTex, texel, (16 - lodFract));
|
||||
|
||||
SampleMip(s, t, baseMip + 1, linear, texmap, sampledTex);
|
||||
AddTexel(sampledTex, texel, lodFract);
|
||||
|
||||
sample[0] = (u8)(texel[0] >> 4);
|
||||
sample[1] = (u8)(texel[1] >> 4);
|
||||
sample[2] = (u8)(texel[2] >> 4);
|
||||
sample[3] = (u8)(texel[3] >> 4);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
SampleMip(s, t, baseMip, linear, texmap, sample);
|
||||
}
|
||||
}
|
||||
|
||||
void SampleMip(s32 s, s32 t, s32 mip, bool linear, u8 texmap, u8 *sample)
|
||||
{
|
||||
FourTexUnits& texUnit = bpmem.tex[(texmap >> 2) & 1];
|
||||
u8 subTexmap = texmap & 3;
|
||||
|
||||
TexMode0& tm0 = texUnit.texMode0[subTexmap];
|
||||
TexImage0& ti0 = texUnit.texImage0[subTexmap];
|
||||
TexTLUT& texTlut = texUnit.texTlut[subTexmap];
|
||||
|
||||
u32 imageBase = texUnit.texImage3[subTexmap].image_base << 5;
|
||||
u8 *imageSrc = g_VideoInitialize.pGetMemoryPointer(imageBase);
|
||||
|
||||
int imageWidth = ti0.width;
|
||||
int imageHeight = ti0.height;
|
||||
|
||||
int tlutAddress = texTlut.tmem_offset << 9;
|
||||
|
||||
// reduce sample location and texture size to mip level
|
||||
// move texture pointer to mip location
|
||||
if (mip)
|
||||
{
|
||||
int mipWidth = imageWidth + 1;
|
||||
int mipHeight = imageHeight + 1;
|
||||
|
||||
int fmtWidth = TexDecoder_GetBlockWidthInTexels(ti0.format);
|
||||
int fmtHeight = TexDecoder_GetBlockHeightInTexels(ti0.format);
|
||||
int fmtDepth = TexDecoder_GetTexelSizeInNibbles(ti0.format);
|
||||
|
||||
imageWidth >>= mip;
|
||||
imageHeight >>= mip;
|
||||
s >>= mip;
|
||||
t >>= mip;
|
||||
|
||||
while (mip)
|
||||
{
|
||||
mipWidth = max(mipWidth, fmtWidth);
|
||||
mipHeight = max(mipHeight, fmtHeight);
|
||||
u32 size = (mipWidth * mipHeight * fmtDepth) >> 1;
|
||||
|
||||
imageSrc += size;
|
||||
mipWidth >>= 1;
|
||||
mipHeight >>= 1;
|
||||
mip--;
|
||||
}
|
||||
}
|
||||
|
||||
if (linear)
|
||||
{
|
||||
// offset linear sampling
|
||||
s -= 64;
|
||||
t -= 64;
|
||||
|
||||
// integer part of sample location
|
||||
int imageS = s >> 7;
|
||||
int imageT = t >> 7;
|
||||
|
||||
// linear sampling
|
||||
int imageSPlus1 = imageS + 1;
|
||||
int fractS = s & 0x7f;
|
||||
|
||||
int imageTPlus1 = imageT + 1;
|
||||
int fractT = t & 0x7f;
|
||||
|
||||
u8 sampledTex[4];
|
||||
u32 texel[4];
|
||||
|
||||
WrapCoord(imageS, tm0.wrap_s, imageWidth);
|
||||
WrapCoord(imageT, tm0.wrap_t, imageHeight);
|
||||
WrapCoord(imageSPlus1, tm0.wrap_s, imageWidth);
|
||||
WrapCoord(imageTPlus1, tm0.wrap_t, imageHeight);
|
||||
|
||||
TexDecoder_DecodeTexel(sampledTex, imageSrc, imageS, imageT, imageWidth, ti0.format, tlutAddress, texTlut.tlut_format);
|
||||
SetTexel(sampledTex, texel, (128 - fractS) * (128 - fractT));
|
||||
|
||||
TexDecoder_DecodeTexel(sampledTex, imageSrc, imageSPlus1, imageT, imageWidth, ti0.format, tlutAddress, texTlut.tlut_format);
|
||||
AddTexel(sampledTex, texel, (fractS) * (128 - fractT));
|
||||
|
||||
TexDecoder_DecodeTexel(sampledTex, imageSrc, imageS, imageTPlus1, imageWidth, ti0.format, tlutAddress, texTlut.tlut_format);
|
||||
AddTexel(sampledTex, texel, (128 - fractS) * (fractT));
|
||||
|
||||
TexDecoder_DecodeTexel(sampledTex, imageSrc, imageSPlus1, imageTPlus1, imageWidth, ti0.format, tlutAddress, texTlut.tlut_format);
|
||||
AddTexel(sampledTex, texel, (fractS) * (fractT));
|
||||
|
||||
sample[0] = (u8)(texel[0] >> 14);
|
||||
sample[1] = (u8)(texel[1] >> 14);
|
||||
sample[2] = (u8)(texel[2] >> 14);
|
||||
sample[3] = (u8)(texel[3] >> 14);
|
||||
}
|
||||
else
|
||||
{
|
||||
// integer part of sample location
|
||||
int imageS = s >> 7;
|
||||
int imageT = t >> 7;
|
||||
|
||||
// nearest neighbor sampling
|
||||
WrapCoord(imageS, tm0.wrap_s, imageWidth);
|
||||
WrapCoord(imageT, tm0.wrap_t, imageHeight);
|
||||
|
||||
TexDecoder_DecodeTexel(sample, imageSrc, imageS, imageT, imageWidth, ti0.format, tlutAddress, texTlut.tlut_format);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
|
||||
#include "TextureSampler.h"
|
||||
#include "main.h"
|
||||
|
||||
#include "BPMemLoader.h"
|
||||
#include "../../../Core/VideoCommon/Src/TextureDecoder.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#define ALLOW_MIPMAP 1
|
||||
|
||||
namespace TextureSampler
|
||||
{
|
||||
|
||||
inline void WrapCoord(int &coord, int wrapMode, int imageSize)
|
||||
{
|
||||
switch (wrapMode)
|
||||
{
|
||||
case 0: // clamp
|
||||
coord = (coord>imageSize)?imageSize:(coord<0)?0:coord;
|
||||
break;
|
||||
case 1: // wrap
|
||||
coord = coord % (imageSize + 1);
|
||||
coord = (coord<0)?imageSize+coord:coord;
|
||||
break;
|
||||
case 2: // mirror
|
||||
{
|
||||
int sizePlus1 = imageSize + 1;
|
||||
int div = coord / sizePlus1;
|
||||
coord = coord - (div * sizePlus1);
|
||||
coord = (coord<0)?-coord:coord;
|
||||
coord = (div&1)?imageSize - coord:coord;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
inline void SetTexel(u8 *inTexel, u32 *outTexel, u32 fract)
|
||||
{
|
||||
outTexel[0] = inTexel[0] * fract;
|
||||
outTexel[1] = inTexel[1] * fract;
|
||||
outTexel[2] = inTexel[2] * fract;
|
||||
outTexel[3] = inTexel[3] * fract;
|
||||
}
|
||||
|
||||
inline void AddTexel(u8 *inTexel, u32 *outTexel, u32 fract)
|
||||
{
|
||||
outTexel[0] += inTexel[0] * fract;
|
||||
outTexel[1] += inTexel[1] * fract;
|
||||
outTexel[2] += inTexel[2] * fract;
|
||||
outTexel[3] += inTexel[3] * fract;
|
||||
}
|
||||
|
||||
void Sample(s32 s, s32 t, s32 lod, bool linear, u8 texmap, u8 *sample)
|
||||
{
|
||||
int baseMip = 0;
|
||||
bool mipLinear = false;
|
||||
|
||||
#if (ALLOW_MIPMAP)
|
||||
FourTexUnits& texUnit = bpmem.tex[(texmap >> 2) & 1];
|
||||
TexMode0& tm0 = texUnit.texMode0[texmap & 3];
|
||||
|
||||
s32 lodFract = lod & 0xf;
|
||||
|
||||
if (lod > 0 && tm0.min_filter & 3)
|
||||
{
|
||||
// use mipmap
|
||||
baseMip = lod >> 4;
|
||||
mipLinear = (lodFract && tm0.min_filter & 2);
|
||||
|
||||
// if using nearest mip filter and lodFract >= 0.5 round up to next mip
|
||||
baseMip += (lodFract >> 3) & (tm0.min_filter & 1);
|
||||
}
|
||||
|
||||
if (mipLinear)
|
||||
{
|
||||
u8 sampledTex[4];
|
||||
u32 texel[4];
|
||||
|
||||
SampleMip(s, t, baseMip, linear, texmap, sampledTex);
|
||||
SetTexel(sampledTex, texel, (16 - lodFract));
|
||||
|
||||
SampleMip(s, t, baseMip + 1, linear, texmap, sampledTex);
|
||||
AddTexel(sampledTex, texel, lodFract);
|
||||
|
||||
sample[0] = (u8)(texel[0] >> 4);
|
||||
sample[1] = (u8)(texel[1] >> 4);
|
||||
sample[2] = (u8)(texel[2] >> 4);
|
||||
sample[3] = (u8)(texel[3] >> 4);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
SampleMip(s, t, baseMip, linear, texmap, sample);
|
||||
}
|
||||
}
|
||||
|
||||
void SampleMip(s32 s, s32 t, s32 mip, bool linear, u8 texmap, u8 *sample)
|
||||
{
|
||||
FourTexUnits& texUnit = bpmem.tex[(texmap >> 2) & 1];
|
||||
u8 subTexmap = texmap & 3;
|
||||
|
||||
TexMode0& tm0 = texUnit.texMode0[subTexmap];
|
||||
TexImage0& ti0 = texUnit.texImage0[subTexmap];
|
||||
TexTLUT& texTlut = texUnit.texTlut[subTexmap];
|
||||
|
||||
u32 imageBase = texUnit.texImage3[subTexmap].image_base << 5;
|
||||
u8 *imageSrc = g_VideoInitialize.pGetMemoryPointer(imageBase);
|
||||
|
||||
int imageWidth = ti0.width;
|
||||
int imageHeight = ti0.height;
|
||||
|
||||
int tlutAddress = texTlut.tmem_offset << 9;
|
||||
|
||||
// reduce sample location and texture size to mip level
|
||||
// move texture pointer to mip location
|
||||
if (mip)
|
||||
{
|
||||
int mipWidth = imageWidth + 1;
|
||||
int mipHeight = imageHeight + 1;
|
||||
|
||||
int fmtWidth = TexDecoder_GetBlockWidthInTexels(ti0.format);
|
||||
int fmtHeight = TexDecoder_GetBlockHeightInTexels(ti0.format);
|
||||
int fmtDepth = TexDecoder_GetTexelSizeInNibbles(ti0.format);
|
||||
|
||||
imageWidth >>= mip;
|
||||
imageHeight >>= mip;
|
||||
s >>= mip;
|
||||
t >>= mip;
|
||||
|
||||
while (mip)
|
||||
{
|
||||
mipWidth = max(mipWidth, fmtWidth);
|
||||
mipHeight = max(mipHeight, fmtHeight);
|
||||
u32 size = (mipWidth * mipHeight * fmtDepth) >> 1;
|
||||
|
||||
imageSrc += size;
|
||||
mipWidth >>= 1;
|
||||
mipHeight >>= 1;
|
||||
mip--;
|
||||
}
|
||||
}
|
||||
|
||||
if (linear)
|
||||
{
|
||||
// offset linear sampling
|
||||
s -= 64;
|
||||
t -= 64;
|
||||
|
||||
// integer part of sample location
|
||||
int imageS = s >> 7;
|
||||
int imageT = t >> 7;
|
||||
|
||||
// linear sampling
|
||||
int imageSPlus1 = imageS + 1;
|
||||
int fractS = s & 0x7f;
|
||||
|
||||
int imageTPlus1 = imageT + 1;
|
||||
int fractT = t & 0x7f;
|
||||
|
||||
u8 sampledTex[4];
|
||||
u32 texel[4];
|
||||
|
||||
WrapCoord(imageS, tm0.wrap_s, imageWidth);
|
||||
WrapCoord(imageT, tm0.wrap_t, imageHeight);
|
||||
WrapCoord(imageSPlus1, tm0.wrap_s, imageWidth);
|
||||
WrapCoord(imageTPlus1, tm0.wrap_t, imageHeight);
|
||||
|
||||
TexDecoder_DecodeTexel(sampledTex, imageSrc, imageS, imageT, imageWidth, ti0.format, tlutAddress, texTlut.tlut_format);
|
||||
SetTexel(sampledTex, texel, (128 - fractS) * (128 - fractT));
|
||||
|
||||
TexDecoder_DecodeTexel(sampledTex, imageSrc, imageSPlus1, imageT, imageWidth, ti0.format, tlutAddress, texTlut.tlut_format);
|
||||
AddTexel(sampledTex, texel, (fractS) * (128 - fractT));
|
||||
|
||||
TexDecoder_DecodeTexel(sampledTex, imageSrc, imageS, imageTPlus1, imageWidth, ti0.format, tlutAddress, texTlut.tlut_format);
|
||||
AddTexel(sampledTex, texel, (128 - fractS) * (fractT));
|
||||
|
||||
TexDecoder_DecodeTexel(sampledTex, imageSrc, imageSPlus1, imageTPlus1, imageWidth, ti0.format, tlutAddress, texTlut.tlut_format);
|
||||
AddTexel(sampledTex, texel, (fractS) * (fractT));
|
||||
|
||||
sample[0] = (u8)(texel[0] >> 14);
|
||||
sample[1] = (u8)(texel[1] >> 14);
|
||||
sample[2] = (u8)(texel[2] >> 14);
|
||||
sample[3] = (u8)(texel[3] >> 14);
|
||||
}
|
||||
else
|
||||
{
|
||||
// integer part of sample location
|
||||
int imageS = s >> 7;
|
||||
int imageT = t >> 7;
|
||||
|
||||
// nearest neighbor sampling
|
||||
WrapCoord(imageS, tm0.wrap_s, imageWidth);
|
||||
WrapCoord(imageT, tm0.wrap_t, imageHeight);
|
||||
|
||||
TexDecoder_DecodeTexel(sample, imageSrc, imageS, imageT, imageWidth, ti0.format, tlutAddress, texTlut.tlut_format);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,344 +1,344 @@
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
#include "VertexLoader.h"
|
||||
#include "VertexLoader_Position.h"
|
||||
#include "../../../Core/VideoCommon/Src/VertexLoader_Normal.h"
|
||||
#include "../../../Core/VideoCommon/Src/VertexLoader_Color.h"
|
||||
#include "../../../Core/VideoCommon/Src/VertexLoader_TextCoord.h"
|
||||
|
||||
#include "CPMemLoader.h"
|
||||
#include "XFMemLoader.h"
|
||||
|
||||
#include "TransformUnit.h"
|
||||
#include "SetupUnit.h"
|
||||
#include "Statistics.h"
|
||||
#include "NativeVertexWriter.h"
|
||||
#include "VertexFormatConverter.h"
|
||||
#include "../../../Core/VideoCommon/Src/DataReader.h"
|
||||
|
||||
// Vertex loaders read these
|
||||
int tcIndex;
|
||||
int colIndex;
|
||||
int colElements[2];
|
||||
float posScale;
|
||||
float tcScale[8];
|
||||
|
||||
|
||||
VertexLoader::VertexLoader() :
|
||||
m_VertexSize(0),
|
||||
m_NumAttributeLoaders(0)
|
||||
{
|
||||
VertexLoader_Normal::Init();
|
||||
VertexLoader_Position::Init();
|
||||
VertexLoader_TextCoord::Init();
|
||||
|
||||
m_SetupUnit = new SetupUnit;
|
||||
}
|
||||
|
||||
VertexLoader::~VertexLoader()
|
||||
{
|
||||
delete m_SetupUnit;
|
||||
m_SetupUnit = NULL;
|
||||
}
|
||||
|
||||
void VertexLoader::SetFormat(u8 attributeIndex, u8 primitiveType)
|
||||
{
|
||||
m_CurrentVat = &g_VtxAttr[attributeIndex];
|
||||
|
||||
posScale = 1.0f / float(1 << m_CurrentVat->g0.PosFrac);
|
||||
tcScale[0] = 1.0f / float(1 << m_CurrentVat->g0.Tex0Frac);
|
||||
tcScale[1] = 1.0f / float(1 << m_CurrentVat->g1.Tex1Frac);
|
||||
tcScale[2] = 1.0f / float(1 << m_CurrentVat->g1.Tex2Frac);
|
||||
tcScale[3] = 1.0f / float(1 << m_CurrentVat->g1.Tex3Frac);
|
||||
tcScale[4] = 1.0f / float(1 << m_CurrentVat->g2.Tex4Frac);
|
||||
tcScale[5] = 1.0f / float(1 << m_CurrentVat->g2.Tex5Frac);
|
||||
tcScale[6] = 1.0f / float(1 << m_CurrentVat->g2.Tex6Frac);
|
||||
tcScale[7] = 1.0f / float(1 << m_CurrentVat->g2.Tex7Frac);
|
||||
|
||||
//TexMtx
|
||||
const int tmDesc[8] = {
|
||||
g_VtxDesc.Tex0MatIdx, g_VtxDesc.Tex1MatIdx, g_VtxDesc.Tex2MatIdx, g_VtxDesc.Tex3MatIdx,
|
||||
g_VtxDesc.Tex4MatIdx, g_VtxDesc.Tex5MatIdx, g_VtxDesc.Tex6MatIdx, g_VtxDesc.Tex7MatIdx
|
||||
};
|
||||
// Colors
|
||||
const int colDesc[2] = {g_VtxDesc.Color0, g_VtxDesc.Color1};
|
||||
colElements[0] = m_CurrentVat->g0.Color0Elements;
|
||||
colElements[1] = m_CurrentVat->g0.Color1Elements;
|
||||
const int colComp[2] = {m_CurrentVat->g0.Color0Comp, m_CurrentVat->g0.Color1Comp};
|
||||
// TextureCoord
|
||||
const int tcDesc[8] = {
|
||||
g_VtxDesc.Tex0Coord, g_VtxDesc.Tex1Coord, g_VtxDesc.Tex2Coord, g_VtxDesc.Tex3Coord,
|
||||
g_VtxDesc.Tex4Coord, g_VtxDesc.Tex5Coord, g_VtxDesc.Tex6Coord, (g_VtxDesc.Hex >> 31) & 3
|
||||
};
|
||||
const int tcElements[8] = {
|
||||
m_CurrentVat->g0.Tex0CoordElements, m_CurrentVat->g1.Tex1CoordElements, m_CurrentVat->g1.Tex2CoordElements,
|
||||
m_CurrentVat->g1.Tex3CoordElements, m_CurrentVat->g1.Tex4CoordElements, m_CurrentVat->g2.Tex5CoordElements,
|
||||
m_CurrentVat->g2.Tex6CoordElements, m_CurrentVat->g2.Tex7CoordElements
|
||||
};
|
||||
|
||||
const int tcFormat[8] = {
|
||||
m_CurrentVat->g0.Tex0CoordFormat, m_CurrentVat->g1.Tex1CoordFormat, m_CurrentVat->g1.Tex2CoordFormat,
|
||||
m_CurrentVat->g1.Tex3CoordFormat, m_CurrentVat->g1.Tex4CoordFormat, m_CurrentVat->g2.Tex5CoordFormat,
|
||||
m_CurrentVat->g2.Tex6CoordFormat, m_CurrentVat->g2.Tex7CoordFormat
|
||||
};
|
||||
|
||||
m_VertexSize = 0;
|
||||
|
||||
// Reset pipeline
|
||||
m_positionLoader = NULL;
|
||||
m_normalLoader = NULL;
|
||||
m_NumAttributeLoaders = 0;
|
||||
|
||||
// Reset vertex
|
||||
// matrix index from xfregs or cp memory?
|
||||
_assert_msg_(VIDEO, xfregs.MatrixIndexA.PosNormalMtxIdx == MatrixIndexA.PosNormalMtxIdx, "Matrix indices don't match");
|
||||
//_assert_msg_(VIDEO, xfregs.MatrixIndexA.Tex0MtxIdx == MatrixIndexA.Tex0MtxIdx, "Matrix indices don't match");
|
||||
//_assert_msg_(VIDEO, xfregs.MatrixIndexA.Tex1MtxIdx == MatrixIndexA.Tex1MtxIdx, "Matrix indices don't match");
|
||||
_assert_msg_(VIDEO, xfregs.MatrixIndexA.Tex2MtxIdx == MatrixIndexA.Tex2MtxIdx, "Matrix indices don't match");
|
||||
_assert_msg_(VIDEO, xfregs.MatrixIndexA.Tex3MtxIdx == MatrixIndexA.Tex3MtxIdx, "Matrix indices don't match");
|
||||
_assert_msg_(VIDEO, xfregs.MatrixIndexB.Tex4MtxIdx == MatrixIndexB.Tex4MtxIdx, "Matrix indices don't match");
|
||||
_assert_msg_(VIDEO, xfregs.MatrixIndexB.Tex5MtxIdx == MatrixIndexB.Tex5MtxIdx, "Matrix indices don't match");
|
||||
_assert_msg_(VIDEO, xfregs.MatrixIndexB.Tex6MtxIdx == MatrixIndexB.Tex6MtxIdx, "Matrix indices don't match");
|
||||
_assert_msg_(VIDEO, xfregs.MatrixIndexB.Tex7MtxIdx == MatrixIndexB.Tex7MtxIdx, "Matrix indices don't match");
|
||||
m_Vertex.posMtx = xfregs.MatrixIndexA.PosNormalMtxIdx;
|
||||
m_Vertex.texMtx[0] = xfregs.MatrixIndexA.Tex0MtxIdx;
|
||||
m_Vertex.texMtx[1] = xfregs.MatrixIndexA.Tex1MtxIdx;
|
||||
m_Vertex.texMtx[2] = xfregs.MatrixIndexA.Tex2MtxIdx;
|
||||
m_Vertex.texMtx[3] = xfregs.MatrixIndexA.Tex3MtxIdx;
|
||||
m_Vertex.texMtx[4] = xfregs.MatrixIndexB.Tex4MtxIdx;
|
||||
m_Vertex.texMtx[5] = xfregs.MatrixIndexB.Tex5MtxIdx;
|
||||
m_Vertex.texMtx[6] = xfregs.MatrixIndexB.Tex6MtxIdx;
|
||||
m_Vertex.texMtx[7] = xfregs.MatrixIndexB.Tex7MtxIdx;
|
||||
/*m_Vertex.posMtx = MatrixIndexA.PosNormalMtxIdx;
|
||||
m_Vertex.texMtx[0] = MatrixIndexA.Tex0MtxIdx;
|
||||
m_Vertex.texMtx[1] = MatrixIndexA.Tex1MtxIdx;
|
||||
m_Vertex.texMtx[2] = MatrixIndexA.Tex2MtxIdx;
|
||||
m_Vertex.texMtx[3] = MatrixIndexA.Tex3MtxIdx;
|
||||
m_Vertex.texMtx[4] = MatrixIndexB.Tex4MtxIdx;
|
||||
m_Vertex.texMtx[5] = MatrixIndexB.Tex5MtxIdx;
|
||||
m_Vertex.texMtx[6] = MatrixIndexB.Tex6MtxIdx;
|
||||
m_Vertex.texMtx[7] = MatrixIndexB.Tex7MtxIdx;*/
|
||||
|
||||
if (g_VtxDesc.PosMatIdx != NOT_PRESENT) {
|
||||
AddAttributeLoader(LoadPosMtx);
|
||||
m_VertexSize++;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
if (tmDesc[i] != NOT_PRESENT)
|
||||
{
|
||||
AddAttributeLoader(LoadTexMtx, i);
|
||||
m_VertexSize++;
|
||||
}
|
||||
}
|
||||
|
||||
// Write vertex position loader
|
||||
m_positionLoader = VertexLoader_Position::GetFunction(g_VtxDesc.Position, m_CurrentVat->g0.PosFormat, m_CurrentVat->g0.PosElements);
|
||||
m_VertexSize += VertexLoader_Position::GetSize(g_VtxDesc.Position, m_CurrentVat->g0.PosFormat, m_CurrentVat->g0.PosElements);
|
||||
AddAttributeLoader(LoadPosition);
|
||||
|
||||
// Normals
|
||||
if (g_VtxDesc.Normal != NOT_PRESENT) {
|
||||
m_VertexSize += VertexLoader_Normal::GetSize(g_VtxDesc.Normal, m_CurrentVat->g0.NormalFormat, m_CurrentVat->g0.NormalElements, m_CurrentVat->g0.NormalIndex3);
|
||||
m_normalLoader = VertexLoader_Normal::GetFunction(g_VtxDesc.Normal, m_CurrentVat->g0.NormalFormat, m_CurrentVat->g0.NormalElements, m_CurrentVat->g0.NormalIndex3, true);
|
||||
if (m_normalLoader == 0)
|
||||
{
|
||||
ERROR_LOG(VIDEO, "VertexLoader_Normal::GetFunction returned zero!");
|
||||
}
|
||||
AddAttributeLoader(LoadNormal);
|
||||
|
||||
switch (m_CurrentVat->g0.NormalFormat) {
|
||||
case FORMAT_UBYTE:
|
||||
case FORMAT_BYTE:
|
||||
if (m_CurrentVat->g0.NormalElements)
|
||||
m_normalConverter = VertexFormatConverter::LoadNormal3_Byte;
|
||||
else
|
||||
m_normalConverter = VertexFormatConverter::LoadNormal1_Byte;
|
||||
break;
|
||||
case FORMAT_USHORT:
|
||||
case FORMAT_SHORT:
|
||||
if (m_CurrentVat->g0.NormalElements)
|
||||
m_normalConverter = VertexFormatConverter::LoadNormal3_Short;
|
||||
else
|
||||
m_normalConverter = VertexFormatConverter::LoadNormal1_Short;
|
||||
break;
|
||||
case FORMAT_FLOAT:
|
||||
if (m_CurrentVat->g0.NormalElements)
|
||||
m_normalConverter = VertexFormatConverter::LoadNormal3_Float;
|
||||
else
|
||||
m_normalConverter = VertexFormatConverter::LoadNormal1_Float;
|
||||
break;
|
||||
default: _assert_(0); break;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
switch (colDesc[i])
|
||||
{
|
||||
case NOT_PRESENT:
|
||||
m_colorLoader[i] = NULL;
|
||||
break;
|
||||
case DIRECT:
|
||||
switch (colComp[i])
|
||||
{
|
||||
case FORMAT_16B_565: m_VertexSize += 2; m_colorLoader[i] = (Color_ReadDirect_16b_565); break;
|
||||
case FORMAT_24B_888: m_VertexSize += 3; m_colorLoader[i] = (Color_ReadDirect_24b_888); break;
|
||||
case FORMAT_32B_888x: m_VertexSize += 4; m_colorLoader[i] = (Color_ReadDirect_32b_888x); break;
|
||||
case FORMAT_16B_4444: m_VertexSize += 2; m_colorLoader[i] = (Color_ReadDirect_16b_4444); break;
|
||||
case FORMAT_24B_6666: m_VertexSize += 3; m_colorLoader[i] = (Color_ReadDirect_24b_6666); break;
|
||||
case FORMAT_32B_8888: m_VertexSize += 4; m_colorLoader[i] = (Color_ReadDirect_32b_8888); break;
|
||||
default: _assert_(0); break;
|
||||
}
|
||||
AddAttributeLoader(LoadColor, i);
|
||||
break;
|
||||
case INDEX8:
|
||||
m_VertexSize += 1;
|
||||
switch (colComp[i])
|
||||
{
|
||||
case FORMAT_16B_565: m_colorLoader[i] = (Color_ReadIndex8_16b_565); break;
|
||||
case FORMAT_24B_888: m_colorLoader[i] = (Color_ReadIndex8_24b_888); break;
|
||||
case FORMAT_32B_888x: m_colorLoader[i] = (Color_ReadIndex8_32b_888x); break;
|
||||
case FORMAT_16B_4444: m_colorLoader[i] = (Color_ReadIndex8_16b_4444); break;
|
||||
case FORMAT_24B_6666: m_colorLoader[i] = (Color_ReadIndex8_24b_6666); break;
|
||||
case FORMAT_32B_8888: m_colorLoader[i] = (Color_ReadIndex8_32b_8888); break;
|
||||
default: _assert_(0); break;
|
||||
}
|
||||
AddAttributeLoader(LoadColor, i);
|
||||
break;
|
||||
case INDEX16:
|
||||
m_VertexSize += 2;
|
||||
switch (colComp[i])
|
||||
{
|
||||
case FORMAT_16B_565: m_colorLoader[i] = (Color_ReadIndex16_16b_565); break;
|
||||
case FORMAT_24B_888: m_colorLoader[i] = (Color_ReadIndex16_24b_888); break;
|
||||
case FORMAT_32B_888x: m_colorLoader[i] = (Color_ReadIndex16_32b_888x); break;
|
||||
case FORMAT_16B_4444: m_colorLoader[i] = (Color_ReadIndex16_16b_4444); break;
|
||||
case FORMAT_24B_6666: m_colorLoader[i] = (Color_ReadIndex16_24b_6666); break;
|
||||
case FORMAT_32B_8888: m_colorLoader[i] = (Color_ReadIndex16_32b_8888); break;
|
||||
default: _assert_(0); break;
|
||||
}
|
||||
AddAttributeLoader(LoadColor, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Texture matrix indices (remove if corresponding texture coordinate isn't enabled)
|
||||
for (int i = 0; i < 8; i++) {
|
||||
const int desc = tcDesc[i];
|
||||
const int format = tcFormat[i];
|
||||
const int elements = tcElements[i];
|
||||
_assert_msg_(VIDEO, NOT_PRESENT <= desc && desc <= INDEX16, "Invalid texture coordinates description!\n(desc = %d)", desc);
|
||||
_assert_msg_(VIDEO, FORMAT_UBYTE <= format && format <= FORMAT_FLOAT, "Invalid texture coordinates format!\n(format = %d)", format);
|
||||
_assert_msg_(VIDEO, 0 <= elements && elements <= 1, "Invalid number of texture coordinates elemnts!\n(elements = %d)", elements);
|
||||
|
||||
m_texCoordLoader[i] = VertexLoader_TextCoord::GetFunction(desc, format, elements);
|
||||
m_VertexSize += VertexLoader_TextCoord::GetSize(desc, format, elements);
|
||||
if (m_texCoordLoader[i])
|
||||
AddAttributeLoader(LoadTexCoord, i);
|
||||
}
|
||||
|
||||
// special case if only pos and tex coord 0 and tex coord input is AB11
|
||||
m_TexGenSpecialCase =
|
||||
((g_VtxDesc.Hex & 0x60600L) == g_VtxDesc.Hex) && // only pos and tex coord 0
|
||||
(g_VtxDesc.Tex0Coord != NOT_PRESENT) &&
|
||||
(xfregs.texMtxInfo[0].inputform == XF_TEXINPUT_AB11);
|
||||
|
||||
|
||||
m_SetupUnit->Init(primitiveType);
|
||||
}
|
||||
|
||||
|
||||
void VertexLoader::LoadVertex()
|
||||
{
|
||||
for (int i = 0; i < m_NumAttributeLoaders; i++)
|
||||
m_AttributeLoaders[i].loader(this, &m_Vertex, m_AttributeLoaders[i].index);
|
||||
|
||||
OutputVertexData* outVertex = m_SetupUnit->GetVertex();
|
||||
|
||||
// transform input data
|
||||
TransformUnit::TransformPosition(&m_Vertex, outVertex);
|
||||
|
||||
if (g_VtxDesc.Normal != NOT_PRESENT)
|
||||
{
|
||||
TransformUnit::TransformNormal(&m_Vertex, m_CurrentVat->g0.NormalElements, outVertex);
|
||||
}
|
||||
|
||||
TransformUnit::TransformColor(&m_Vertex, outVertex);
|
||||
|
||||
TransformUnit::TransformTexCoord(&m_Vertex, outVertex, m_TexGenSpecialCase);
|
||||
|
||||
m_SetupUnit->SetupVertex();
|
||||
|
||||
INCSTAT(stats.thisFrame.numVerticesLoaded)
|
||||
}
|
||||
|
||||
void VertexLoader::AddAttributeLoader(AttributeLoader loader, u8 index)
|
||||
{
|
||||
_assert_msg_(VIDEO, m_NumAttributeLoaders < 21, "Too many attribute loaders");
|
||||
m_AttributeLoaders[m_NumAttributeLoaders].loader = loader;
|
||||
m_AttributeLoaders[m_NumAttributeLoaders++].index = index;
|
||||
}
|
||||
|
||||
void VertexLoader::LoadPosMtx(VertexLoader *vertexLoader, InputVertexData *vertex, u8 unused)
|
||||
{
|
||||
vertex->posMtx = DataReadU8() & 0x3f;
|
||||
}
|
||||
|
||||
void VertexLoader::LoadTexMtx(VertexLoader *vertexLoader, InputVertexData *vertex, u8 index)
|
||||
{
|
||||
vertex->texMtx[index] = DataReadU8() & 0x3f;
|
||||
}
|
||||
|
||||
void VertexLoader::LoadPosition(VertexLoader *vertexLoader, InputVertexData *vertex, u8 unused)
|
||||
{
|
||||
VertexManager::s_pCurBufferPointer = (u8*)&vertex->position;
|
||||
vertexLoader->m_positionLoader();
|
||||
}
|
||||
|
||||
void VertexLoader::LoadNormal(VertexLoader *vertexLoader, InputVertexData *vertex, u8 unused)
|
||||
{
|
||||
u8 buffer[3*3*4];
|
||||
|
||||
VertexManager::s_pCurBufferPointer = buffer;
|
||||
vertexLoader->m_normalLoader();
|
||||
|
||||
// the common vertex loader loads data as bytes, shorts or floats so an extra step is needed to make it floats
|
||||
vertexLoader->m_normalConverter(vertex, buffer);
|
||||
}
|
||||
|
||||
void VertexLoader::LoadColor(VertexLoader *vertexLoader, InputVertexData *vertex, u8 index)
|
||||
{
|
||||
u32 color;
|
||||
VertexManager::s_pCurBufferPointer = (u8*)&color;
|
||||
colIndex = index;
|
||||
vertexLoader->m_colorLoader[index]();
|
||||
|
||||
// rgba -> abgr
|
||||
*(u32*)vertex->color[index] = Common::swap32(color);
|
||||
}
|
||||
|
||||
void VertexLoader::LoadTexCoord(VertexLoader *vertexLoader, InputVertexData *vertex, u8 index)
|
||||
{
|
||||
VertexManager::s_pCurBufferPointer = (u8*)&vertex->texCoords[index];
|
||||
tcIndex = index;
|
||||
vertexLoader->m_texCoordLoader[index]();
|
||||
}
|
||||
|
||||
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
#include "VertexLoader.h"
|
||||
#include "VertexLoader_Position.h"
|
||||
#include "../../../Core/VideoCommon/Src/VertexLoader_Normal.h"
|
||||
#include "../../../Core/VideoCommon/Src/VertexLoader_Color.h"
|
||||
#include "../../../Core/VideoCommon/Src/VertexLoader_TextCoord.h"
|
||||
|
||||
#include "CPMemLoader.h"
|
||||
#include "XFMemLoader.h"
|
||||
|
||||
#include "TransformUnit.h"
|
||||
#include "SetupUnit.h"
|
||||
#include "Statistics.h"
|
||||
#include "NativeVertexWriter.h"
|
||||
#include "VertexFormatConverter.h"
|
||||
#include "../../../Core/VideoCommon/Src/DataReader.h"
|
||||
|
||||
// Vertex loaders read these
|
||||
int tcIndex;
|
||||
int colIndex;
|
||||
int colElements[2];
|
||||
float posScale;
|
||||
float tcScale[8];
|
||||
|
||||
|
||||
VertexLoader::VertexLoader() :
|
||||
m_VertexSize(0),
|
||||
m_NumAttributeLoaders(0)
|
||||
{
|
||||
VertexLoader_Normal::Init();
|
||||
VertexLoader_Position::Init();
|
||||
VertexLoader_TextCoord::Init();
|
||||
|
||||
m_SetupUnit = new SetupUnit;
|
||||
}
|
||||
|
||||
VertexLoader::~VertexLoader()
|
||||
{
|
||||
delete m_SetupUnit;
|
||||
m_SetupUnit = NULL;
|
||||
}
|
||||
|
||||
void VertexLoader::SetFormat(u8 attributeIndex, u8 primitiveType)
|
||||
{
|
||||
m_CurrentVat = &g_VtxAttr[attributeIndex];
|
||||
|
||||
posScale = 1.0f / float(1 << m_CurrentVat->g0.PosFrac);
|
||||
tcScale[0] = 1.0f / float(1 << m_CurrentVat->g0.Tex0Frac);
|
||||
tcScale[1] = 1.0f / float(1 << m_CurrentVat->g1.Tex1Frac);
|
||||
tcScale[2] = 1.0f / float(1 << m_CurrentVat->g1.Tex2Frac);
|
||||
tcScale[3] = 1.0f / float(1 << m_CurrentVat->g1.Tex3Frac);
|
||||
tcScale[4] = 1.0f / float(1 << m_CurrentVat->g2.Tex4Frac);
|
||||
tcScale[5] = 1.0f / float(1 << m_CurrentVat->g2.Tex5Frac);
|
||||
tcScale[6] = 1.0f / float(1 << m_CurrentVat->g2.Tex6Frac);
|
||||
tcScale[7] = 1.0f / float(1 << m_CurrentVat->g2.Tex7Frac);
|
||||
|
||||
//TexMtx
|
||||
const int tmDesc[8] = {
|
||||
g_VtxDesc.Tex0MatIdx, g_VtxDesc.Tex1MatIdx, g_VtxDesc.Tex2MatIdx, g_VtxDesc.Tex3MatIdx,
|
||||
g_VtxDesc.Tex4MatIdx, g_VtxDesc.Tex5MatIdx, g_VtxDesc.Tex6MatIdx, g_VtxDesc.Tex7MatIdx
|
||||
};
|
||||
// Colors
|
||||
const int colDesc[2] = {g_VtxDesc.Color0, g_VtxDesc.Color1};
|
||||
colElements[0] = m_CurrentVat->g0.Color0Elements;
|
||||
colElements[1] = m_CurrentVat->g0.Color1Elements;
|
||||
const int colComp[2] = {m_CurrentVat->g0.Color0Comp, m_CurrentVat->g0.Color1Comp};
|
||||
// TextureCoord
|
||||
const int tcDesc[8] = {
|
||||
g_VtxDesc.Tex0Coord, g_VtxDesc.Tex1Coord, g_VtxDesc.Tex2Coord, g_VtxDesc.Tex3Coord,
|
||||
g_VtxDesc.Tex4Coord, g_VtxDesc.Tex5Coord, g_VtxDesc.Tex6Coord, (g_VtxDesc.Hex >> 31) & 3
|
||||
};
|
||||
const int tcElements[8] = {
|
||||
m_CurrentVat->g0.Tex0CoordElements, m_CurrentVat->g1.Tex1CoordElements, m_CurrentVat->g1.Tex2CoordElements,
|
||||
m_CurrentVat->g1.Tex3CoordElements, m_CurrentVat->g1.Tex4CoordElements, m_CurrentVat->g2.Tex5CoordElements,
|
||||
m_CurrentVat->g2.Tex6CoordElements, m_CurrentVat->g2.Tex7CoordElements
|
||||
};
|
||||
|
||||
const int tcFormat[8] = {
|
||||
m_CurrentVat->g0.Tex0CoordFormat, m_CurrentVat->g1.Tex1CoordFormat, m_CurrentVat->g1.Tex2CoordFormat,
|
||||
m_CurrentVat->g1.Tex3CoordFormat, m_CurrentVat->g1.Tex4CoordFormat, m_CurrentVat->g2.Tex5CoordFormat,
|
||||
m_CurrentVat->g2.Tex6CoordFormat, m_CurrentVat->g2.Tex7CoordFormat
|
||||
};
|
||||
|
||||
m_VertexSize = 0;
|
||||
|
||||
// Reset pipeline
|
||||
m_positionLoader = NULL;
|
||||
m_normalLoader = NULL;
|
||||
m_NumAttributeLoaders = 0;
|
||||
|
||||
// Reset vertex
|
||||
// matrix index from xfregs or cp memory?
|
||||
_assert_msg_(VIDEO, xfregs.MatrixIndexA.PosNormalMtxIdx == MatrixIndexA.PosNormalMtxIdx, "Matrix indices don't match");
|
||||
//_assert_msg_(VIDEO, xfregs.MatrixIndexA.Tex0MtxIdx == MatrixIndexA.Tex0MtxIdx, "Matrix indices don't match");
|
||||
//_assert_msg_(VIDEO, xfregs.MatrixIndexA.Tex1MtxIdx == MatrixIndexA.Tex1MtxIdx, "Matrix indices don't match");
|
||||
_assert_msg_(VIDEO, xfregs.MatrixIndexA.Tex2MtxIdx == MatrixIndexA.Tex2MtxIdx, "Matrix indices don't match");
|
||||
_assert_msg_(VIDEO, xfregs.MatrixIndexA.Tex3MtxIdx == MatrixIndexA.Tex3MtxIdx, "Matrix indices don't match");
|
||||
_assert_msg_(VIDEO, xfregs.MatrixIndexB.Tex4MtxIdx == MatrixIndexB.Tex4MtxIdx, "Matrix indices don't match");
|
||||
_assert_msg_(VIDEO, xfregs.MatrixIndexB.Tex5MtxIdx == MatrixIndexB.Tex5MtxIdx, "Matrix indices don't match");
|
||||
_assert_msg_(VIDEO, xfregs.MatrixIndexB.Tex6MtxIdx == MatrixIndexB.Tex6MtxIdx, "Matrix indices don't match");
|
||||
_assert_msg_(VIDEO, xfregs.MatrixIndexB.Tex7MtxIdx == MatrixIndexB.Tex7MtxIdx, "Matrix indices don't match");
|
||||
m_Vertex.posMtx = xfregs.MatrixIndexA.PosNormalMtxIdx;
|
||||
m_Vertex.texMtx[0] = xfregs.MatrixIndexA.Tex0MtxIdx;
|
||||
m_Vertex.texMtx[1] = xfregs.MatrixIndexA.Tex1MtxIdx;
|
||||
m_Vertex.texMtx[2] = xfregs.MatrixIndexA.Tex2MtxIdx;
|
||||
m_Vertex.texMtx[3] = xfregs.MatrixIndexA.Tex3MtxIdx;
|
||||
m_Vertex.texMtx[4] = xfregs.MatrixIndexB.Tex4MtxIdx;
|
||||
m_Vertex.texMtx[5] = xfregs.MatrixIndexB.Tex5MtxIdx;
|
||||
m_Vertex.texMtx[6] = xfregs.MatrixIndexB.Tex6MtxIdx;
|
||||
m_Vertex.texMtx[7] = xfregs.MatrixIndexB.Tex7MtxIdx;
|
||||
/*m_Vertex.posMtx = MatrixIndexA.PosNormalMtxIdx;
|
||||
m_Vertex.texMtx[0] = MatrixIndexA.Tex0MtxIdx;
|
||||
m_Vertex.texMtx[1] = MatrixIndexA.Tex1MtxIdx;
|
||||
m_Vertex.texMtx[2] = MatrixIndexA.Tex2MtxIdx;
|
||||
m_Vertex.texMtx[3] = MatrixIndexA.Tex3MtxIdx;
|
||||
m_Vertex.texMtx[4] = MatrixIndexB.Tex4MtxIdx;
|
||||
m_Vertex.texMtx[5] = MatrixIndexB.Tex5MtxIdx;
|
||||
m_Vertex.texMtx[6] = MatrixIndexB.Tex6MtxIdx;
|
||||
m_Vertex.texMtx[7] = MatrixIndexB.Tex7MtxIdx;*/
|
||||
|
||||
if (g_VtxDesc.PosMatIdx != NOT_PRESENT) {
|
||||
AddAttributeLoader(LoadPosMtx);
|
||||
m_VertexSize++;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
if (tmDesc[i] != NOT_PRESENT)
|
||||
{
|
||||
AddAttributeLoader(LoadTexMtx, i);
|
||||
m_VertexSize++;
|
||||
}
|
||||
}
|
||||
|
||||
// Write vertex position loader
|
||||
m_positionLoader = VertexLoader_Position::GetFunction(g_VtxDesc.Position, m_CurrentVat->g0.PosFormat, m_CurrentVat->g0.PosElements);
|
||||
m_VertexSize += VertexLoader_Position::GetSize(g_VtxDesc.Position, m_CurrentVat->g0.PosFormat, m_CurrentVat->g0.PosElements);
|
||||
AddAttributeLoader(LoadPosition);
|
||||
|
||||
// Normals
|
||||
if (g_VtxDesc.Normal != NOT_PRESENT) {
|
||||
m_VertexSize += VertexLoader_Normal::GetSize(g_VtxDesc.Normal, m_CurrentVat->g0.NormalFormat, m_CurrentVat->g0.NormalElements, m_CurrentVat->g0.NormalIndex3);
|
||||
m_normalLoader = VertexLoader_Normal::GetFunction(g_VtxDesc.Normal, m_CurrentVat->g0.NormalFormat, m_CurrentVat->g0.NormalElements, m_CurrentVat->g0.NormalIndex3, true);
|
||||
if (m_normalLoader == 0)
|
||||
{
|
||||
ERROR_LOG(VIDEO, "VertexLoader_Normal::GetFunction returned zero!");
|
||||
}
|
||||
AddAttributeLoader(LoadNormal);
|
||||
|
||||
switch (m_CurrentVat->g0.NormalFormat) {
|
||||
case FORMAT_UBYTE:
|
||||
case FORMAT_BYTE:
|
||||
if (m_CurrentVat->g0.NormalElements)
|
||||
m_normalConverter = VertexFormatConverter::LoadNormal3_Byte;
|
||||
else
|
||||
m_normalConverter = VertexFormatConverter::LoadNormal1_Byte;
|
||||
break;
|
||||
case FORMAT_USHORT:
|
||||
case FORMAT_SHORT:
|
||||
if (m_CurrentVat->g0.NormalElements)
|
||||
m_normalConverter = VertexFormatConverter::LoadNormal3_Short;
|
||||
else
|
||||
m_normalConverter = VertexFormatConverter::LoadNormal1_Short;
|
||||
break;
|
||||
case FORMAT_FLOAT:
|
||||
if (m_CurrentVat->g0.NormalElements)
|
||||
m_normalConverter = VertexFormatConverter::LoadNormal3_Float;
|
||||
else
|
||||
m_normalConverter = VertexFormatConverter::LoadNormal1_Float;
|
||||
break;
|
||||
default: _assert_(0); break;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
switch (colDesc[i])
|
||||
{
|
||||
case NOT_PRESENT:
|
||||
m_colorLoader[i] = NULL;
|
||||
break;
|
||||
case DIRECT:
|
||||
switch (colComp[i])
|
||||
{
|
||||
case FORMAT_16B_565: m_VertexSize += 2; m_colorLoader[i] = (Color_ReadDirect_16b_565); break;
|
||||
case FORMAT_24B_888: m_VertexSize += 3; m_colorLoader[i] = (Color_ReadDirect_24b_888); break;
|
||||
case FORMAT_32B_888x: m_VertexSize += 4; m_colorLoader[i] = (Color_ReadDirect_32b_888x); break;
|
||||
case FORMAT_16B_4444: m_VertexSize += 2; m_colorLoader[i] = (Color_ReadDirect_16b_4444); break;
|
||||
case FORMAT_24B_6666: m_VertexSize += 3; m_colorLoader[i] = (Color_ReadDirect_24b_6666); break;
|
||||
case FORMAT_32B_8888: m_VertexSize += 4; m_colorLoader[i] = (Color_ReadDirect_32b_8888); break;
|
||||
default: _assert_(0); break;
|
||||
}
|
||||
AddAttributeLoader(LoadColor, i);
|
||||
break;
|
||||
case INDEX8:
|
||||
m_VertexSize += 1;
|
||||
switch (colComp[i])
|
||||
{
|
||||
case FORMAT_16B_565: m_colorLoader[i] = (Color_ReadIndex8_16b_565); break;
|
||||
case FORMAT_24B_888: m_colorLoader[i] = (Color_ReadIndex8_24b_888); break;
|
||||
case FORMAT_32B_888x: m_colorLoader[i] = (Color_ReadIndex8_32b_888x); break;
|
||||
case FORMAT_16B_4444: m_colorLoader[i] = (Color_ReadIndex8_16b_4444); break;
|
||||
case FORMAT_24B_6666: m_colorLoader[i] = (Color_ReadIndex8_24b_6666); break;
|
||||
case FORMAT_32B_8888: m_colorLoader[i] = (Color_ReadIndex8_32b_8888); break;
|
||||
default: _assert_(0); break;
|
||||
}
|
||||
AddAttributeLoader(LoadColor, i);
|
||||
break;
|
||||
case INDEX16:
|
||||
m_VertexSize += 2;
|
||||
switch (colComp[i])
|
||||
{
|
||||
case FORMAT_16B_565: m_colorLoader[i] = (Color_ReadIndex16_16b_565); break;
|
||||
case FORMAT_24B_888: m_colorLoader[i] = (Color_ReadIndex16_24b_888); break;
|
||||
case FORMAT_32B_888x: m_colorLoader[i] = (Color_ReadIndex16_32b_888x); break;
|
||||
case FORMAT_16B_4444: m_colorLoader[i] = (Color_ReadIndex16_16b_4444); break;
|
||||
case FORMAT_24B_6666: m_colorLoader[i] = (Color_ReadIndex16_24b_6666); break;
|
||||
case FORMAT_32B_8888: m_colorLoader[i] = (Color_ReadIndex16_32b_8888); break;
|
||||
default: _assert_(0); break;
|
||||
}
|
||||
AddAttributeLoader(LoadColor, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Texture matrix indices (remove if corresponding texture coordinate isn't enabled)
|
||||
for (int i = 0; i < 8; i++) {
|
||||
const int desc = tcDesc[i];
|
||||
const int format = tcFormat[i];
|
||||
const int elements = tcElements[i];
|
||||
_assert_msg_(VIDEO, NOT_PRESENT <= desc && desc <= INDEX16, "Invalid texture coordinates description!\n(desc = %d)", desc);
|
||||
_assert_msg_(VIDEO, FORMAT_UBYTE <= format && format <= FORMAT_FLOAT, "Invalid texture coordinates format!\n(format = %d)", format);
|
||||
_assert_msg_(VIDEO, 0 <= elements && elements <= 1, "Invalid number of texture coordinates elemnts!\n(elements = %d)", elements);
|
||||
|
||||
m_texCoordLoader[i] = VertexLoader_TextCoord::GetFunction(desc, format, elements);
|
||||
m_VertexSize += VertexLoader_TextCoord::GetSize(desc, format, elements);
|
||||
if (m_texCoordLoader[i])
|
||||
AddAttributeLoader(LoadTexCoord, i);
|
||||
}
|
||||
|
||||
// special case if only pos and tex coord 0 and tex coord input is AB11
|
||||
m_TexGenSpecialCase =
|
||||
((g_VtxDesc.Hex & 0x60600L) == g_VtxDesc.Hex) && // only pos and tex coord 0
|
||||
(g_VtxDesc.Tex0Coord != NOT_PRESENT) &&
|
||||
(xfregs.texMtxInfo[0].inputform == XF_TEXINPUT_AB11);
|
||||
|
||||
|
||||
m_SetupUnit->Init(primitiveType);
|
||||
}
|
||||
|
||||
|
||||
void VertexLoader::LoadVertex()
|
||||
{
|
||||
for (int i = 0; i < m_NumAttributeLoaders; i++)
|
||||
m_AttributeLoaders[i].loader(this, &m_Vertex, m_AttributeLoaders[i].index);
|
||||
|
||||
OutputVertexData* outVertex = m_SetupUnit->GetVertex();
|
||||
|
||||
// transform input data
|
||||
TransformUnit::TransformPosition(&m_Vertex, outVertex);
|
||||
|
||||
if (g_VtxDesc.Normal != NOT_PRESENT)
|
||||
{
|
||||
TransformUnit::TransformNormal(&m_Vertex, m_CurrentVat->g0.NormalElements, outVertex);
|
||||
}
|
||||
|
||||
TransformUnit::TransformColor(&m_Vertex, outVertex);
|
||||
|
||||
TransformUnit::TransformTexCoord(&m_Vertex, outVertex, m_TexGenSpecialCase);
|
||||
|
||||
m_SetupUnit->SetupVertex();
|
||||
|
||||
INCSTAT(stats.thisFrame.numVerticesLoaded)
|
||||
}
|
||||
|
||||
void VertexLoader::AddAttributeLoader(AttributeLoader loader, u8 index)
|
||||
{
|
||||
_assert_msg_(VIDEO, m_NumAttributeLoaders < 21, "Too many attribute loaders");
|
||||
m_AttributeLoaders[m_NumAttributeLoaders].loader = loader;
|
||||
m_AttributeLoaders[m_NumAttributeLoaders++].index = index;
|
||||
}
|
||||
|
||||
void VertexLoader::LoadPosMtx(VertexLoader *vertexLoader, InputVertexData *vertex, u8 unused)
|
||||
{
|
||||
vertex->posMtx = DataReadU8() & 0x3f;
|
||||
}
|
||||
|
||||
void VertexLoader::LoadTexMtx(VertexLoader *vertexLoader, InputVertexData *vertex, u8 index)
|
||||
{
|
||||
vertex->texMtx[index] = DataReadU8() & 0x3f;
|
||||
}
|
||||
|
||||
void VertexLoader::LoadPosition(VertexLoader *vertexLoader, InputVertexData *vertex, u8 unused)
|
||||
{
|
||||
VertexManager::s_pCurBufferPointer = (u8*)&vertex->position;
|
||||
vertexLoader->m_positionLoader();
|
||||
}
|
||||
|
||||
void VertexLoader::LoadNormal(VertexLoader *vertexLoader, InputVertexData *vertex, u8 unused)
|
||||
{
|
||||
u8 buffer[3*3*4];
|
||||
|
||||
VertexManager::s_pCurBufferPointer = buffer;
|
||||
vertexLoader->m_normalLoader();
|
||||
|
||||
// the common vertex loader loads data as bytes, shorts or floats so an extra step is needed to make it floats
|
||||
vertexLoader->m_normalConverter(vertex, buffer);
|
||||
}
|
||||
|
||||
void VertexLoader::LoadColor(VertexLoader *vertexLoader, InputVertexData *vertex, u8 index)
|
||||
{
|
||||
u32 color;
|
||||
VertexManager::s_pCurBufferPointer = (u8*)&color;
|
||||
colIndex = index;
|
||||
vertexLoader->m_colorLoader[index]();
|
||||
|
||||
// rgba -> abgr
|
||||
*(u32*)vertex->color[index] = Common::swap32(color);
|
||||
}
|
||||
|
||||
void VertexLoader::LoadTexCoord(VertexLoader *vertexLoader, InputVertexData *vertex, u8 index)
|
||||
{
|
||||
VertexManager::s_pCurBufferPointer = (u8*)&vertex->texCoords[index];
|
||||
tcIndex = index;
|
||||
vertexLoader->m_texCoordLoader[index]();
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,64 +1,64 @@
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "FileUtil.h"
|
||||
#include "IniFile.h"
|
||||
#include "VideoConfig.h"
|
||||
|
||||
Config g_Config;
|
||||
|
||||
Config::Config()
|
||||
{
|
||||
bFullscreen = false;
|
||||
bHideCursor = false;
|
||||
renderToMainframe = false;
|
||||
|
||||
bShowStats = false;
|
||||
bDumpTextures = false;
|
||||
bDumpObjects = false;
|
||||
bDumpFrames = false;
|
||||
bDumpTevStages = false;
|
||||
|
||||
bHwRasterizer = false;
|
||||
|
||||
drawStart = 0;
|
||||
drawEnd = 100000;
|
||||
}
|
||||
|
||||
void Config::Load()
|
||||
{
|
||||
std::string temp;
|
||||
IniFile iniFile;
|
||||
iniFile.Load((std::string(File::GetUserPath(D_CONFIG_IDX)) + "gfx_software.ini").c_str());
|
||||
|
||||
iniFile.Get("Hardware", "Fullscreen", &bFullscreen, 0); // Hardware
|
||||
iniFile.Get("Hardware", "RenderToMainframe", &renderToMainframe, false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Config::Save()
|
||||
{
|
||||
IniFile iniFile;
|
||||
iniFile.Load((std::string(File::GetUserPath(D_CONFIG_IDX)) + "gfx_software.ini").c_str());
|
||||
|
||||
iniFile.Set("Hardware", "Fullscreen", bFullscreen);
|
||||
iniFile.Set("Hardware", "RenderToMainframe", renderToMainframe);
|
||||
|
||||
iniFile.Save((std::string(File::GetUserPath(D_CONFIG_IDX)) + "gfx_opengl.ini").c_str());
|
||||
}
|
||||
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "FileUtil.h"
|
||||
#include "IniFile.h"
|
||||
#include "VideoConfig.h"
|
||||
|
||||
Config g_Config;
|
||||
|
||||
Config::Config()
|
||||
{
|
||||
bFullscreen = false;
|
||||
bHideCursor = false;
|
||||
renderToMainframe = false;
|
||||
|
||||
bShowStats = false;
|
||||
bDumpTextures = false;
|
||||
bDumpObjects = false;
|
||||
bDumpFrames = false;
|
||||
bDumpTevStages = false;
|
||||
|
||||
bHwRasterizer = false;
|
||||
|
||||
drawStart = 0;
|
||||
drawEnd = 100000;
|
||||
}
|
||||
|
||||
void Config::Load()
|
||||
{
|
||||
std::string temp;
|
||||
IniFile iniFile;
|
||||
iniFile.Load((std::string(File::GetUserPath(D_CONFIG_IDX)) + "gfx_software.ini").c_str());
|
||||
|
||||
iniFile.Get("Hardware", "Fullscreen", &bFullscreen, 0); // Hardware
|
||||
iniFile.Get("Hardware", "RenderToMainframe", &renderToMainframe, false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Config::Save()
|
||||
{
|
||||
IniFile iniFile;
|
||||
iniFile.Load((std::string(File::GetUserPath(D_CONFIG_IDX)) + "gfx_software.ini").c_str());
|
||||
|
||||
iniFile.Set("Hardware", "Fullscreen", bFullscreen);
|
||||
iniFile.Set("Hardware", "RenderToMainframe", renderToMainframe);
|
||||
|
||||
iniFile.Save((std::string(File::GetUserPath(D_CONFIG_IDX)) + "gfx_opengl.ini").c_str());
|
||||
}
|
||||
|
||||
|
@ -1,54 +1,54 @@
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _PLUGIN_VIDEOSOFTWARE_CONFIG_H_
|
||||
#define _PLUGIN_VIDEOSOFTWARE_CONFIG_H_
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
#define STATISTICS 1
|
||||
|
||||
// NEVER inherit from this class.
|
||||
struct Config
|
||||
{
|
||||
Config();
|
||||
void Load();
|
||||
void Save();
|
||||
|
||||
// General
|
||||
bool bFullscreen;
|
||||
bool bHideCursor;
|
||||
bool renderToMainframe;
|
||||
|
||||
bool bShowStats;
|
||||
bool bDumpTextures;
|
||||
bool bDumpObjects;
|
||||
bool bDumpFrames;
|
||||
bool bDumpTevStages;
|
||||
|
||||
bool bHwRasterizer;
|
||||
|
||||
u32 drawStart;
|
||||
u32 drawEnd;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(Config);
|
||||
};
|
||||
|
||||
extern Config g_Config;
|
||||
|
||||
#endif // _PLUGIN_VIDEOSOFTWARE_CONFIG_H_
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _PLUGIN_VIDEOSOFTWARE_CONFIG_H_
|
||||
#define _PLUGIN_VIDEOSOFTWARE_CONFIG_H_
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
#define STATISTICS 1
|
||||
|
||||
// NEVER inherit from this class.
|
||||
struct Config
|
||||
{
|
||||
Config();
|
||||
void Load();
|
||||
void Save();
|
||||
|
||||
// General
|
||||
bool bFullscreen;
|
||||
bool bHideCursor;
|
||||
bool renderToMainframe;
|
||||
|
||||
bool bShowStats;
|
||||
bool bDumpTextures;
|
||||
bool bDumpObjects;
|
||||
bool bDumpFrames;
|
||||
bool bDumpTevStages;
|
||||
|
||||
bool bHwRasterizer;
|
||||
|
||||
u32 drawStart;
|
||||
u32 drawEnd;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(Config);
|
||||
};
|
||||
|
||||
extern Config g_Config;
|
||||
|
||||
#endif // _PLUGIN_VIDEOSOFTWARE_CONFIG_H_
|
||||
|
@ -1,389 +1,389 @@
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <wx/wx.h>
|
||||
#include <wx/filepicker.h>
|
||||
#include <wx/notebook.h>
|
||||
#include <wx/dialog.h>
|
||||
#include <wx/aboutdlg.h>
|
||||
|
||||
#include "VideoConfig.h"
|
||||
#include "main.h"
|
||||
#include "Win32.h"
|
||||
|
||||
#include "StringUtil.h"
|
||||
|
||||
|
||||
HINSTANCE g_hInstance;
|
||||
|
||||
#if defined(HAVE_WX) && HAVE_WX
|
||||
class wxDLLApp : public wxApp
|
||||
{
|
||||
bool OnInit()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
IMPLEMENT_APP_NO_MAIN(wxDLLApp)
|
||||
WXDLLIMPEXP_BASE void wxSetInstance(HINSTANCE hInst);
|
||||
#endif
|
||||
// ------------------
|
||||
|
||||
BOOL APIENTRY DllMain(HINSTANCE hinstDLL, // DLL module handle
|
||||
DWORD dwReason, // reason called
|
||||
LPVOID lpvReserved) // reserved
|
||||
{
|
||||
switch (dwReason)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
{
|
||||
#if defined(HAVE_WX) && HAVE_WX
|
||||
wxSetInstance((HINSTANCE)hinstDLL);
|
||||
wxInitialize();
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
case DLL_PROCESS_DETACH:
|
||||
#if defined(HAVE_WX) && HAVE_WX
|
||||
wxUninitialize();
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
g_hInstance = hinstDLL;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// ----------------------
|
||||
// The rendering window
|
||||
// ----------------------
|
||||
namespace EmuWindow
|
||||
{
|
||||
|
||||
HWND m_hWnd = NULL; // The new window that is created here
|
||||
HWND m_hParent = NULL;
|
||||
|
||||
HINSTANCE m_hInstance = NULL;
|
||||
WNDCLASSEX wndClass;
|
||||
const TCHAR m_szClassName[] = _T("DolphinEmuWnd");
|
||||
int g_winstyle;
|
||||
|
||||
// ------------------------------------------
|
||||
/* Invisible cursor option. In the lack of a predefined IDC_BLANK we make
|
||||
an empty transparent cursor */
|
||||
// ------------------
|
||||
HCURSOR hCursor = NULL, hCursorBlank = NULL;
|
||||
void CreateCursors(HINSTANCE hInstance)
|
||||
{
|
||||
BYTE ANDmaskCursor[] = { 0xff };
|
||||
BYTE XORmaskCursor[] = { 0x00 };
|
||||
hCursorBlank = CreateCursor(hInstance, 0,0, 1,1, ANDmaskCursor,XORmaskCursor);
|
||||
|
||||
hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||
}
|
||||
|
||||
HWND GetWnd()
|
||||
{
|
||||
return m_hWnd;
|
||||
}
|
||||
|
||||
HWND GetParentWnd()
|
||||
{
|
||||
return m_hParent;
|
||||
}
|
||||
|
||||
LRESULT CALLBACK WndProc( HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam )
|
||||
{
|
||||
HDC hdc;
|
||||
PAINTSTRUCT ps;
|
||||
switch( iMsg )
|
||||
{
|
||||
case WM_CREATE:
|
||||
PostMessage(m_hParent, WM_USER, WM_USER_CREATE, (int)m_hParent);
|
||||
break;
|
||||
|
||||
case WM_PAINT:
|
||||
hdc = BeginPaint( hWnd, &ps );
|
||||
EndPaint( hWnd, &ps );
|
||||
break;
|
||||
|
||||
case WM_SYSKEYDOWN:
|
||||
switch( LOWORD( wParam ))
|
||||
{
|
||||
case VK_RETURN:
|
||||
// Pressing Alt+Enter switch FullScreen/Windowed
|
||||
if (m_hParent == NULL && !g_Config.renderToMainframe)
|
||||
{
|
||||
ToggleFullscreen(hWnd);
|
||||
}
|
||||
break;
|
||||
case VK_F5: case VK_F6: case VK_F7: case VK_F8:
|
||||
PostMessage(m_hParent, WM_SYSKEYDOWN, wParam, lParam);
|
||||
break;
|
||||
default:
|
||||
return DefWindowProc(hWnd, iMsg, wParam, lParam);
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_KEYDOWN:
|
||||
switch (LOWORD( wParam ))
|
||||
{
|
||||
case VK_ESCAPE:
|
||||
if (g_Config.bFullscreen)
|
||||
{
|
||||
// Pressing Esc switches to Windowed mode from Fullscreen mode
|
||||
ToggleFullscreen(hWnd);
|
||||
}
|
||||
// And pause the emulation when already in Windowed mode
|
||||
PostMessage(m_hParent, WM_USER, WM_USER_PAUSE, 0);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
/* The reason we pick up the WM_MOUSEMOVE is to be able to change this option
|
||||
during gameplay. The alternative is to load one of the cursors when the plugin
|
||||
is loaded and go with that. This should only produce a minimal performance hit
|
||||
because SetCursor is not supposed to actually change the cursor if it's the
|
||||
same as the one before. */
|
||||
case WM_MOUSEMOVE:
|
||||
/* Check rendering mode; child or parent. Then post the mouse moves to the main window
|
||||
it's nessesary for both the chil dwindow and separate rendering window because
|
||||
moves over the rendering window do not reach the main program then. */
|
||||
if (GetParentWnd() == NULL) // Separate rendering window
|
||||
PostMessage(m_hParent, iMsg, wParam, -1);
|
||||
else
|
||||
PostMessage(GetParentWnd(), iMsg, wParam, lParam);
|
||||
break;
|
||||
|
||||
/* To support the separate window rendering we get the message back here. So we basically
|
||||
only let it pass through Dolphin > Frame.cpp to determine if it should be on or off
|
||||
and coordinate it with the other settings if necessary */
|
||||
case WM_USER:
|
||||
if (wParam == WM_USER_STOP)
|
||||
SetCursor((lParam) ? hCursor : hCursorBlank);
|
||||
else if (wParam == WIIMOTE_DISCONNECT)
|
||||
PostMessage(m_hParent, WM_USER, wParam, lParam);
|
||||
break;
|
||||
|
||||
/* Post these mouse events to the main window, it's nessesary becase in difference to the
|
||||
keyboard inputs these events only appear here, not in the main WndProc() */
|
||||
case WM_LBUTTONDOWN:
|
||||
case WM_LBUTTONUP:
|
||||
case WM_LBUTTONDBLCLK:
|
||||
PostMessage(GetParentWnd(), iMsg, wParam, lParam);
|
||||
break;
|
||||
|
||||
// This is called when we close the window when we render to a separate window
|
||||
case WM_CLOSE:
|
||||
if (m_hParent == NULL)
|
||||
{
|
||||
// Take it out of fullscreen and stop the game
|
||||
if( g_Config.bFullscreen )
|
||||
ToggleFullscreen(m_hParent);
|
||||
PostMessage(m_hParent, WM_USER, WM_USER_STOP, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_DESTROY:
|
||||
Shutdown();
|
||||
break;
|
||||
|
||||
// Called when a screensaver wants to show up while this window is active
|
||||
case WM_SYSCOMMAND:
|
||||
switch (wParam)
|
||||
{
|
||||
case SC_SCREENSAVE:
|
||||
case SC_MONITORPOWER:
|
||||
break;
|
||||
default:
|
||||
return DefWindowProc(hWnd, iMsg, wParam, lParam);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return DefWindowProc(hWnd, iMsg, wParam, lParam);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// This is called from Create()
|
||||
HWND OpenWindow(HWND parent, HINSTANCE hInstance, int width, int height, const TCHAR *title)
|
||||
{
|
||||
wndClass.cbSize = sizeof( wndClass );
|
||||
wndClass.style = CS_HREDRAW | CS_VREDRAW;
|
||||
wndClass.lpfnWndProc = WndProc;
|
||||
wndClass.cbClsExtra = 0;
|
||||
wndClass.cbWndExtra = 0;
|
||||
wndClass.hInstance = hInstance;
|
||||
wndClass.hIcon = LoadIcon( NULL, IDI_APPLICATION );
|
||||
// To interfer less with SetCursor() later we set this to NULL
|
||||
//wndClass.hCursor = LoadCursor( NULL, IDC_ARROW );
|
||||
wndClass.hCursor = NULL;
|
||||
wndClass.hbrBackground = (HBRUSH)GetStockObject( BLACK_BRUSH );
|
||||
wndClass.lpszMenuName = NULL;
|
||||
wndClass.lpszClassName = m_szClassName;
|
||||
wndClass.hIconSm = LoadIcon( NULL, IDI_APPLICATION );
|
||||
|
||||
m_hInstance = hInstance;
|
||||
RegisterClassEx( &wndClass );
|
||||
|
||||
CreateCursors(m_hInstance);
|
||||
|
||||
// Create child window
|
||||
if (parent)
|
||||
{
|
||||
m_hParent = parent;
|
||||
|
||||
m_hWnd = CreateWindow(m_szClassName, title,
|
||||
WS_CHILD,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
parent, NULL, hInstance, NULL);
|
||||
|
||||
ShowWindow(m_hWnd, SW_SHOWMAXIMIZED);
|
||||
}
|
||||
|
||||
// Create new separate window
|
||||
else
|
||||
{
|
||||
DWORD style = g_Config.bFullscreen ? WS_POPUP : WS_OVERLAPPEDWINDOW;
|
||||
|
||||
RECT rc = {0, 0, width, height};
|
||||
AdjustWindowRect(&rc, style, false);
|
||||
|
||||
int w = rc.right - rc.left;
|
||||
int h = rc.bottom - rc.top;
|
||||
|
||||
rc.left = (1280 - w)/2;
|
||||
rc.right = rc.left + w;
|
||||
rc.top = (1024 - h)/2;
|
||||
rc.bottom = rc.top + h;
|
||||
|
||||
m_hParent = (HWND)g_VideoInitialize.pWindowHandle;
|
||||
|
||||
m_hWnd = CreateWindow(m_szClassName, title,
|
||||
style,
|
||||
rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top,
|
||||
parent, NULL, hInstance, NULL );
|
||||
|
||||
g_winstyle = GetWindowLong( m_hWnd, GWL_STYLE );
|
||||
g_winstyle &= ~WS_MAXIMIZE & ~WS_MINIMIZE; // remove minimize/maximize style
|
||||
}
|
||||
|
||||
return m_hWnd;
|
||||
}
|
||||
|
||||
void ToggleFullscreen(HWND hParent)
|
||||
{
|
||||
if (m_hParent == NULL)
|
||||
{
|
||||
int w_fs = 640, h_fs = 480;
|
||||
if (g_Config.bFullscreen)
|
||||
{
|
||||
// Get out of fullscreen
|
||||
g_Config.bFullscreen = false;
|
||||
RECT rc = {0, 0, w_fs, h_fs};
|
||||
|
||||
// FullScreen -> Desktop
|
||||
ChangeDisplaySettings(NULL, 0);
|
||||
|
||||
RECT rcdesktop; // Get desktop resolution
|
||||
GetWindowRect(GetDesktopWindow(), &rcdesktop);
|
||||
|
||||
ShowCursor(TRUE);
|
||||
|
||||
int X = (rcdesktop.right-rcdesktop.left)/2 - (rc.right-rc.left)/2;
|
||||
int Y = (rcdesktop.bottom-rcdesktop.top)/2 - (rc.bottom-rc.top)/2;
|
||||
// SetWindowPos to the center of the screen
|
||||
SetWindowPos(hParent, NULL, X, Y, w_fs, h_fs, SWP_NOREPOSITION | SWP_NOZORDER);
|
||||
|
||||
// Set new window style FS -> Windowed
|
||||
SetWindowLong(hParent, GWL_STYLE, WS_OVERLAPPEDWINDOW);
|
||||
|
||||
// Eventually show the window!
|
||||
EmuWindow::Show();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get into fullscreen
|
||||
DEVMODE dmScreenSettings;
|
||||
memset(&dmScreenSettings, 0, sizeof(dmScreenSettings));
|
||||
|
||||
// Desktop -> FullScreen
|
||||
dmScreenSettings.dmSize = sizeof(dmScreenSettings);
|
||||
dmScreenSettings.dmPelsWidth = w_fs;
|
||||
dmScreenSettings.dmPelsHeight = h_fs;
|
||||
dmScreenSettings.dmBitsPerPel = 32;
|
||||
dmScreenSettings.dmFields = DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
|
||||
if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
|
||||
return;
|
||||
|
||||
// Set new window style -> PopUp
|
||||
SetWindowLong(hParent, GWL_STYLE, WS_POPUP);
|
||||
g_Config.bFullscreen = true;
|
||||
ShowCursor(FALSE);
|
||||
|
||||
// SetWindowPos to the upper-left corner of the screen
|
||||
SetWindowPos(hParent, NULL, 0, 0, w_fs, h_fs, SWP_NOREPOSITION | SWP_NOZORDER);
|
||||
|
||||
// Eventually show the window!
|
||||
EmuWindow::Show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Show()
|
||||
{
|
||||
ShowWindow(m_hWnd, SW_SHOW);
|
||||
BringWindowToTop(m_hWnd);
|
||||
UpdateWindow(m_hWnd);
|
||||
}
|
||||
|
||||
HWND Create(HWND hParent, HINSTANCE hInstance, const TCHAR *title)
|
||||
{
|
||||
return OpenWindow(hParent, hInstance, 640, 480, title);
|
||||
}
|
||||
|
||||
void Close()
|
||||
{
|
||||
if (!m_hParent)
|
||||
DestroyWindow(m_hWnd);
|
||||
UnregisterClass(m_szClassName, m_hInstance);
|
||||
}
|
||||
|
||||
// ------------------------------------------
|
||||
// Set the size of the child or main window
|
||||
// ------------------------------------------
|
||||
void SetSize(int width, int height)
|
||||
{
|
||||
RECT rc = {0, 0, width, height};
|
||||
AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, false);
|
||||
|
||||
int w = rc.right - rc.left;
|
||||
int h = rc.bottom - rc.top;
|
||||
|
||||
// Move and resize the window
|
||||
rc.left = (1280 - w)/2;
|
||||
rc.right = rc.left + w;
|
||||
rc.top = (1024 - h)/2;
|
||||
rc.bottom = rc.top + h;
|
||||
MoveWindow(m_hWnd, rc.left,rc.top,rc.right-rc.left,rc.bottom-rc.top, TRUE);
|
||||
}
|
||||
|
||||
} // EmuWindow
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <wx/wx.h>
|
||||
#include <wx/filepicker.h>
|
||||
#include <wx/notebook.h>
|
||||
#include <wx/dialog.h>
|
||||
#include <wx/aboutdlg.h>
|
||||
|
||||
#include "VideoConfig.h"
|
||||
#include "main.h"
|
||||
#include "Win32.h"
|
||||
|
||||
#include "StringUtil.h"
|
||||
|
||||
|
||||
HINSTANCE g_hInstance;
|
||||
|
||||
#if defined(HAVE_WX) && HAVE_WX
|
||||
class wxDLLApp : public wxApp
|
||||
{
|
||||
bool OnInit()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
IMPLEMENT_APP_NO_MAIN(wxDLLApp)
|
||||
WXDLLIMPEXP_BASE void wxSetInstance(HINSTANCE hInst);
|
||||
#endif
|
||||
// ------------------
|
||||
|
||||
BOOL APIENTRY DllMain(HINSTANCE hinstDLL, // DLL module handle
|
||||
DWORD dwReason, // reason called
|
||||
LPVOID lpvReserved) // reserved
|
||||
{
|
||||
switch (dwReason)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
{
|
||||
#if defined(HAVE_WX) && HAVE_WX
|
||||
wxSetInstance((HINSTANCE)hinstDLL);
|
||||
wxInitialize();
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
case DLL_PROCESS_DETACH:
|
||||
#if defined(HAVE_WX) && HAVE_WX
|
||||
wxUninitialize();
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
g_hInstance = hinstDLL;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// ----------------------
|
||||
// The rendering window
|
||||
// ----------------------
|
||||
namespace EmuWindow
|
||||
{
|
||||
|
||||
HWND m_hWnd = NULL; // The new window that is created here
|
||||
HWND m_hParent = NULL;
|
||||
|
||||
HINSTANCE m_hInstance = NULL;
|
||||
WNDCLASSEX wndClass;
|
||||
const TCHAR m_szClassName[] = _T("DolphinEmuWnd");
|
||||
int g_winstyle;
|
||||
|
||||
// ------------------------------------------
|
||||
/* Invisible cursor option. In the lack of a predefined IDC_BLANK we make
|
||||
an empty transparent cursor */
|
||||
// ------------------
|
||||
HCURSOR hCursor = NULL, hCursorBlank = NULL;
|
||||
void CreateCursors(HINSTANCE hInstance)
|
||||
{
|
||||
BYTE ANDmaskCursor[] = { 0xff };
|
||||
BYTE XORmaskCursor[] = { 0x00 };
|
||||
hCursorBlank = CreateCursor(hInstance, 0,0, 1,1, ANDmaskCursor,XORmaskCursor);
|
||||
|
||||
hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||
}
|
||||
|
||||
HWND GetWnd()
|
||||
{
|
||||
return m_hWnd;
|
||||
}
|
||||
|
||||
HWND GetParentWnd()
|
||||
{
|
||||
return m_hParent;
|
||||
}
|
||||
|
||||
LRESULT CALLBACK WndProc( HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam )
|
||||
{
|
||||
HDC hdc;
|
||||
PAINTSTRUCT ps;
|
||||
switch( iMsg )
|
||||
{
|
||||
case WM_CREATE:
|
||||
PostMessage(m_hParent, WM_USER, WM_USER_CREATE, (int)m_hParent);
|
||||
break;
|
||||
|
||||
case WM_PAINT:
|
||||
hdc = BeginPaint( hWnd, &ps );
|
||||
EndPaint( hWnd, &ps );
|
||||
break;
|
||||
|
||||
case WM_SYSKEYDOWN:
|
||||
switch( LOWORD( wParam ))
|
||||
{
|
||||
case VK_RETURN:
|
||||
// Pressing Alt+Enter switch FullScreen/Windowed
|
||||
if (m_hParent == NULL && !g_Config.renderToMainframe)
|
||||
{
|
||||
ToggleFullscreen(hWnd);
|
||||
}
|
||||
break;
|
||||
case VK_F5: case VK_F6: case VK_F7: case VK_F8:
|
||||
PostMessage(m_hParent, WM_SYSKEYDOWN, wParam, lParam);
|
||||
break;
|
||||
default:
|
||||
return DefWindowProc(hWnd, iMsg, wParam, lParam);
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_KEYDOWN:
|
||||
switch (LOWORD( wParam ))
|
||||
{
|
||||
case VK_ESCAPE:
|
||||
if (g_Config.bFullscreen)
|
||||
{
|
||||
// Pressing Esc switches to Windowed mode from Fullscreen mode
|
||||
ToggleFullscreen(hWnd);
|
||||
}
|
||||
// And pause the emulation when already in Windowed mode
|
||||
PostMessage(m_hParent, WM_USER, WM_USER_PAUSE, 0);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
/* The reason we pick up the WM_MOUSEMOVE is to be able to change this option
|
||||
during gameplay. The alternative is to load one of the cursors when the plugin
|
||||
is loaded and go with that. This should only produce a minimal performance hit
|
||||
because SetCursor is not supposed to actually change the cursor if it's the
|
||||
same as the one before. */
|
||||
case WM_MOUSEMOVE:
|
||||
/* Check rendering mode; child or parent. Then post the mouse moves to the main window
|
||||
it's nessesary for both the chil dwindow and separate rendering window because
|
||||
moves over the rendering window do not reach the main program then. */
|
||||
if (GetParentWnd() == NULL) // Separate rendering window
|
||||
PostMessage(m_hParent, iMsg, wParam, -1);
|
||||
else
|
||||
PostMessage(GetParentWnd(), iMsg, wParam, lParam);
|
||||
break;
|
||||
|
||||
/* To support the separate window rendering we get the message back here. So we basically
|
||||
only let it pass through Dolphin > Frame.cpp to determine if it should be on or off
|
||||
and coordinate it with the other settings if necessary */
|
||||
case WM_USER:
|
||||
if (wParam == WM_USER_STOP)
|
||||
SetCursor((lParam) ? hCursor : hCursorBlank);
|
||||
else if (wParam == WIIMOTE_DISCONNECT)
|
||||
PostMessage(m_hParent, WM_USER, wParam, lParam);
|
||||
break;
|
||||
|
||||
/* Post these mouse events to the main window, it's nessesary becase in difference to the
|
||||
keyboard inputs these events only appear here, not in the main WndProc() */
|
||||
case WM_LBUTTONDOWN:
|
||||
case WM_LBUTTONUP:
|
||||
case WM_LBUTTONDBLCLK:
|
||||
PostMessage(GetParentWnd(), iMsg, wParam, lParam);
|
||||
break;
|
||||
|
||||
// This is called when we close the window when we render to a separate window
|
||||
case WM_CLOSE:
|
||||
if (m_hParent == NULL)
|
||||
{
|
||||
// Take it out of fullscreen and stop the game
|
||||
if( g_Config.bFullscreen )
|
||||
ToggleFullscreen(m_hParent);
|
||||
PostMessage(m_hParent, WM_USER, WM_USER_STOP, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_DESTROY:
|
||||
Shutdown();
|
||||
break;
|
||||
|
||||
// Called when a screensaver wants to show up while this window is active
|
||||
case WM_SYSCOMMAND:
|
||||
switch (wParam)
|
||||
{
|
||||
case SC_SCREENSAVE:
|
||||
case SC_MONITORPOWER:
|
||||
break;
|
||||
default:
|
||||
return DefWindowProc(hWnd, iMsg, wParam, lParam);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return DefWindowProc(hWnd, iMsg, wParam, lParam);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// This is called from Create()
|
||||
HWND OpenWindow(HWND parent, HINSTANCE hInstance, int width, int height, const TCHAR *title)
|
||||
{
|
||||
wndClass.cbSize = sizeof( wndClass );
|
||||
wndClass.style = CS_HREDRAW | CS_VREDRAW;
|
||||
wndClass.lpfnWndProc = WndProc;
|
||||
wndClass.cbClsExtra = 0;
|
||||
wndClass.cbWndExtra = 0;
|
||||
wndClass.hInstance = hInstance;
|
||||
wndClass.hIcon = LoadIcon( NULL, IDI_APPLICATION );
|
||||
// To interfer less with SetCursor() later we set this to NULL
|
||||
//wndClass.hCursor = LoadCursor( NULL, IDC_ARROW );
|
||||
wndClass.hCursor = NULL;
|
||||
wndClass.hbrBackground = (HBRUSH)GetStockObject( BLACK_BRUSH );
|
||||
wndClass.lpszMenuName = NULL;
|
||||
wndClass.lpszClassName = m_szClassName;
|
||||
wndClass.hIconSm = LoadIcon( NULL, IDI_APPLICATION );
|
||||
|
||||
m_hInstance = hInstance;
|
||||
RegisterClassEx( &wndClass );
|
||||
|
||||
CreateCursors(m_hInstance);
|
||||
|
||||
// Create child window
|
||||
if (parent)
|
||||
{
|
||||
m_hParent = parent;
|
||||
|
||||
m_hWnd = CreateWindow(m_szClassName, title,
|
||||
WS_CHILD,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
parent, NULL, hInstance, NULL);
|
||||
|
||||
ShowWindow(m_hWnd, SW_SHOWMAXIMIZED);
|
||||
}
|
||||
|
||||
// Create new separate window
|
||||
else
|
||||
{
|
||||
DWORD style = g_Config.bFullscreen ? WS_POPUP : WS_OVERLAPPEDWINDOW;
|
||||
|
||||
RECT rc = {0, 0, width, height};
|
||||
AdjustWindowRect(&rc, style, false);
|
||||
|
||||
int w = rc.right - rc.left;
|
||||
int h = rc.bottom - rc.top;
|
||||
|
||||
rc.left = (1280 - w)/2;
|
||||
rc.right = rc.left + w;
|
||||
rc.top = (1024 - h)/2;
|
||||
rc.bottom = rc.top + h;
|
||||
|
||||
m_hParent = (HWND)g_VideoInitialize.pWindowHandle;
|
||||
|
||||
m_hWnd = CreateWindow(m_szClassName, title,
|
||||
style,
|
||||
rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top,
|
||||
parent, NULL, hInstance, NULL );
|
||||
|
||||
g_winstyle = GetWindowLong( m_hWnd, GWL_STYLE );
|
||||
g_winstyle &= ~WS_MAXIMIZE & ~WS_MINIMIZE; // remove minimize/maximize style
|
||||
}
|
||||
|
||||
return m_hWnd;
|
||||
}
|
||||
|
||||
void ToggleFullscreen(HWND hParent)
|
||||
{
|
||||
if (m_hParent == NULL)
|
||||
{
|
||||
int w_fs = 640, h_fs = 480;
|
||||
if (g_Config.bFullscreen)
|
||||
{
|
||||
// Get out of fullscreen
|
||||
g_Config.bFullscreen = false;
|
||||
RECT rc = {0, 0, w_fs, h_fs};
|
||||
|
||||
// FullScreen -> Desktop
|
||||
ChangeDisplaySettings(NULL, 0);
|
||||
|
||||
RECT rcdesktop; // Get desktop resolution
|
||||
GetWindowRect(GetDesktopWindow(), &rcdesktop);
|
||||
|
||||
ShowCursor(TRUE);
|
||||
|
||||
int X = (rcdesktop.right-rcdesktop.left)/2 - (rc.right-rc.left)/2;
|
||||
int Y = (rcdesktop.bottom-rcdesktop.top)/2 - (rc.bottom-rc.top)/2;
|
||||
// SetWindowPos to the center of the screen
|
||||
SetWindowPos(hParent, NULL, X, Y, w_fs, h_fs, SWP_NOREPOSITION | SWP_NOZORDER);
|
||||
|
||||
// Set new window style FS -> Windowed
|
||||
SetWindowLong(hParent, GWL_STYLE, WS_OVERLAPPEDWINDOW);
|
||||
|
||||
// Eventually show the window!
|
||||
EmuWindow::Show();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get into fullscreen
|
||||
DEVMODE dmScreenSettings;
|
||||
memset(&dmScreenSettings, 0, sizeof(dmScreenSettings));
|
||||
|
||||
// Desktop -> FullScreen
|
||||
dmScreenSettings.dmSize = sizeof(dmScreenSettings);
|
||||
dmScreenSettings.dmPelsWidth = w_fs;
|
||||
dmScreenSettings.dmPelsHeight = h_fs;
|
||||
dmScreenSettings.dmBitsPerPel = 32;
|
||||
dmScreenSettings.dmFields = DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
|
||||
if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
|
||||
return;
|
||||
|
||||
// Set new window style -> PopUp
|
||||
SetWindowLong(hParent, GWL_STYLE, WS_POPUP);
|
||||
g_Config.bFullscreen = true;
|
||||
ShowCursor(FALSE);
|
||||
|
||||
// SetWindowPos to the upper-left corner of the screen
|
||||
SetWindowPos(hParent, NULL, 0, 0, w_fs, h_fs, SWP_NOREPOSITION | SWP_NOZORDER);
|
||||
|
||||
// Eventually show the window!
|
||||
EmuWindow::Show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Show()
|
||||
{
|
||||
ShowWindow(m_hWnd, SW_SHOW);
|
||||
BringWindowToTop(m_hWnd);
|
||||
UpdateWindow(m_hWnd);
|
||||
}
|
||||
|
||||
HWND Create(HWND hParent, HINSTANCE hInstance, const TCHAR *title)
|
||||
{
|
||||
return OpenWindow(hParent, hInstance, 640, 480, title);
|
||||
}
|
||||
|
||||
void Close()
|
||||
{
|
||||
if (!m_hParent)
|
||||
DestroyWindow(m_hWnd);
|
||||
UnregisterClass(m_szClassName, m_hInstance);
|
||||
}
|
||||
|
||||
// ------------------------------------------
|
||||
// Set the size of the child or main window
|
||||
// ------------------------------------------
|
||||
void SetSize(int width, int height)
|
||||
{
|
||||
RECT rc = {0, 0, width, height};
|
||||
AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, false);
|
||||
|
||||
int w = rc.right - rc.left;
|
||||
int h = rc.bottom - rc.top;
|
||||
|
||||
// Move and resize the window
|
||||
rc.left = (1280 - w)/2;
|
||||
rc.right = rc.left + w;
|
||||
rc.top = (1024 - h)/2;
|
||||
rc.bottom = rc.top + h;
|
||||
MoveWindow(m_hWnd, rc.left,rc.top,rc.right-rc.left,rc.bottom-rc.top, TRUE);
|
||||
}
|
||||
|
||||
} // EmuWindow
|
||||
|
@ -1,39 +1,39 @@
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _WIN32_H_
|
||||
#define _WIN32_H_
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
namespace EmuWindow
|
||||
{
|
||||
extern int g_winstyle;
|
||||
|
||||
HWND GetWnd();
|
||||
HWND GetParentWnd();
|
||||
HWND GetChildParentWnd();
|
||||
HWND Create(HWND hParent, HINSTANCE hInstance, const TCHAR *title);
|
||||
void Show();
|
||||
void Close();
|
||||
void ToggleFullscreen(HWND hParent);
|
||||
void SetSize(int displayWidth, int displayHeight);
|
||||
}
|
||||
|
||||
#endif // _WIN32_H_
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _WIN32_H_
|
||||
#define _WIN32_H_
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
namespace EmuWindow
|
||||
{
|
||||
extern int g_winstyle;
|
||||
|
||||
HWND GetWnd();
|
||||
HWND GetParentWnd();
|
||||
HWND GetChildParentWnd();
|
||||
HWND Create(HWND hParent, HINSTANCE hInstance, const TCHAR *title);
|
||||
void Show();
|
||||
void Close();
|
||||
void ToggleFullscreen(HWND hParent);
|
||||
void SetSize(int displayWidth, int displayHeight);
|
||||
}
|
||||
|
||||
#endif // _WIN32_H_
|
||||
|
@ -1,96 +1,96 @@
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "../../../Core/VideoCommon/Src/VideoCommon.h"
|
||||
|
||||
#include "XFMemLoader.h"
|
||||
#include "CPMemLoader.h"
|
||||
#include "Clipper.h"
|
||||
|
||||
|
||||
XFRegisters xfregs;
|
||||
|
||||
void InitXFMemory()
|
||||
{
|
||||
memset(&xfregs, 0, sizeof(xfregs));
|
||||
}
|
||||
|
||||
void XFWritten(u32 transferSize, u32 baseAddress)
|
||||
{
|
||||
u32 topAddress = baseAddress + transferSize;
|
||||
|
||||
if (baseAddress <= 0x1026 && topAddress >= 0x1020)
|
||||
Clipper::SetViewOffset();
|
||||
|
||||
// fix lights so invalid values don't trash the lighting computations
|
||||
if (baseAddress <= 0x067f && topAddress >= 0x0604)
|
||||
{
|
||||
u32* x = xfregs.lights;
|
||||
|
||||
// go through all lights
|
||||
for (int light = 0; light < 8; light++)
|
||||
{
|
||||
// skip to floating point values
|
||||
x += 4;
|
||||
|
||||
for (int i = 0; i < 12; i++)
|
||||
{
|
||||
u32 xVal = *x;
|
||||
|
||||
// if the exponent is 255 then the number is inf or nan
|
||||
if ((xVal & 0x7f800000) == 0x7f800000)
|
||||
*x = 0;
|
||||
|
||||
x++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LoadXFReg(u32 transferSize, u32 baseAddress, u32 *pData)
|
||||
{
|
||||
u32 size = transferSize;
|
||||
|
||||
// do not allow writes past registers
|
||||
if (baseAddress + transferSize > 0x1058)
|
||||
{
|
||||
INFO_LOG(VIDEO, "xf load exceeds address space: %x %d bytes\n", baseAddress, transferSize);
|
||||
|
||||
if (baseAddress >= 0x1058)
|
||||
size = 0;
|
||||
else
|
||||
size = 0x1058 - baseAddress;
|
||||
}
|
||||
|
||||
if (size > 0) {
|
||||
memcpy_gc( &((u32*)&xfregs)[baseAddress], pData, size * 4);
|
||||
XFWritten(transferSize, baseAddress);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void LoadIndexedXF(u32 val, int array)
|
||||
{
|
||||
int index = val >> 16;
|
||||
int address = val & 0xFFF; //check mask
|
||||
int size = ((val >> 12) & 0xF) + 1;
|
||||
//load stuff from array to address in xf mem
|
||||
|
||||
u32 *pData = (u32*)g_VideoInitialize.pGetMemoryPointer(arraybases[array] + arraystrides[array]*index);
|
||||
|
||||
LoadXFReg(size, address, pData);
|
||||
}
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "../../../Core/VideoCommon/Src/VideoCommon.h"
|
||||
|
||||
#include "XFMemLoader.h"
|
||||
#include "CPMemLoader.h"
|
||||
#include "Clipper.h"
|
||||
|
||||
|
||||
XFRegisters xfregs;
|
||||
|
||||
void InitXFMemory()
|
||||
{
|
||||
memset(&xfregs, 0, sizeof(xfregs));
|
||||
}
|
||||
|
||||
void XFWritten(u32 transferSize, u32 baseAddress)
|
||||
{
|
||||
u32 topAddress = baseAddress + transferSize;
|
||||
|
||||
if (baseAddress <= 0x1026 && topAddress >= 0x1020)
|
||||
Clipper::SetViewOffset();
|
||||
|
||||
// fix lights so invalid values don't trash the lighting computations
|
||||
if (baseAddress <= 0x067f && topAddress >= 0x0604)
|
||||
{
|
||||
u32* x = xfregs.lights;
|
||||
|
||||
// go through all lights
|
||||
for (int light = 0; light < 8; light++)
|
||||
{
|
||||
// skip to floating point values
|
||||
x += 4;
|
||||
|
||||
for (int i = 0; i < 12; i++)
|
||||
{
|
||||
u32 xVal = *x;
|
||||
|
||||
// if the exponent is 255 then the number is inf or nan
|
||||
if ((xVal & 0x7f800000) == 0x7f800000)
|
||||
*x = 0;
|
||||
|
||||
x++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LoadXFReg(u32 transferSize, u32 baseAddress, u32 *pData)
|
||||
{
|
||||
u32 size = transferSize;
|
||||
|
||||
// do not allow writes past registers
|
||||
if (baseAddress + transferSize > 0x1058)
|
||||
{
|
||||
INFO_LOG(VIDEO, "xf load exceeds address space: %x %d bytes\n", baseAddress, transferSize);
|
||||
|
||||
if (baseAddress >= 0x1058)
|
||||
size = 0;
|
||||
else
|
||||
size = 0x1058 - baseAddress;
|
||||
}
|
||||
|
||||
if (size > 0) {
|
||||
memcpy_gc( &((u32*)&xfregs)[baseAddress], pData, size * 4);
|
||||
XFWritten(transferSize, baseAddress);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void LoadIndexedXF(u32 val, int array)
|
||||
{
|
||||
int index = val >> 16;
|
||||
int address = val & 0xFFF; //check mask
|
||||
int size = ((val >> 12) & 0xF) + 1;
|
||||
//load stuff from array to address in xf mem
|
||||
|
||||
u32 *pData = (u32*)g_VideoInitialize.pGetMemoryPointer(arraybases[array] + arraystrides[array]*index);
|
||||
|
||||
LoadXFReg(size, address, pData);
|
||||
}
|
||||
|
@ -1,211 +1,211 @@
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
|
||||
#include "Common.h"
|
||||
#include "pluginspecs_video.h"
|
||||
|
||||
#include "CommandProcessor.h"
|
||||
#include "OpcodeDecoder.h"
|
||||
#include "VideoConfig.h"
|
||||
#include "PixelEngine.h"
|
||||
#include "CommandProcessor.h"
|
||||
#include "BPMemLoader.h"
|
||||
#include "XFMemLoader.h"
|
||||
#include "Clipper.h"
|
||||
#include "Rasterizer.h"
|
||||
#include "Renderer.h"
|
||||
#include "../../../Core/VideoCommon/Src/LookUpTables.h"
|
||||
#include "HwRasterizer.h"
|
||||
#include "LogManager.h"
|
||||
#include "EfbInterface.h"
|
||||
#include "DebugUtil.h"
|
||||
|
||||
|
||||
PLUGIN_GLOBALS* globals = NULL;
|
||||
SVideoInitialize g_VideoInitialize;
|
||||
|
||||
|
||||
void GetDllInfo (PLUGIN_INFO* _PluginInfo)
|
||||
{
|
||||
_PluginInfo->Version = 0x0100;
|
||||
_PluginInfo->Type = PLUGIN_TYPE_VIDEO;
|
||||
#ifdef DEBUGFAST
|
||||
sprintf(_PluginInfo->Name, "Dolphin Software Renderer (DebugFast)");
|
||||
#else
|
||||
#ifndef _DEBUG
|
||||
sprintf(_PluginInfo->Name, "Dolphin Software Renderer");
|
||||
#else
|
||||
sprintf(_PluginInfo->Name, "Dolphin Software Renderer (Debug)");
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void SetDllGlobals(PLUGIN_GLOBALS* _pPluginGlobals)
|
||||
{
|
||||
globals = _pPluginGlobals;
|
||||
LogManager::SetInstance((LogManager *)globals->logManager);
|
||||
}
|
||||
|
||||
void DllDebugger(HWND _hParent, bool Show)
|
||||
{
|
||||
}
|
||||
|
||||
void DllConfig(HWND _hParent)
|
||||
{
|
||||
}
|
||||
|
||||
void Initialize(void *init)
|
||||
{
|
||||
SVideoInitialize *_pVideoInitialize = (SVideoInitialize*)init;
|
||||
g_VideoInitialize = *_pVideoInitialize;
|
||||
|
||||
g_Config.Load();
|
||||
|
||||
InitBPMemory();
|
||||
InitXFMemory();
|
||||
CommandProcessor::Init();
|
||||
PixelEngine::Init();
|
||||
OpcodeDecoder::Init();
|
||||
Clipper::Init();
|
||||
Rasterizer::Init();
|
||||
HwRasterizer::Init();
|
||||
Renderer::Init(_pVideoInitialize);
|
||||
DebugUtil::Init();
|
||||
}
|
||||
|
||||
void DoState(unsigned char **ptr, int mode)
|
||||
{
|
||||
}
|
||||
|
||||
void EmuStateChange(PLUGIN_EMUSTATE newState)
|
||||
{
|
||||
}
|
||||
|
||||
void Shutdown(void)
|
||||
{
|
||||
Renderer::Shutdown();
|
||||
OpenGL_Shutdown();
|
||||
}
|
||||
|
||||
// This is called after Video_Initialize() from the Core
|
||||
void Video_Prepare(void)
|
||||
{
|
||||
Renderer::Prepare();
|
||||
|
||||
INFO_LOG(VIDEO, "Video plugin initialized.");
|
||||
}
|
||||
|
||||
// Run from the CPU thread (from VideoInterface.cpp)
|
||||
void Video_BeginField(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight)
|
||||
{
|
||||
}
|
||||
|
||||
// Run from the CPU thread (from VideoInterface.cpp)
|
||||
void Video_EndField()
|
||||
{
|
||||
}
|
||||
|
||||
u32 Video_AccessEFB(EFBAccessType type, u32 x, u32 y)
|
||||
{
|
||||
u32 value = 0;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case PEEK_Z:
|
||||
{
|
||||
value = EfbInterface::GetDepth(x, y);
|
||||
break;
|
||||
}
|
||||
case POKE_Z:
|
||||
break;
|
||||
case PEEK_COLOR:
|
||||
{
|
||||
u32 color = 0;
|
||||
EfbInterface::GetColor(x, y, (u8*)&color);
|
||||
|
||||
// rgba to argb
|
||||
value = (color >> 8) | (color & 0xff) << 24;
|
||||
break;
|
||||
}
|
||||
|
||||
case POKE_COLOR:
|
||||
break;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
void Video_Screenshot(const char *_szFilename)
|
||||
{
|
||||
}
|
||||
|
||||
// -------------------------------
|
||||
// Enter and exit the video loop
|
||||
// -------------------------------
|
||||
void Video_EnterLoop()
|
||||
{
|
||||
Fifo_EnterLoop(g_VideoInitialize);
|
||||
}
|
||||
|
||||
void Video_ExitLoop()
|
||||
{
|
||||
Fifo_ExitLoop();
|
||||
}
|
||||
|
||||
void Video_AddMessage(const char* pstr, u32 milliseconds)
|
||||
{
|
||||
}
|
||||
|
||||
void Video_SetRendering(bool bEnabled)
|
||||
{
|
||||
Fifo_SetRendering(bEnabled);
|
||||
}
|
||||
|
||||
void Video_CommandProcessorRead16(u16& _rReturnValue, const u32 _Address)
|
||||
{
|
||||
CommandProcessor::Read16(_rReturnValue, _Address);
|
||||
}
|
||||
|
||||
void Video_CommandProcessorWrite16(const u16 _Data, const u32 _Address)
|
||||
{
|
||||
CommandProcessor::Write16(_Data, _Address);
|
||||
}
|
||||
|
||||
void Video_PixelEngineRead16(u16& _rReturnValue, const u32 _Address)
|
||||
{
|
||||
PixelEngine::Read16(_rReturnValue, _Address);
|
||||
}
|
||||
|
||||
void Video_PixelEngineWrite16(const u16 _Data, const u32 _Address)
|
||||
{
|
||||
PixelEngine::Write16(_Data, _Address);
|
||||
}
|
||||
|
||||
void Video_PixelEngineWrite32(const u32 _Data, const u32 _Address)
|
||||
{
|
||||
PixelEngine::Write32(_Data, _Address);
|
||||
}
|
||||
|
||||
void Video_GatherPipeBursted(void)
|
||||
{
|
||||
CommandProcessor::GatherPipeBursted();
|
||||
}
|
||||
|
||||
void Video_WaitForFrameFinish(void)
|
||||
{
|
||||
}
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
|
||||
#include "Common.h"
|
||||
#include "pluginspecs_video.h"
|
||||
|
||||
#include "CommandProcessor.h"
|
||||
#include "OpcodeDecoder.h"
|
||||
#include "VideoConfig.h"
|
||||
#include "PixelEngine.h"
|
||||
#include "CommandProcessor.h"
|
||||
#include "BPMemLoader.h"
|
||||
#include "XFMemLoader.h"
|
||||
#include "Clipper.h"
|
||||
#include "Rasterizer.h"
|
||||
#include "Renderer.h"
|
||||
#include "../../../Core/VideoCommon/Src/LookUpTables.h"
|
||||
#include "HwRasterizer.h"
|
||||
#include "LogManager.h"
|
||||
#include "EfbInterface.h"
|
||||
#include "DebugUtil.h"
|
||||
|
||||
|
||||
PLUGIN_GLOBALS* globals = NULL;
|
||||
SVideoInitialize g_VideoInitialize;
|
||||
|
||||
|
||||
void GetDllInfo (PLUGIN_INFO* _PluginInfo)
|
||||
{
|
||||
_PluginInfo->Version = 0x0100;
|
||||
_PluginInfo->Type = PLUGIN_TYPE_VIDEO;
|
||||
#ifdef DEBUGFAST
|
||||
sprintf(_PluginInfo->Name, "Dolphin Software Renderer (DebugFast)");
|
||||
#else
|
||||
#ifndef _DEBUG
|
||||
sprintf(_PluginInfo->Name, "Dolphin Software Renderer");
|
||||
#else
|
||||
sprintf(_PluginInfo->Name, "Dolphin Software Renderer (Debug)");
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void SetDllGlobals(PLUGIN_GLOBALS* _pPluginGlobals)
|
||||
{
|
||||
globals = _pPluginGlobals;
|
||||
LogManager::SetInstance((LogManager *)globals->logManager);
|
||||
}
|
||||
|
||||
void DllDebugger(HWND _hParent, bool Show)
|
||||
{
|
||||
}
|
||||
|
||||
void DllConfig(HWND _hParent)
|
||||
{
|
||||
}
|
||||
|
||||
void Initialize(void *init)
|
||||
{
|
||||
SVideoInitialize *_pVideoInitialize = (SVideoInitialize*)init;
|
||||
g_VideoInitialize = *_pVideoInitialize;
|
||||
|
||||
g_Config.Load();
|
||||
|
||||
InitBPMemory();
|
||||
InitXFMemory();
|
||||
CommandProcessor::Init();
|
||||
PixelEngine::Init();
|
||||
OpcodeDecoder::Init();
|
||||
Clipper::Init();
|
||||
Rasterizer::Init();
|
||||
HwRasterizer::Init();
|
||||
Renderer::Init(_pVideoInitialize);
|
||||
DebugUtil::Init();
|
||||
}
|
||||
|
||||
void DoState(unsigned char **ptr, int mode)
|
||||
{
|
||||
}
|
||||
|
||||
void EmuStateChange(PLUGIN_EMUSTATE newState)
|
||||
{
|
||||
}
|
||||
|
||||
void Shutdown(void)
|
||||
{
|
||||
Renderer::Shutdown();
|
||||
OpenGL_Shutdown();
|
||||
}
|
||||
|
||||
// This is called after Video_Initialize() from the Core
|
||||
void Video_Prepare(void)
|
||||
{
|
||||
Renderer::Prepare();
|
||||
|
||||
INFO_LOG(VIDEO, "Video plugin initialized.");
|
||||
}
|
||||
|
||||
// Run from the CPU thread (from VideoInterface.cpp)
|
||||
void Video_BeginField(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight)
|
||||
{
|
||||
}
|
||||
|
||||
// Run from the CPU thread (from VideoInterface.cpp)
|
||||
void Video_EndField()
|
||||
{
|
||||
}
|
||||
|
||||
u32 Video_AccessEFB(EFBAccessType type, u32 x, u32 y)
|
||||
{
|
||||
u32 value = 0;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case PEEK_Z:
|
||||
{
|
||||
value = EfbInterface::GetDepth(x, y);
|
||||
break;
|
||||
}
|
||||
case POKE_Z:
|
||||
break;
|
||||
case PEEK_COLOR:
|
||||
{
|
||||
u32 color = 0;
|
||||
EfbInterface::GetColor(x, y, (u8*)&color);
|
||||
|
||||
// rgba to argb
|
||||
value = (color >> 8) | (color & 0xff) << 24;
|
||||
break;
|
||||
}
|
||||
|
||||
case POKE_COLOR:
|
||||
break;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
void Video_Screenshot(const char *_szFilename)
|
||||
{
|
||||
}
|
||||
|
||||
// -------------------------------
|
||||
// Enter and exit the video loop
|
||||
// -------------------------------
|
||||
void Video_EnterLoop()
|
||||
{
|
||||
Fifo_EnterLoop(g_VideoInitialize);
|
||||
}
|
||||
|
||||
void Video_ExitLoop()
|
||||
{
|
||||
Fifo_ExitLoop();
|
||||
}
|
||||
|
||||
void Video_AddMessage(const char* pstr, u32 milliseconds)
|
||||
{
|
||||
}
|
||||
|
||||
void Video_SetRendering(bool bEnabled)
|
||||
{
|
||||
Fifo_SetRendering(bEnabled);
|
||||
}
|
||||
|
||||
void Video_CommandProcessorRead16(u16& _rReturnValue, const u32 _Address)
|
||||
{
|
||||
CommandProcessor::Read16(_rReturnValue, _Address);
|
||||
}
|
||||
|
||||
void Video_CommandProcessorWrite16(const u16 _Data, const u32 _Address)
|
||||
{
|
||||
CommandProcessor::Write16(_Data, _Address);
|
||||
}
|
||||
|
||||
void Video_PixelEngineRead16(u16& _rReturnValue, const u32 _Address)
|
||||
{
|
||||
PixelEngine::Read16(_rReturnValue, _Address);
|
||||
}
|
||||
|
||||
void Video_PixelEngineWrite16(const u16 _Data, const u32 _Address)
|
||||
{
|
||||
PixelEngine::Write16(_Data, _Address);
|
||||
}
|
||||
|
||||
void Video_PixelEngineWrite32(const u32 _Data, const u32 _Address)
|
||||
{
|
||||
PixelEngine::Write32(_Data, _Address);
|
||||
}
|
||||
|
||||
void Video_GatherPipeBursted(void)
|
||||
{
|
||||
CommandProcessor::GatherPipeBursted();
|
||||
}
|
||||
|
||||
void Video_WaitForFrameFinish(void)
|
||||
{
|
||||
}
|
||||
|
@ -1,25 +1,25 @@
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef MAIN_H
|
||||
#define MAIN_H
|
||||
|
||||
#include "pluginspecs_video.h"
|
||||
|
||||
extern SVideoInitialize g_VideoInitialize;
|
||||
|
||||
#endif
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef MAIN_H
|
||||
#define MAIN_H
|
||||
|
||||
#include "pluginspecs_video.h"
|
||||
|
||||
extern SVideoInitialize g_VideoInitialize;
|
||||
|
||||
#endif
|
||||
|
@ -1,18 +1,18 @@
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "stdafx.h"
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "stdafx.h"
|
||||
|
@ -1,26 +1,26 @@
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#pragma once
|
||||
#define _WIN32_WINNT 0x501
|
||||
#ifndef _WIN32_IE
|
||||
#define _WIN32_IE 0x0500 // Default value is 0x0400
|
||||
#endif
|
||||
|
||||
#include <tchar.h>
|
||||
#include <windows.h>
|
||||
|
||||
// Copyright (C) 2003-2009 Dolphin 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.
|
||||
|
||||
// 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 SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#pragma once
|
||||
#define _WIN32_WINNT 0x501
|
||||
#ifndef _WIN32_IE
|
||||
#define _WIN32_IE 0x0500 // Default value is 0x0400
|
||||
#endif
|
||||
|
||||
#include <tchar.h>
|
||||
#include <windows.h>
|
||||
|
||||
|
Reference in New Issue
Block a user