11c6e79bd3149ce30c201fa6faf7da10a11a289c
[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, get_screen_size());
92 }
93
94 const Rect &get_clipping_rect()
95 {
96         return gfx->clipping_rect;
97 }
98
99
100 void set_cursor_visibility(bool visible)
101 {
102 }
103
104 void gfx_update(const Rect &upd_rect)
105 {
106         if(SDL_MUSTLOCK(fbsurf)) {
107                 SDL_LockSurface(fbsurf);
108         }
109
110         Rect rect = rect_intersection(upd_rect, gfx->screen_rect);
111
112         unsigned char *sptr = gfx->pixmap->pixels + (rect.y * gfx->screen_rect.width + rect.x) * 4;
113         unsigned char *dptr = (unsigned char*)fbsurf->pixels + (rect.y * gfx->screen_rect.width + rect.x) * 4;
114
115         for(int i=0; i<rect.height; i++) {
116                 memcpy(dptr, sptr, rect.width * 4);
117                 sptr += gfx->screen_rect.width * 4;
118                 dptr += gfx->screen_rect.width * 4;
119         }
120
121         if(SDL_MUSTLOCK(fbsurf)) {
122                 SDL_UnlockSurface(fbsurf);
123         }
124         SDL_UpdateRect(fbsurf, rect.x, rect.y, rect.width, rect.height);
125 }
126
127 void wait_vsync()
128 {
129 }
130
131 void get_rgb_order(int *r, int *g, int *b)
132 {
133         *r = fbsurf->format->Rshift / 8;
134         *g = fbsurf->format->Gshift / 8;
135         *b = fbsurf->format->Bshift / 8;
136 }
137
138 #endif // WINNIE_SDL