gpu_neon: flush cmd buffer before blit too
[pcsx_rearmed.git] / plugins / gpu_neon / vout_fb.c
1 /*
2  * (C) GraÅžvydas "notaz" Ignotas, 2011
3  *
4  * This work is licensed under the terms of any of these licenses
5  * (at your option):
6  *  - GNU GPL, version 2 or later.
7  *  - GNU LGPL, version 2.1 or later.
8  * See the COPYING file in the top-level directory.
9  */
10
11 #include "gpu.h"
12 #include "../../frontend/plugin_lib.h"
13 #include "../../frontend/cspace.h"
14
15 static const struct rearmed_cbs *cbs;
16 static void *screen_buf;
17
18 int vout_init(void)
19 {
20   return 0;
21 }
22
23 int vout_finish(void)
24 {
25   return 0;
26 }
27
28 static void check_mode_change(void)
29 {
30   static uint32_t old_status;
31   static int old_h;
32
33   // width|rgb24 change?
34   if ((gpu.status.reg ^ old_status) & ((7<<16)|(1<<21)) || gpu.screen.h != old_h)
35   {
36     old_status = gpu.status.reg;
37     old_h = gpu.screen.h;
38     screen_buf = cbs->pl_vout_set_mode(gpu.screen.hres,
39                                        gpu.screen.h, gpu.status.rgb24 ? 24 : 16);
40   }
41 }
42
43 static void blit(void)
44 {
45   int x = gpu.screen.x & ~1; // alignment needed by blitter
46   int y = gpu.screen.y;
47   int w = gpu.screen.w;
48   int h = gpu.screen.h;
49   uint16_t *vram = gpu.vram;
50   int stride = gpu.screen.hres;
51   int fb_offs, doffs;
52   uint8_t *dest;
53
54   fb_offs = y * 1024 + x;
55   dest = (uint8_t *)screen_buf;
56
57   // only do centering, at least for now
58   doffs = (stride - w) / 2 & ~1;
59
60   if (gpu.status.rgb24)
61   {
62 #ifndef MAEMO
63     dest += (doffs / 8) * 24;
64     for (; h-- > 0; dest += stride * 3, fb_offs += 1024)
65     {
66       fb_offs &= 1024*512-1;
67       bgr888_to_rgb888(dest, vram + fb_offs, w * 3);
68     }
69 #else
70     dest += doffs * 2;
71     for (; h-- > 0; dest += stride * 2, fb_offs += 1024)
72     {
73       fb_offs &= 1024*512-1;
74       bgr888_to_rgb565(dest, vram + fb_offs, w * 3);
75     }
76 #endif
77   }
78   else
79   {
80     dest += doffs * 2;
81     for (; h-- > 0; dest += stride * 2, fb_offs += 1024)
82     {
83       fb_offs &= 1024*512-1;
84       bgr555_to_rgb565(dest, vram + fb_offs, w * 2);
85     }
86   }
87
88   screen_buf = cbs->pl_vout_flip();
89 }
90
91 void GPUupdateLace(void)
92 {
93   if (gpu.status.blanking || !gpu.state.fb_dirty)
94     return;
95
96   if (gpu.frameskip.set) {
97     if (!gpu.frameskip.frame_ready) {
98       if (*gpu.state.frame_count - gpu.frameskip.last_flip_frame < 9)
99         return;
100     }
101     gpu.frameskip.frame_ready = 0;
102   }
103
104   if (gpu.cmd_len > 0)
105     flush_cmd_buffer();
106   renderer_flush_queues();
107   check_mode_change();
108   if (cbs->pl_vout_raw_flip)
109     cbs->pl_vout_raw_flip(gpu.screen.x, gpu.screen.y);
110   else
111     blit();
112   gpu.state.fb_dirty = 0;
113 }
114
115 long GPUopen(void **unused)
116 {
117   gpu.frameskip.active = 0;
118   gpu.frameskip.frame_ready = 1;
119
120   cbs->pl_vout_open();
121   screen_buf = cbs->pl_vout_flip();
122   return 0;
123 }
124
125 long GPUclose(void)
126 {
127   cbs->pl_vout_close();
128   return 0;
129 }
130
131 void GPUrearmedCallbacks(const struct rearmed_cbs *cbs_)
132 {
133   cbs = cbs_;
134   gpu.frameskip.set = cbs->frameskip;
135   gpu.frameskip.advice = &cbs->fskip_advice;
136   gpu.frameskip.active = 0;
137   gpu.frameskip.frame_ready = 1;
138   gpu.state.hcnt = cbs->gpu_hcnt;
139   gpu.state.frame_count = cbs->gpu_frame_count;
140
141   if (cbs->pl_vout_set_raw_vram)
142     cbs->pl_vout_set_raw_vram(gpu.vram);
143   renderer_set_config(cbs_);
144 }
145
146 // vim:shiftwidth=2:expandtab