summaryrefslogtreecommitdiff
path: root/README
diff options
context:
space:
mode:
authorM Joonas Pihlaja <jpihlaja@cc.helsinki.fi>2009-02-15 15:10:30 +0200
committerM Joonas Pihlaja <jpihlaja@cc.helsinki.fi>2009-02-15 15:10:30 +0200
commit11ea8fbcc8634b130a22237dadf338c0d735adb1 (patch)
tree1e5a14ec69759702dc68bbda6f215af6c803db62 /README
Import cairosdl.
Diffstat (limited to 'README')
-rw-r--r--README173
1 files changed, 173 insertions, 0 deletions
diff --git a/README b/README
new file mode 100644
index 0000000..30f8917
--- /dev/null
+++ b/README
@@ -0,0 +1,173 @@
+Cairosdl: convenience functions for setting up drawing to SDL surfaces
+using cairo.
+
+Using cairo to draw on SDL functions is very easy. The only gotcha is
+that it's only possible for surfaces whose pixel format is supported
+by cairo.
+
+
+* Quick start to cairosdl.c
+---------------------------
+
+For one-off rendering using cairo only:
+
+ sdlsurf = SDL_CreateRBGSurface(flags, width, height, 32,
+ CAIROSDL_RMASK, CAIROSDL_GMASK, CAIROSDL_BMASK,
+ 0 /* or CAIROSDL_AMASK*/);
+
+ cairo_t *cairosdl_create(sdlsurf);
+
+ /* ... normal cairo calls ... */
+
+ cairosdl_destroy(sdlsurf);
+
+For mixed cairo/non-cairo rendering:
+
+ sdlsurf = ... as before ...;
+
+ cairo_surface_t *cairosurf = cairosdl_surface_create(sdlsurf);
+
+ /* ... normal cairo calls ... and then before switching to
+ * non-cairo rendering: */
+
+ cairosdl_surface_flush_rects (cairosurf, rects, num_rects);
+
+ /* ... non-cairo rendering to the sdlsurf ... and then before
+ * resuming cairo rendering mark the changed areas: */
+
+ cairosdl_surface_mark_dirty_rects (cairosurf, rects, num_rects);
+
+So the short of it is: Use cairosdl_surface_create() or
+cairosdl_create() to bind your SDL_Surface to a cairo_surface_t or
+cairo_t context, and do normal cairo calls to render to it. Replace
+calls to cairo_surface_flush() and cairo_surface_mark_dirty() with the
+corresponding cairosdl.c calls. All the cairo functions expect the
+SDL_Surface to be locked or not need locking.
+
+
+* Amask = 0 surfaces
+--------------------
+
+Technically there is only one common pixel format in common between
+cairo and SDL: 32 bit pixels which do NOT use per pixel alpha. Cairo
+calls that format CAIRO_FORMAT_RGB24. In SDL terms such surfaces are
+created by:
+
+ SDL_CreateRGBSurface (flags, width, height, 32,
+ CAIROSDL_RMASK, // 0x00FF0000
+ CAIROSDL_GMASK, // 0x0000FF00
+ CAIROSDL_BMASK, // 0x000000FF
+ 0);
+
+Using the cairosdl_surface_create(SDL_Surface*) function one can get a
+cairo_surface_t* that can be used to get a cairo_t drawing context,
+just as normal. As a convenience, cairosdl_create(SDL_Surface*) will
+make the cairo_surface_t and then bind it to a cairo_t drawing context.
+
+If your SDL_Surface has this pixel format and does not need locking,
+that's all you need to do.
+
+
+* Amask = 0xFF000000 surfaces
+-----------------------------
+
+Unfortunately SDL and cairo have an inconsolable difference of opinion
+on the interpretation of 32 bit pixels with per pixel alpha. SDL uses
+unpremultiplied colour components, while cairo uses premultiplied
+colours: an SDL pixel with components (r,g,b,a) would be represented
+in a cairo as (a*r/255, a*g/255, a*b/255, a). (Here a=255 means fully
+opaque and a=0 means fully transparent.)
+
+The first option to consider is whether you really need such surfaces
+to be SDL_Surfaces or whether cairo's image surfaces would do just as
+well. After all, the screen surface almost never has per-pixel alpha,
+so you could create an Amask=0 surface for it and use cairo to blit to
+it from a normal cairo image surface. This is likely a little faster
+than SDL's per-pixel-alpha blits even when SDL can't accelerate them.
+
+Regardless, sometimes you really want to draw to an Amask=0xFF000000
+surface. The good news is that cairosdl.c supports such surfaces
+anyway via a backing buffer and will format shift between them on
+demand. In the simple one-off rendering case you just need to
+remember to call cairosdl_destroy() rather than cairo_destroy(). That
+will flush the backing buffer at the end to the SDL_Surface.
+
+If you plan to do mixed cairo/non-cairo rendering to the surface,
+cairosdl needs some coordination from you so that it can format shift
+between it's backing buffer and the SDL_Surface at the right times.
+
+The functions to call to make the cairo-drawn stuff appear in the
+SDL_Surface are:
+
+ cairosdl_surface_flush() ; writes to the entire SDL_Surface
+
+ cairosdl_surface_flush_rect(); writes to just a region.
+
+ cairosdl_surface_flush_rects(); writes via a list of SDL_Rects.
+
+These functions do not call SDL_UpdateRect or anything like that to
+make the output visible on screen.
+
+The functions to call to import non-cairo drawn changes from the
+SDL_Surface to the backing surface are:
+
+ cairosdl_surface_mark_dirty () ; reads the entire SDL_Surface.
+
+ cairosdl_surface_mark_dirty_rect () ; reads just a region.
+
+ cairosdl_surface_mark_dirty_rects () ; reads via a list of SDL_Rects.
+
+If you're doing mixed rendering and are already using the
+flush/mark_dirty functions, then you don't want to call
+cairosdl_destroy() at the end since that does an implicit final flush.
+
+
+* Palette indexed surfaces
+--------------------------
+
+You could create a cairo image surface using the CAIRO_FORMAT_A8 pixel
+format. Cairo will ignore your palette though. cairosdl.c doesn't
+support this at the moment.
+
+
+* SDL_Surface flags, locking and other caveats
+----------------------------------------------
+
+Cairo really needs direct access to the pixel data of an SDL surface,
+but it doesn't know anything about locking them. Since the SDL
+locking rules can be a little inconvenient, the cairosdl_* functions
+assume that you're passing in an SDL_Surface which does not need
+locking or is already locked. In particular, the surface->pixels
+member must be valid and not change for the lifetime of a
+cairo_surface_t created by cairosdl_surface_create() or
+cairosdl_create(). It must also be safe to call malloc and whatever
+platform specific mutex operations inside cairo while the surface is
+locked.
+
+For most platforms I believe this means that SDL_SWSURFACEs are always
+safe to use with cairo. If they don't use RLEACCEL, they don't even
+need any locking at all.
+
+One can also use SDL_HWSURFACEs if it's okay to call malloc and other
+OS facilities while they're locked. In this case the the lifetime of
+the cairo_surface_t created for the SDL_Surface must be contained
+within a single SDL_LockSurface/UnlockSurface pair. Again, for many
+platforms this isn't a problem.
+
+I haven't tested GL enabled SDL surfaces, but expect there shouldn't
+be a problem if GL can be configured to accept cairo's pixel formats.
+
+Cairo ignores SDL_Surface colorkey and treats every 32 bit surface
+with alpha as if it had SDL_SRCALPHA.
+
+
+* Tips and tricks
+-----------------
+
+Cairo's software blits seem to be slightly faster than SDL's software
+blits. The fastest combination seems to be using a 32 bit SDL_Surface
+with Amask = 0, wrap that up in a cairo_surface_t, and use normal
+cairo image surfaces for the per-pixel-alpha surfaces.
+
+The cairosdl_surface_get_target() and cairosdl_get_target() functions
+return the SDL_Surface bound to the given cairo_surface_t or cairo_t.