1 #include <stdint.h>
2 #include <stdlib.h>
3 
4 #include "OpenGL.h"
5 #include "FrameBuffer.h"
6 #include "RSP.h"
7 #include "RDP.h"
8 #include "Textures.h"
9 #include "ShaderCombiner.h"
10 #include "VI.h"
11 
12 struct FrameBufferInfo frameBuffer;
13 CachedTexture *g_RDRAMtoFB;
14 
FrameBuffer_Init(void)15 void FrameBuffer_Init(void)
16 {
17    frameBuffer.current = NULL;
18    frameBuffer.top = NULL;
19    frameBuffer.bottom = NULL;
20    frameBuffer.numBuffers = 0;
21 }
22 
FrameBuffer_RemoveBottom(void)23 void FrameBuffer_RemoveBottom(void)
24 {
25    struct FrameBuffer *newBottom = (struct FrameBuffer*)
26       frameBuffer.bottom->higher;
27 
28    TextureCache_Remove( frameBuffer.bottom->texture );
29 
30    if (frameBuffer.bottom == frameBuffer.top)
31       frameBuffer.top = NULL;
32 
33    free( frameBuffer.bottom );
34 
35    frameBuffer.bottom = newBottom;
36 
37    if (frameBuffer.bottom != NULL)
38       frameBuffer.bottom->lower = NULL;
39 
40    frameBuffer.numBuffers--;
41 }
42 
FrameBuffer_Remove(struct FrameBuffer * buffer)43 void FrameBuffer_Remove( struct FrameBuffer *buffer )
44 {
45    if ((buffer == frameBuffer.bottom) &&
46          (buffer == frameBuffer.top))
47    {
48       frameBuffer.top = NULL;
49       frameBuffer.bottom = NULL;
50    }
51    else if (buffer == frameBuffer.bottom)
52    {
53       frameBuffer.bottom = buffer->higher;
54 
55       if (frameBuffer.bottom)
56          frameBuffer.bottom->lower = NULL;
57    }
58    else if (buffer == frameBuffer.top)
59    {
60       frameBuffer.top = buffer->lower;
61 
62       if (frameBuffer.top)
63          frameBuffer.top->higher = NULL;
64    }
65    else
66    {
67       buffer->higher->lower = buffer->lower;
68       buffer->lower->higher = buffer->higher;
69    }
70 
71    if (buffer->texture)
72       TextureCache_Remove( buffer->texture );
73 
74    free( buffer );
75 
76    frameBuffer.numBuffers--;
77 }
78 
FrameBuffer_RemoveBuffer(uint32_t address)79 void FrameBuffer_RemoveBuffer( uint32_t address )
80 {
81    struct FrameBuffer *current = (struct FrameBuffer*)frameBuffer.bottom;
82 
83    while (current != NULL)
84    {
85       if (current->m_startAddress == address)
86       {
87          current->texture = NULL;
88          FrameBuffer_Remove( current );
89          return;
90       }
91       current = current->higher;
92    }
93 }
94 
FrameBuffer_AddTop(void)95 struct FrameBuffer *FrameBuffer_AddTop(void)
96 {
97    struct FrameBuffer *newtop = (struct FrameBuffer*)malloc( sizeof(struct FrameBuffer ) );
98 
99    newtop->texture = TextureCache_AddTop();
100 
101    newtop->lower = frameBuffer.top;
102    newtop->higher = NULL;
103 
104    if (frameBuffer.top)
105       frameBuffer.top->higher = newtop;
106 
107    if (!frameBuffer.bottom)
108       frameBuffer.bottom = newtop;
109 
110    frameBuffer.top = newtop;
111 
112    frameBuffer.numBuffers++;
113 
114    return newtop;
115 }
116 
FrameBuffer_MoveToTop(struct FrameBuffer * newtop)117 void FrameBuffer_MoveToTop( struct FrameBuffer *newtop )
118 {
119    if (newtop == frameBuffer.top)
120       return;
121 
122    if (newtop == frameBuffer.bottom)
123    {
124       frameBuffer.bottom = newtop->higher;
125       frameBuffer.bottom->lower = NULL;
126    }
127    else
128    {
129       newtop->higher->lower = newtop->lower;
130       newtop->lower->higher = newtop->higher;
131    }
132 
133    newtop->higher = NULL;
134    newtop->lower = frameBuffer.top;
135    frameBuffer.top->higher = newtop;
136    frameBuffer.top = newtop;
137 
138    TextureCache_MoveToTop( newtop->texture );
139 }
140 
FrameBuffer_Destroy(void)141 void FrameBuffer_Destroy(void)
142 {
143    while (frameBuffer.bottom)
144       FrameBuffer_RemoveBottom();
145 }
146 
FrameBuffer_SaveBuffer(uint32_t address,uint16_t format,uint16_t size,uint16_t width,uint16_t height,bool unknown)147 void FrameBuffer_SaveBuffer( uint32_t address, uint16_t format, uint16_t size, uint16_t width, uint16_t height, bool unknown)
148 {
149    struct FrameBuffer *current = frameBuffer.top;
150 
151    if (width != VI.width && height == 0)
152       return;
153 
154    (void)format;
155    (void)unknown;
156 
157    /* Search through saved frame buffers */
158    while (current != NULL)
159    {
160       if ((current->m_startAddress == address) &&
161             (current->m_width == width) &&
162             (current->m_height == height) &&
163             (current->m_size == size))
164       {
165          if ((current->m_scaleX != OGL.scaleX) ||
166                (current->m_scaleY != OGL.scaleY))
167          {
168             FrameBuffer_Remove( current );
169             break;
170          }
171 
172          /* code goes here */
173          *(uint32_t*)&gfx_info.RDRAM[current->m_startAddress] = current->m_startAddress;
174 
175          current->m_changed = true;
176 
177          FrameBuffer_MoveToTop( current );
178 
179          gSP.changed |= CHANGED_TEXTURE;
180          return;
181       }
182       current = current->lower;
183    }
184 
185    /* Wasn't found, create a new one */
186    current = FrameBuffer_AddTop();
187 
188    current->m_startAddress = address;
189    current->m_endAddress = address + ((width * height << size >> 1) - 1);
190    current->m_width = width;
191    current->m_height = height;
192    current->m_size = size;
193    current->m_scaleX = OGL.scaleX;
194    current->m_scaleY = OGL.scaleY;
195 
196    current->texture->width = current->m_width * OGL.scaleX;
197    current->texture->height = current->m_height * OGL.scaleY;
198    current->texture->clampS = 1;
199    current->texture->clampT = 1;
200    current->texture->address = current->m_startAddress;
201    current->texture->clampWidth = current->m_width;
202    current->texture->clampHeight = current->m_height;
203    current->texture->frameBufferTexture = true;
204    current->texture->maskS = 0;
205    current->texture->maskT = 0;
206    current->texture->mirrorS = 0;
207    current->texture->mirrorT = 0;
208    current->texture->realWidth = pow2( current->m_width * OGL.scaleX );
209    current->texture->realHeight = pow2( current->m_height * OGL.scaleY );
210    current->texture->textureBytes = current->texture->realWidth * current->texture->realHeight * 4;
211    cache.cachedBytes += current->texture->textureBytes;
212 
213    /* code goes here - just bind texture and copy it over */
214    *(uint32_t*)&gfx_info.RDRAM[current->m_startAddress] = current->m_startAddress;
215 
216    current->m_changed = true;
217 
218    gSP.changed |= CHANGED_TEXTURE;
219 }
220 
FrameBuffer_GetCurrent(void)221 struct FrameBuffer *FrameBuffer_GetCurrent(void)
222 {
223    return (struct FrameBuffer*)frameBuffer.top;
224 }
225 
FrameBuffer_RenderBuffer(uint32_t address)226 void FrameBuffer_RenderBuffer( uint32_t address )
227 {
228    struct FrameBuffer *current = (struct FrameBuffer*)frameBuffer.top;
229 
230    while (current != NULL)
231    {
232       if ((current->m_startAddress <= address) &&
233             (current->m_endAddress >= address))
234       {
235          /* code goes here */
236 
237          current->m_changed = false;
238 
239          FrameBuffer_MoveToTop( current );
240 
241          gSP.changed |= CHANGED_TEXTURE | CHANGED_VIEWPORT;
242          gDP.changed |= CHANGED_COMBINE;
243          return;
244       }
245       current = current->lower;
246    }
247 }
248 
FrameBuffer_RestoreBuffer(uint32_t address,uint16_t size,uint16_t width)249 void FrameBuffer_RestoreBuffer( uint32_t address, uint16_t size, uint16_t width )
250 {
251    struct FrameBuffer *current = (struct FrameBuffer*)frameBuffer.top;
252 
253    while (current != NULL)
254    {
255       if ((current->m_startAddress == address) &&
256             (current->m_width == width) &&
257             (current->m_size == size))
258       {
259 
260          /* code goes here */
261 
262          FrameBuffer_MoveToTop( current );
263 
264          gSP.changed |= CHANGED_TEXTURE | CHANGED_VIEWPORT;
265          gDP.changed |= CHANGED_COMBINE;
266          return;
267       }
268       current = current->lower;
269    }
270 }
271 
FrameBuffer_FindBuffer(uint32_t address)272 struct FrameBuffer *FrameBuffer_FindBuffer( uint32_t address )
273 {
274    struct FrameBuffer *current = (struct FrameBuffer*)frameBuffer.top;
275 
276    while (current)
277    {
278       if ((current->m_startAddress <= address) &&
279             (current->m_endAddress >= address))
280          return current;
281       current = current->lower;
282    }
283 
284    return NULL;
285 }
286 
FrameBuffer_ActivateBufferTexture(int16_t t,struct FrameBuffer * buffer)287 void FrameBuffer_ActivateBufferTexture( int16_t t, struct FrameBuffer *buffer )
288 {
289    buffer->texture->scaleS = OGL.scaleX / (float)buffer->texture->realWidth;
290    buffer->texture->scaleT = OGL.scaleY / (float)buffer->texture->realHeight;
291 
292    if (gSP.textureTile[t]->shifts > 10)
293       buffer->texture->shiftScaleS = (float)(1 << (16 - gSP.textureTile[t]->shifts));
294    else if (gSP.textureTile[t]->shifts > 0)
295       buffer->texture->shiftScaleS = 1.0f / (float)(1 << gSP.textureTile[t]->shifts);
296    else
297       buffer->texture->shiftScaleS = 1.0f;
298 
299    if (gSP.textureTile[t]->shiftt > 10)
300       buffer->texture->shiftScaleT = (float)(1 << (16 - gSP.textureTile[t]->shiftt));
301    else if (gSP.textureTile[t]->shiftt > 0)
302       buffer->texture->shiftScaleT = 1.0f / (float)(1 << gSP.textureTile[t]->shiftt);
303    else
304       buffer->texture->shiftScaleT = 1.0f;
305 
306    if (gDP.loadTile->loadType == LOADTYPE_TILE)
307    {
308       buffer->texture->offsetS = gDP.loadTile->uls;
309       buffer->texture->offsetT = (float)buffer->m_height -
310          (gDP.loadTile->ult + (gDP.textureImage.address - buffer->m_startAddress) / (buffer->m_width << buffer->m_size >> 1));
311    }
312    else
313    {
314       buffer->texture->offsetS = 0.0f;
315       buffer->texture->offsetT = (float)buffer->m_height - (gDP.textureImage.address - buffer->m_startAddress) / (buffer->m_width << buffer->m_size >> 1);
316    }
317 
318    FrameBuffer_MoveToTop( buffer );
319    TextureCache_ActivateTexture( t, buffer->texture );
320 	gDP.changed |= CHANGED_FB_TEXTURE;
321 }
322 
FrameBuffer_ActivateBufferTextureBG(int16_t t,struct FrameBuffer * buffer)323 void FrameBuffer_ActivateBufferTextureBG(int16_t t, struct FrameBuffer *buffer )
324 {
325 	if (buffer == NULL || buffer->texture == NULL)
326 		return;
327 
328    buffer->texture->scaleS = OGL.scaleX / (float)buffer->texture->realWidth;
329    buffer->texture->scaleT = OGL.scaleY / (float)buffer->texture->realHeight;
330 
331 	buffer->texture->shiftScaleS = 1.0f;
332 	buffer->texture->shiftScaleT = 1.0f;
333 
334 	buffer->texture->offsetS = gSP.bgImage.imageX;
335 	buffer->texture->offsetT = (float)buffer->m_height - gSP.bgImage.imageY;
336 
337    FrameBuffer_MoveToTop( buffer );
338    TextureCache_ActivateTexture( t, buffer->texture );
339 	gDP.changed |= CHANGED_FB_TEXTURE;
340 }
341 
FrameBuffer_CopyFromRDRAM(uint32_t _address,bool _bUseAlpha)342 void FrameBuffer_CopyFromRDRAM( uint32_t _address, bool _bUseAlpha )
343 {
344    /* stub */
345 }
346 
FrameBuffer_CopyToRDRAM(uint32_t _address)347 void FrameBuffer_CopyToRDRAM( uint32_t _address )
348 {
349    /* stub */
350 }
351 
FrameBuffer_CopyDepthBuffer(uint32_t _address)352 void FrameBuffer_CopyDepthBuffer( uint32_t _address )
353 {
354    /* stub */
355 }
356