7 #define TRECT(x,y,w,h, tw, th) glBegin(GL_TRIANGLE_STRIP);glTexCoord2f(0.0,h/th);glVertex2f(x, y+1*h);glTexCoord2f(0.0,0.0);glVertex2f(x, y);glTexCoord2f(w/tw,h/th);glVertex2f(x+1*w, y+1*h);glTexCoord2f(w/tw,0.0);glVertex2f(x+1*w, y);glEnd();
10 unsigned int occupied
=0;
14 unsigned int allocated
;
17 SurfaceList gsprite_surfaces
;
18 int AddSurface(GLuint s
);
19 void RemoveSurface(GLuint s
);
20 void RemoveSID(int SID
);
21 void FlushSpriteSurfaces();
22 int SetVideoMode(int width
, int height
);
27 unsigned int allocated
;
31 int AddSprite(Sprite
*s
);
32 void RemoveSprite(Sprite
*s
);
42 SpriteQueueItem
*items
;
43 unsigned int allocated
;
46 SpriteQueue gsprite_queue
;
47 SpriteQueue gsprite_queue_sorted
;
48 void FlushSpriteQueue();
49 void RotateSurface(int SID
, int rotation
);
53 GLuint
load_svg (char *file
, int width
, int height
, double *pdw
, double *pdh
);
59 return (x
/(double)SCREEN_WIDTH
)*GetConfig().screen_width
;
62 return (y
/(double)SCREEN_HEIGHT
)*GetConfig().screen_height
;
65 int SetVideoMode(int width
, int height
){
72 Config config
=GetConfig();
74 SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER
, 1 );
77 flags
= flags
|SDL_FULLSCREEN
;
78 /* Get available fullscreen/hardware modes */
79 modes
=SDL_ListModes(NULL
, flags
);
81 /* Check if there are any modes available */
82 if(modes
== (SDL_Rect
**)0){
83 printf("No modes available!\n");
87 /* Check if our resolution is restricted */
88 if(modes
== (SDL_Rect
**)-1){
89 printf("All resolutions available.\n");
90 gscreen
= SDL_SetVideoMode(config
.screen_width
, config
.screen_height
, 0, flags
);
93 /* Print valid modes */
94 printf("Available Modes\n");
95 bestdif
= abs((modes
[0]->w
- config
.screen_width
) + (modes
[0]->h
- config
.screen_height
));
97 for(i
=0;modes
[i
];++i
){
98 printf(" %d x %d\n", modes
[i
]->w
, modes
[i
]->h
);
99 if(bestdif
> abs((modes
[i
]->w
- config
.screen_width
) + (modes
[i
]->h
- config
.screen_height
))){
100 bestdif
= abs((modes
[i
]->w
- config
.screen_width
) + (modes
[i
]->h
- config
.screen_height
));
104 printf("Using: %d x %d\n", modes
[ibest
]->w
, modes
[ibest
]->h
);
105 gscreen
= SDL_SetVideoMode(modes
[ibest
]->w
, modes
[ibest
]->h
, 0, flags
);
106 config
.screen_height
= modes
[ibest
]->h
;
107 config
.screen_width
= modes
[ibest
]->w
;
112 int AddSurface(GLuint s
){ //returns -1 on error, SID if success
115 for(i
=0;i
<gsprite_surfaces
.allocated
;i
++)
116 if( gsprite_surfaces
.surfaces
[i
]==s
){
120 for(i
=0;i
<gsprite_surfaces
.allocated
;i
++)
121 if( gsprite_surfaces
.surfaces
[i
]==0 ){
122 gsprite_surfaces
.surfaces
[i
]=s
;
125 i
=gsprite_surfaces
.allocated
;
126 tmp
= (GLuint
*) realloc(gsprite_surfaces
.surfaces
, sizeof(GLuint
)*i
*2); //if the allocated space is not wide enough, then allocate double space than previous
129 gsprite_surfaces
.surfaces
=tmp
;
130 memset(&gsprite_surfaces
.surfaces
[i
],0, sizeof(GLuint
)*i
); //zero newly allocated space
131 gsprite_surfaces
.allocated
=i
*2;
132 gsprite_surfaces
.surfaces
[i
]=s
;
136 void RemoveSurface(GLuint s
){
137 int i
,iwannakillyoubitch
;
139 iwannakillyoubitch
=1;
140 for(i
=0;i
<gsprite_surfaces
.allocated
;i
++){
141 if( gsprite_surfaces
.surfaces
[i
]==s
){
142 gsprite_surfaces
.surfaces
[i
]=0;
144 if( i
>=gsprite_surfaces
.allocated
/2 && iwannakillyoubitch
&& gsprite_surfaces
.surfaces
[i
]!=0 )
145 iwannakillyoubitch
=0;
148 if(iwannakillyoubitch
){
149 gsprite_surfaces
.allocated
/=2;
150 gsprite_surfaces
.surfaces
= (GLuint
*)realloc(gsprite_surfaces
.surfaces
, sizeof(GLuint
)*gsprite_surfaces
.allocated
);//TODO:check return value
154 void RemoveSID(int SID
){
155 int i
,iwannakillyoubitch
;
157 iwannakillyoubitch
=1;
158 for(i
=0;i
<gsprite_surfaces
.allocated
;i
++){
160 gsprite_surfaces
.surfaces
[i
]=0;
162 if( i
>=gsprite_surfaces
.allocated
/2 && iwannakillyoubitch
&& gsprite_surfaces
.surfaces
[i
]!=0 )
163 iwannakillyoubitch
=0;
166 if(iwannakillyoubitch
){
167 gsprite_surfaces
.allocated
/=2;
168 gsprite_surfaces
.surfaces
= (GLuint
*)realloc(gsprite_surfaces
.surfaces
, sizeof(GLuint
)*gsprite_surfaces
.allocated
);//TODO:check return value
172 int AddSprite(Sprite
*s
){//returns 0 on error, Sprite ID on success
175 for(i
=0;i
<gsprites
.allocated
;i
++)
176 if( gsprites
.sprites
[i
]==s
){
180 for(i
=0;i
<gsprites
.allocated
;i
++)
181 if( gsprites
.sprites
[i
]==0 ){
182 gsprites
.sprites
[i
]=s
;
185 i
=gsprites
.allocated
;
186 tmp
=(Sprite
**)realloc(gsprites
.sprites
, sizeof(Sprite
*)*i
*2); //if the allocated space is not wide enough, then allocate double space than previous
189 gsprites
.sprites
=tmp
;
190 memset(&gsprites
.sprites
[i
],0, sizeof(Sprite
*)*i
); //zero newly allocated space
191 gsprites
.allocated
=i
*2;
192 gsprites
.sprites
[i
]=s
;
196 void RemoveSprite(Sprite
*s
){
197 int i
,iwannakillyoubitch
;
199 iwannakillyoubitch
=1;
200 for(i
=0;i
<gsprites
.allocated
;i
++){
201 if( gsprites
.sprites
[i
]==s
){
202 gsprites
.sprites
[i
]=0;
204 if( i
>=gsprites
.allocated
/2 && iwannakillyoubitch
&& gsprites
.sprites
[i
]!=0 )
205 iwannakillyoubitch
=0;
208 if(iwannakillyoubitch
){
209 gsprites
.allocated
/=2;
210 gsprites
.sprites
= (Sprite
**) realloc(gsprites
.sprites
, sizeof(Sprite
*)*gsprites
.allocated
);//TODO:check return value
219 FlushSpriteSurfaces();
222 free(gsprite_surfaces
.surfaces
);
223 gsprite_surfaces
.surfaces
=0;
226 for(i
=0; i
<gsprites
.allocated
; i
++)
227 if(gsprites
.sprites
[i
]){
228 free(gsprites
.sprites
[i
]->fname
);
229 free(gsprites
.sprites
[i
]);
230 gsprites
.sprites
[i
]=0;
233 gsprites
.allocated
= 0;
236 SetVideoMode(config
.screen_width
, config
.screen_height
);
245 gsprite_surfaces
.surfaces
= (GLuint
*) calloc(2, sizeof(GLuint
));
246 if( gsprite_surfaces
.surfaces
== 0 )
249 gsprite_surfaces
.allocated
= 2;
250 memset(gsprite_surfaces
.surfaces
, 0, gsprite_surfaces
.allocated
* sizeof(GLuint
));
252 gsprites
.sprites
= (Sprite
**) calloc(2,sizeof(Sprite
*));
253 if( gsprites
.sprites
== 0 )
255 memset(gsprites
.sprites
, 0, gsprites
.allocated
* sizeof(Sprite
*));
256 gsprites
.allocated
= 2;
259 gsprite_queue
.allocated
=2;
260 gsprite_queue
.items
=(SpriteQueueItem
*) malloc(sizeof(SpriteQueueItem
)*2);
261 gsprite_queue
.next_id
=0;
263 SetVideoMode(config
.screen_width
, config
.screen_height
);
265 glClearColor(0.0f
, 0.0f
, 0.0f
, 0.5f
);
267 glDisable(GL_DEPTH_TEST
);
268 //glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
270 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
271 //glEnable(GL_ALPHA_TEST);
272 //glAlphaFunc(GL_GREATER, 0);
273 SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL
, 1);
275 glViewport(0, 0, config
.screen_width
, config
.screen_height
);
276 glMatrixMode(GL_PROJECTION
);
279 glOrtho(0.0f
,config
.screen_width
, config
.screen_height
,0.0f
,-1.0f
,1.0f
);
281 glMatrixMode(GL_MODELVIEW
);
287 void FlushSpriteSurfaces(){
290 for(i
=0;i
<gsprite_surfaces
.allocated
;i
++){
291 if(gsprite_surfaces
.surfaces
[i
]){
292 glDeleteTextures(1, &gsprite_surfaces
.surfaces
[i
]);
293 gsprite_surfaces
.surfaces
[i
]=0;
299 int RegenerateSprites(){
309 FlushSpriteSurfaces();
311 SetVideoMode(config
.screen_width
, config
.screen_height
);
314 for(i
=0;i
<gsprites
.allocated
;i
++)
315 if(gsprites
.sprites
[i
]){
316 tmpsprite
=gsprites
.sprites
[i
];
317 xx
= (tmpsprite
->width
/SCREEN_WIDTH
)*config
.screen_width
;
318 yy
= (tmpsprite
->height
/SCREEN_HEIGHT
)*config
.screen_height
;
320 tmpsurface
=load_svg(tmpsprite
->fname
, xx
, yy
, &tmpsprite
->twidth
, &tmpsprite
->theight
);
322 SID
=AddSurface(tmpsurface
);
326 RotateSurface(SID
,tmpsprite
->rotation
);
333 void InvalidateSprites(){
338 void FlushSpriteQueue(){
341 for(i
=0;i
<gsprite_queue
.allocated
;i
++){
342 gsprite_queue
.items
[i
].sprite
= 0;
344 if(gsprite_queue
.next_id
< gsprite_queue
.allocated
/2){
345 //TODO:dopsat zmenseni fronty
347 gsprite_queue
.next_id
= 0;
351 void ZSortSpriteQueue(){
352 int minz
, lastminz
, found
;
358 gsprite_queue_sorted
.next_id
= 0;
362 //we seek for smallest z bigger than z in last iteration
363 for(i
=0; i
<gsprite_queue
.next_id
; i
++){
364 if( gsprite_queue
.items
[i
].z
< minz
&& gsprite_queue
.items
[i
].z
> lastminz
){
366 minz
= gsprite_queue
.items
[i
].z
;
371 //now we copy all items on z==minz
372 for(i
=0; i
< gsprite_queue
.next_id
; i
++){
373 if(gsprite_queue
.items
[i
].z
== minz
){
374 memcpy(&gsprite_queue_sorted
.items
[gsprite_queue_sorted
.next_id
], &gsprite_queue
.items
[i
], sizeof(SpriteQueueItem
));
375 gsprite_queue_sorted
.next_id
++;
395 gsprite_queue_sorted
.allocated
= gsprite_queue
.allocated
;
396 gsprite_queue_sorted
.next_id
= 0;
397 gsprite_queue_sorted
.items
= malloc(sizeof(SpriteQueueItem
)* gsprite_queue_sorted
.allocated
);
400 for(i
=0;i
<gsprite_queue_sorted
.next_id
;i
++)
401 if(gsprite_queue_sorted
.items
[i
].sprite
){
402 dspr
= gsprite_queue_sorted
.items
[i
].sprite
;
403 ds
= gsprite_surfaces
.surfaces
[dspr
->SID
];
404 dest
.x
= G2SX(gsprite_queue_sorted
.items
[i
].x
);
405 dest
.y
= G2SY(gsprite_queue_sorted
.items
[i
].y
);
406 dest
.w
= G2SX(gsprite_queue_sorted
.items
[i
].sprite
->width
);
407 dest
.h
= G2SX(gsprite_queue_sorted
.items
[i
].sprite
->height
);
410 src
.w
= G2SX(gsprite_queue_sorted
.items
[i
].sprite
->width
);
411 src
.h
= G2SX(gsprite_queue_sorted
.items
[i
].sprite
->height
);
412 glBindTexture(GL_TEXTURE_2D
, ds
);
413 glEnable(GL_TEXTURE_2D
);
414 TRECT(dest
.x
, dest
.y
, dest
.w
, dest
.h
, dspr
->twidth
, dspr
->theight
);
415 glDisable(GL_TEXTURE_2D
);
418 gsprite_queue_sorted
.allocated
= 0;
419 gsprite_queue_sorted
.next_id
= 0;
420 free(gsprite_queue_sorted
.items
);
421 gsprite_queue_sorted
.items
= 0;
424 SDL_GL_SwapBuffers();
430 //SDL_FillRect(gscreen, 0, 0x0);
433 Sprite
* LoadSpriteSVG(char *fname
, double width
, double height
){
437 Config conf
=GetConfig();
439 xx
= width
*(double)conf
.screen_width
/SCREEN_WIDTH
;
440 yy
= height
*(double)conf
.screen_height
/SCREEN_HEIGHT
;
443 sprite
= (Sprite
*)malloc(sizeof(Sprite
));
444 surface
= load_svg(fname
, xx
, yy
, &sprite
->twidth
, &sprite
->theight
);
445 sprite
->fname
= malloc(sizeof(char)*(strlen(fname
)+2));
446 strcpy(sprite
->fname
, fname
);
447 sprite
->width
= width
;
448 sprite
->height
= height
;
449 sprite
->rotation
= 0;
450 sprite
->SID
= AddSurface(surface
);
455 void DestroySprite(Sprite
*sprite
){
458 RemoveSprite(sprite
);
461 glDeleteTextures(1, &gsprite_surfaces
.surfaces
[sprite
->SID
]);
462 RemoveSID(sprite
->SID
);
466 Sprite
* CopySprite(Sprite
*old
){
467 printf("CopySprite not Implemented\n");
473 void RotateSurface(int SID
, int rotation
){
477 fprintf(stderr
, "Rotation of sprites not implemented :(\n");
480 void RotateClockwise(Sprite
*sprite
){
481 RotateSurface(sprite
->SID
,1);
485 void QueueDrawSprite(Sprite
*sprite
, double x
, double y
, int z
){
486 SpriteQueueItem
*item
;
487 if(gsprite_queue
.next_id
>=gsprite_queue
.allocated
){
488 item
= (SpriteQueueItem
*) realloc(gsprite_queue
.items
, sizeof(SpriteQueueItem
)*gsprite_queue
.allocated
*2);
490 fprintf(stderr
, "Can't allocate enough memory for sprite queue\n");
493 gsprite_queue
.allocated
*= 2;
494 gsprite_queue
.items
= item
;
497 item
= &gsprite_queue
.items
[gsprite_queue
.next_id
];
498 item
->sprite
= sprite
;
503 gsprite_queue
.next_id
++;
507 unsigned int closestpoweroftwo(unsigned int i
){
518 //load_svg borrowed from cairo demo
521 #include <sys/types.h>
524 #include <svg-cairo.h>
526 /* load_svg: This is what you're probably interested in!
527 * -----------------------------------------------------
528 * If width and height are greater than 0, the image will
529 * be scaled to that size. wscale and hscale would be ignored.
531 * If width and height are less than 1, wscale and hscale will
532 * resize the width and the height to the specified scales.
534 * If width and height are less than 1, and wscale and hscale
535 * are either 0 or 1, then the image will be loaded at it's
538 * See main() for examples.
540 GLuint
load_svg (char *file
, int width
, int height
, double *pdw
, double *pdh
) {
545 unsigned int rheight
;
546 unsigned int pw
,ph
; //power of two dimensions
547 double wscale
,hscale
;
548 Config config
=GetConfig();
550 // Create the SVG cairo stuff.
551 svg_cairo_create(&scr
);
552 svg_cairo_parse (scr
, file
);
554 svg_cairo_get_size (scr
, &rwidth
, &rheight
);
555 *pdw
= closestpoweroftwo(width
);
556 *pdh
= closestpoweroftwo(height
);
557 width
= width
>>config
.texture_lod
;
558 height
= height
>>config
.texture_lod
;
560 /*Calculate final width and height of our surface based on the parameters passed */
562 wscale
=(float)width
/(float)rwidth
;
564 width
=(int)(rwidth
*wscale
);
567 hscale
=(float)height
/(float)rheight
;
569 height
=(int)(rheight
*hscale
);
579 /* We will create a CAIRO_FORMAT_ARGB32 surface. We don't need to match
580 the screen SDL format, but we are interested in the alpha bit */
581 bpp
=32; /*bits per pixel*/
582 btpp
=4; /*bytes per pixel*/
585 int stride
=width
* btpp
;
587 /* Allocate an image */
588 unsigned char *image
=calloc(stride
*height
, 1);
590 /* Create the cairo surface with the adjusted width and height */
591 cairo_surface_t
*cairo_surface
;
592 cairo_surface
= cairo_image_surface_create_for_data (image
,
594 width
, height
, stride
);
596 cairo_t
*cr
=cairo_create(cairo_surface
);
597 cairo_scale (cr
, wscale
, hscale
);
599 /* Render SVG to our surface */
600 svg_cairo_render (scr
, cr
);
603 cairo_surface_destroy (cairo_surface
);
606 /*Destroy the svg_cairo structure */
607 svg_cairo_destroy (scr
);
609 /*Adjust the SDL surface mask to ARGB, matching the cairo surface created.*/
610 Uint32 rmask
, gmask
, bmask
, amask
;
617 /* Create the SDL surface using the pixel data stored. It will automatically be set to use alpha using these mask values */
618 SDL_Surface
*sdl_surface
=SDL_CreateRGBSurfaceFrom( (void *) image
, width
, height
, bpp
, stride
, rmask
, gmask
, bmask
, amask
);
619 SDL_SetAlpha(sdl_surface
, 0, 255);
624 pw
= closestpoweroftwo(width
);
625 ph
= closestpoweroftwo(height
);
626 SDL_Surface
*sdl_rgba_surface
=SDL_CreateRGBSurface( SDL_SWSURFACE
, pw
, ph
, bpp
, rmask
, gmask
, bmask
, amask
);
627 SDL_BlitSurface(sdl_surface
, 0, sdl_rgba_surface
, 0);
628 SDL_FreeSurface(sdl_surface
);
631 SDL_LockSurface(sdl_rgba_surface
);
634 glGenTextures(1, &tid
);
635 glBindTexture(GL_TEXTURE_2D
, tid
);
636 glTexParameteri(GL_TEXTURE_2D
,GL_TEXTURE_MAG_FILTER
,GL_LINEAR
); // scale linearly when image bigger than texture
637 glTexParameteri(GL_TEXTURE_2D
,GL_TEXTURE_MIN_FILTER
,GL_LINEAR
); // scale linearly when image smalled than texture
638 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, pw
, ph
, 0, GL_RGBA
, GL_UNSIGNED_BYTE
, sdl_rgba_surface
->pixels
);
639 SDL_UnlockSurface(sdl_rgba_surface
);
640 SDL_FreeSurface(sdl_rgba_surface
);
642 printf("Occupied: %u\n", occupied
);