added memory allocator
[winnie] / src / sdl / gfx.cc
1 #ifdef WINNIE_SDL
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <SDL/SDL.h>
5
6 #include "gfx.h"
7 #include "shalloc.h"
8
9 static SDL_Surface *fbsurf;
10
11 struct Graphics {
12         Rect screen_rect;
13         Rect clipping_rect;
14         int color_depth; // bits per pixel
15         Pixmap *pixmap;
16 };
17
18 static Graphics *gfx;
19
20 bool init_gfx()
21 {
22         if(SDL_Init(SDL_INIT_VIDEO) == -1) {
23                 fprintf(stderr, "failed to initialize SDL\n");
24                 return false;
25         }
26
27         if(!(gfx = (Graphics*)sh_malloc(sizeof *gfx))) {
28                 return false;
29         }
30
31         Rect scr_rect = {0, 0, 1024, 768};
32         gfx->screen_rect = scr_rect;
33         gfx->color_depth = 32;
34
35         if(!(fbsurf = SDL_SetVideoMode(gfx->screen_rect.width, gfx->screen_rect.height, gfx->color_depth, 0))) {
36                 fprintf(stderr, "Failed to set video mode\n");
37                 return false;
38         }
39         SDL_ShowCursor(0);
40
41         if(!(gfx->pixmap = (Pixmap*)sh_malloc(sizeof(Pixmap)))) {
42                 fprintf(stderr, "Failed to allocate pixmap.\n");
43                 return false;
44         }
45
46         gfx->pixmap->width = gfx->screen_rect.width;
47         gfx->pixmap->height = gfx->screen_rect.height;
48
49         int fbsize = gfx->pixmap->width * gfx->pixmap->height * gfx->color_depth / 8;
50         if(!(gfx->pixmap->pixels = (unsigned char*)sh_malloc(fbsize))) {
51                 fprintf(stderr, "failed to allocate the pixmap framebuffer.\n");
52                 return false;
53         }
54
55         set_clipping_rect(gfx->screen_rect);
56
57         return true;
58 }
59
60 void destroy_gfx()
61 {
62         sh_free(gfx->pixmap->pixels);
63         gfx->pixmap->pixels = 0;
64         sh_free(gfx->pixmap);
65         sh_free(gfx);
66         SDL_Quit();
67 }
68
69 unsigned char *get_framebuffer()
70 {
71         return gfx->pixmap->pixels;
72 }
73
74 Pixmap *get_framebuffer_pixmap()
75 {
76         return gfx->pixmap;
77 }
78
79 Rect get_screen_size()
80 {
81         return gfx->screen_rect;
82 }
83
84 int get_color_depth()
85 {
86         return gfx->color_depth;
87 }
88
89 /*void set_clipping_rect(const Rect &rect)
90 {
91         gfx->clipping_rect = rect_intersection(rect, gfx->screen_rect);
92
93         SDL_Rect sdl_rect;
94         sdl_rect.x = gfx->clipping_rect.x;
95         sdl_rect.y = gfx->clipping_rect.y;
96         sdl_rect.w = gfx->clipping_recvoid fill_rect(const Rect &rect, int r, int g, int b)
97 {
98         Rect drect = rect;
99         Rect screen_rect = get_screen_size();
100
101         if(drect.x < clipping_rect.x) {
102                 drect.width -= clipping_rect.x - drect.x;
103                 drect.x = clipping_rect.x;
104         }
105
106         if(drect.y < clipping_rect.y) {
107                 drect.height -= clipping_rect.y - drect.y;
108                 drect.y = clipping_rect.y;
109         }
110
111         if(drect.x + drect.width >= clipping_rect.x + clipping_rect.width) {
112                 drect.width = clipping_rect.width + clipping_rect.x - drect.x;
113         }
114
115         if(drect.y + drect.height >= clipping_rect.y + clipping_rect.height) {
116                 drect.height = clipping_rect.height + clipping_rect.y - drect.y;
117         }
118
119         unsigned char *fb = get_framebuffer() + (drect.x + screen_rect.width * drect.y) * 4;
120         for(int i=0; i<drect.height; i++) {
121                 for(int j=0; j<drect.width; j++) {
122                         fb[j * 4] = b;
123                         fb[j * 4 + 1] = g;
124                         fb[j * 4 + 2] = r;
125                 }
126                 fb += screen_rect.width * 4;
127         }
128 }
129 t.width;
130         sdl_rect.h = gfx->clipping_rect.height;
131
132         SDL_SetClipRect(fbsurf, &sdl_rect);
133 }
134
135 const Rect &get_clipping_rect()
136 {
137         return gfx->clipping_rect;
138 }
139
140 void clear_screen(int r, int g, int b)
141 {
142         fill_rect(gfx->screen_rect, r, g, b);
143 }
144
145 void fill_rect(const Rect &rect, int r, int g, int b)
146 {
147         uint32_t color = ((r & 0xff) << 16) | ((g & 0xff) << 8) | (b & 0xff);
148         
149         SDL_Rect sdl_rect;
150         sdl_rect.x = rect.x;
151         sdl_rect.y = rect.y;
152         sdl_rect.w = rect.width;
153         sdl_rect.h = rect.height;
154
155         SDL_FillRect(fbsurf, &sdl_rect, color);
156 }*/
157
158 void set_clipping_rect(const Rect &rect)
159 {
160         gfx->clipping_rect = rect_intersection(rect, get_screen_size());
161 }
162
163 const Rect &get_clipping_rect()
164 {
165         return gfx->clipping_rect;
166 }
167
168
169 void set_cursor_visibility(bool visible)
170 {
171 }
172
173 void gfx_update()
174 {
175         if(SDL_MUSTLOCK(fbsurf)) {
176                 SDL_LockSurface(fbsurf);
177         }
178         memcpy(fbsurf->pixels, gfx->pixmap->pixels, gfx->pixmap->width * gfx->pixmap->height * (gfx->color_depth / 8));
179         if(SDL_MUSTLOCK(fbsurf)) {
180                 SDL_UnlockSurface(fbsurf);
181         }
182         SDL_UpdateRect(fbsurf, 0, 0, 0, 0);
183 }
184
185 void wait_vsync()
186 {
187 }
188
189 #endif // WINNIE_SDL