forked from dolphin-emu/dolphin
		
	git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4410 8ced0084-cf51-0410-be5f-012b33b47a6e
		
			
				
	
	
		
			192 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			192 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| // 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[0] / efbHalfWidth - 1.0f, 1.0f - v->screenPosition[1] / efbHalfHeight, v->screenPosition[2]);
 | |
|     }
 | |
| 
 | |
|     void DrawTextureVertex(OutputVertexData *v)
 | |
|     {
 | |
|         glTexCoord2f(v->texCoords[0][0] * texWidth, v->texCoords[0][1] * texHeight);
 | |
|         glVertex3f(v->screenPosition[0] / efbHalfWidth - 1.0f, 1.0f - v->screenPosition[1] / efbHalfHeight, v->screenPosition[2]);
 | |
|     }
 | |
| 
 | |
|     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, 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();
 | |
|         }
 | |
|     }
 | |
| 
 | |
| }
 | |
| 
 |