summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/video_core/src/renderer_opengl/renderer_opengl.cpp159
-rw-r--r--src/video_core/src/renderer_opengl/renderer_opengl.h8
2 files changed, 147 insertions, 20 deletions
diff --git a/src/video_core/src/renderer_opengl/renderer_opengl.cpp b/src/video_core/src/renderer_opengl/renderer_opengl.cpp
index 133740a74..27917a5a2 100644
--- a/src/video_core/src/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/src/renderer_opengl/renderer_opengl.cpp
@@ -22,9 +22,31 @@
22 * http://code.google.com/p/gekko-gc-emu/ 22 * http://code.google.com/p/gekko-gc-emu/
23 */ 23 */
24 24
25#include "mem_map.h"
25#include "video_core.h" 26#include "video_core.h"
26#include "renderer_opengl/renderer_opengl.h" 27#include "renderer_opengl/renderer_opengl.h"
27 28
29/**
30 * Helper function to flip framebuffer from left-to-right to top-to-bottom
31 * @param addr Address of framebuffer in RAM
32 * @param out Pointer to output buffer with flipped framebuffer
33 * @todo Early on hack... I'd like to find a more efficient way of doing this /bunnei
34 */
35inline void _flip_framebuffer(u32 addr, u8* out) {
36 u8* in = Memory::GetPointer(addr);
37 for (int y = 0; y < VideoCore::kScreenTopHeight; y++) {
38 for (int x = 0; x < VideoCore::kScreenTopWidth; x++) {
39 int in_coord = (VideoCore::kScreenTopHeight * 3 * x) + (VideoCore::kScreenTopHeight * 3)
40 - (3 * y + 3);
41 int out_coord = (VideoCore::kScreenTopWidth * y * 3) + (x * 3);
42
43 out[out_coord + 0] = in[in_coord + 0];
44 out[out_coord + 1] = in[in_coord + 1];
45 out[out_coord + 2] = in[in_coord + 2];
46 }
47 }
48}
49
28/// RendererOpenGL constructor 50/// RendererOpenGL constructor
29RendererOpenGL::RendererOpenGL() { 51RendererOpenGL::RendererOpenGL() {
30 memset(fbo_, 0, sizeof(fbo_)); 52 memset(fbo_, 0, sizeof(fbo_));
@@ -33,27 +55,28 @@ RendererOpenGL::RendererOpenGL() {
33 55
34 resolution_width_ = max(VideoCore::kScreenTopWidth, VideoCore::kScreenBottomWidth); 56 resolution_width_ = max(VideoCore::kScreenTopWidth, VideoCore::kScreenBottomWidth);
35 resolution_height_ = VideoCore::kScreenTopHeight + VideoCore::kScreenBottomHeight; 57 resolution_height_ = VideoCore::kScreenTopHeight + VideoCore::kScreenBottomHeight;
58
59 xfb_texture_top_ = 0;
60 xfb_texture_bottom_ = 0;
61
62 xfb_top_ = 0;
63 xfb_bottom_ = 0;
36} 64}
37 65
38/// RendererOpenGL destructor 66/// RendererOpenGL destructor
39RendererOpenGL::~RendererOpenGL() { 67RendererOpenGL::~RendererOpenGL() {
40} 68}
41 69
42
43/// Swap buffers (render frame) 70/// Swap buffers (render frame)
44void RendererOpenGL::SwapBuffers() { 71void RendererOpenGL::SwapBuffers() {
45 72
46 glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
47 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
48
49 ResetRenderState(); 73 ResetRenderState();
50 74
51 // EFB->XFB copy 75 // EFB->XFB copy
52 // TODO(bunnei): This is a hack and does not belong here. The copy should be triggered by some 76 // TODO(bunnei): This is a hack and does not belong here. The copy should be triggered by some
53 // register write We're also treating both framebuffers as a single one in OpenGL. 77 // register write We're also treating both framebuffers as a single one in OpenGL.
54 Rect framebuffer_size(0, 0, VideoCore::kScreenTopWidth, 78 Rect framebuffer_size(0, 0, resolution_width_, resolution_height_);
55 VideoCore::kScreenTopHeight + VideoCore::kScreenBottomHeight); 79 RenderXFB(framebuffer_size, framebuffer_size);
56 CopyToXFB(framebuffer_size, framebuffer_size);
57 80
58 // XFB->Window copy 81 // XFB->Window copy
59 RenderFramebuffer(); 82 RenderFramebuffer();
@@ -69,20 +92,34 @@ void RendererOpenGL::SwapBuffers() {
69} 92}
70 93
71/** 94/**
72 * Blits the EFB to the external framebuffer (XFB) 95 * Renders external framebuffer (XFB)
73 * @param src_rect Source rectangle in EFB to copy 96 * @param src_rect Source rectangle in XFB to copy
74 * @param dst_rect Destination rectangle in EFB to copy to 97 * @param dst_rect Destination rectangle in output framebuffer to copy to
75 * @param dest_height Destination height in pixels
76 */ 98 */
77void RendererOpenGL::CopyToXFB(const Rect& src_rect, const Rect& dst_rect) { 99void RendererOpenGL::RenderXFB(const Rect& src_rect, const Rect& dst_rect) {
100 static u8 xfb_top_flipped[VideoCore::kScreenTopWidth * VideoCore::kScreenTopWidth *3];
101 static u8 xfb_bottom_flipped[VideoCore::kScreenTopWidth * VideoCore::kScreenTopWidth *3];
102
103 _flip_framebuffer(0x20282160, xfb_top_flipped);
104 _flip_framebuffer(0x202118E0, xfb_bottom_flipped);
105
78 ResetRenderState(); 106 ResetRenderState();
79 107
108 // Blit the top framebuffer
109 // ------------------------
110
111 // Update textures with contents of XFB in RAM - top
112 glBindTexture(GL_TEXTURE_2D, xfb_texture_top_);
113 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, VideoCore::kScreenTopWidth, VideoCore::kScreenTopHeight,
114 GL_RGB, GL_UNSIGNED_BYTE, xfb_top_flipped);
115 glBindTexture(GL_TEXTURE_2D, 0);
116
80 // Render target is destination framebuffer 117 // Render target is destination framebuffer
81 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_[kFramebuffer_VirtualXFB]); 118 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_[kFramebuffer_VirtualXFB]);
82 glViewport(0, 0, resolution_width_, resolution_height_); 119 glViewport(0, 0, VideoCore::kScreenTopWidth, VideoCore::kScreenTopHeight);
83 120
84 // Render source is our EFB 121 // Render source is our EFB
85 glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo_[kFramebuffer_EFB]); 122 glBindFramebuffer(GL_READ_FRAMEBUFFER, xfb_top_);
86 glReadBuffer(GL_COLOR_ATTACHMENT0); 123 glReadBuffer(GL_COLOR_ATTACHMENT0);
87 124
88 // Blit 125 // Blit
@@ -92,9 +129,62 @@ void RendererOpenGL::CopyToXFB(const Rect& src_rect, const Rect& dst_rect) {
92 129
93 glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); 130 glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
94 131
132 // Blit the bottom framebuffer
133 // ---------------------------
134
135 // Update textures with contents of XFB in RAM - bottom
136 glBindTexture(GL_TEXTURE_2D, xfb_texture_bottom_);
137 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, VideoCore::kScreenTopWidth, VideoCore::kScreenTopHeight,
138 GL_RGB, GL_UNSIGNED_BYTE, xfb_bottom_flipped);
139 glBindTexture(GL_TEXTURE_2D, 0);
140
141 // Render target is destination framebuffer
142 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_[kFramebuffer_VirtualXFB]);
143 glViewport(0, 0,
144 VideoCore::kScreenBottomWidth, VideoCore::kScreenBottomHeight);
145
146 // Render source is our EFB
147 glBindFramebuffer(GL_READ_FRAMEBUFFER, xfb_bottom_);
148 glReadBuffer(GL_COLOR_ATTACHMENT0);
149
150 // Blit
151 int offset = (VideoCore::kScreenTopWidth - VideoCore::kScreenBottomWidth) / 2;
152 glBlitFramebuffer(0,0, VideoCore::kScreenBottomWidth, VideoCore::kScreenBottomHeight,
153 offset, VideoCore::kScreenBottomHeight, VideoCore::kScreenBottomWidth + offset, 0,
154 GL_COLOR_BUFFER_BIT, GL_LINEAR);
155
156 glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
157
95 RestoreRenderState(); 158 RestoreRenderState();
96} 159}
97 160
161/**
162 * Blits the EFB to the external framebuffer (XFB)
163 * @param src_rect Source rectangle in EFB to copy
164 * @param dst_rect Destination rectangle in EFB to copy to
165 */
166void RendererOpenGL::CopyToXFB(const Rect& src_rect, const Rect& dst_rect) {
167 ERROR_LOG(RENDER, "CopyToXFB not implemented! No EFB support yet!");
168 //ResetRenderState();
169
170 //// Render target is destination framebuffer
171 //glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_[kFramebuffer_VirtualXFB]);
172 //glViewport(0, 0, VideoCore::kScreenTopWidth, VideoCore::kScreenTopHeight);
173
174 //// Render source is our EFB
175 //glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo_[kFramebuffer_EFB]);
176 //glReadBuffer(GL_COLOR_ATTACHMENT0);
177
178 //// Blit
179 //glBlitFramebuffer(src_rect.x0_, src_rect.y0_, src_rect.x1_, src_rect.y1_,
180 // dst_rect.x0_, dst_rect.y1_, dst_rect.x1_, dst_rect.y0_,
181 // GL_COLOR_BUFFER_BIT, GL_LINEAR);
182
183 //glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
184
185 //RestoreRenderState();
186}
187
98/** 188/**
99 * Clear the screen 189 * Clear the screen
100 * @param rect Screen rectangle to clear 190 * @param rect Screen rectangle to clear
@@ -234,12 +324,13 @@ void RendererOpenGL::InitFramebuffer() {
234 for (int i = 0; i < kMaxFramebuffers; i++) { 324 for (int i = 0; i < kMaxFramebuffers; i++) {
235 // Generate color buffer storage 325 // Generate color buffer storage
236 glBindRenderbuffer(GL_RENDERBUFFER, fbo_rbo_[i]); 326 glBindRenderbuffer(GL_RENDERBUFFER, fbo_rbo_[i]);
237 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, resolution_width_, resolution_height_); 327 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, VideoCore::kScreenTopWidth,
328 VideoCore::kScreenTopHeight + VideoCore::kScreenBottomHeight);
238 329
239 // Generate depth buffer storage 330 // Generate depth buffer storage
240 glBindRenderbuffer(GL_RENDERBUFFER, fbo_depth_buffers_[i]); 331 glBindRenderbuffer(GL_RENDERBUFFER, fbo_depth_buffers_[i]);
241 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT32, resolution_width_, 332 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT32, VideoCore::kScreenTopWidth,
242 resolution_height_); 333 VideoCore::kScreenTopHeight + VideoCore::kScreenBottomHeight);
243 334
244 // Attach the buffers 335 // Attach the buffers
245 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_[i]); 336 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_[i]);
@@ -257,6 +348,37 @@ void RendererOpenGL::InitFramebuffer() {
257 } 348 }
258 } 349 }
259 glBindFramebuffer(GL_FRAMEBUFFER, 0); // Unbind our frame buffer(s) 350 glBindFramebuffer(GL_FRAMEBUFFER, 0); // Unbind our frame buffer(s)
351
352 // Initialize framebuffer textures
353 // -------------------------------
354
355 // Create XFB textures
356 glGenTextures(1, &xfb_texture_top_);
357 glGenTextures(1, &xfb_texture_bottom_);
358
359 // Alocate video memorry for XFB textures
360 glBindTexture(GL_TEXTURE_2D, xfb_texture_top_);
361 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, VideoCore::kScreenTopWidth, VideoCore::kScreenTopHeight,
362 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
363 glBindTexture(GL_TEXTURE_2D, 0);
364
365 glBindTexture(GL_TEXTURE_2D, xfb_texture_bottom_);
366 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, VideoCore::kScreenTopWidth, VideoCore::kScreenTopHeight,
367 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
368 glBindTexture(GL_TEXTURE_2D, 0);
369
370 // Create the FBO and attach color/depth textures
371 glGenFramebuffers(1, &xfb_top_); // Generate framebuffer
372 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, xfb_top_);
373 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
374 xfb_texture_top_, 0);
375 glBindFramebuffer(GL_FRAMEBUFFER, 0);
376
377 glGenFramebuffers(1, &xfb_bottom_); // Generate framebuffer
378 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, xfb_bottom_);
379 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
380 xfb_texture_bottom_, 0);
381 glBindFramebuffer(GL_FRAMEBUFFER, 0);
260} 382}
261 383
262/// Blit the FBO to the OpenGL default framebuffer 384/// Blit the FBO to the OpenGL default framebuffer
@@ -272,8 +394,7 @@ void RendererOpenGL::RenderFramebuffer() {
272 394
273 // Blit 395 // Blit
274 glBlitFramebuffer(0, 0, resolution_width_, resolution_height_, 0, 0, 396 glBlitFramebuffer(0, 0, resolution_width_, resolution_height_, 0, 0,
275 render_window_->client_area_width(), render_window_->client_area_height(), 397 resolution_width_, resolution_height_, GL_COLOR_BUFFER_BIT, GL_LINEAR);
276 GL_COLOR_BUFFER_BIT, GL_LINEAR);
277 398
278 // Update the FPS count 399 // Update the FPS count
279 UpdateFramerate(); 400 UpdateFramerate();
diff --git a/src/video_core/src/renderer_opengl/renderer_opengl.h b/src/video_core/src/renderer_opengl/renderer_opengl.h
index f9fb89d50..b84afc5d2 100644
--- a/src/video_core/src/renderer_opengl/renderer_opengl.h
+++ b/src/video_core/src/renderer_opengl/renderer_opengl.h
@@ -45,10 +45,16 @@ public:
45 void SwapBuffers(); 45 void SwapBuffers();
46 46
47 /** 47 /**
48 * Renders external framebuffer (XFB)
49 * @param src_rect Source rectangle in XFB to copy
50 * @param dst_rect Destination rectangle in output framebuffer to copy to
51 */
52 void RenderXFB(const Rect& src_rect, const Rect& dst_rect);
53
54 /**
48 * Blits the EFB to the external framebuffer (XFB) 55 * Blits the EFB to the external framebuffer (XFB)
49 * @param src_rect Source rectangle in EFB to copy 56 * @param src_rect Source rectangle in EFB to copy
50 * @param dst_rect Destination rectangle in EFB to copy to 57 * @param dst_rect Destination rectangle in EFB to copy to
51 * @param dest_height Destination height in pixels
52 */ 58 */
53 void CopyToXFB(const Rect& src_rect, const Rect& dst_rect); 59 void CopyToXFB(const Rect& src_rect, const Rect& dst_rect);
54 60