Merge lp:~nha/widelands/graphics-refactor into lp:widelands

Proposed by Nicolai Hähnle
Status: Merged
Merged at revision: 5755
Proposed branch: lp:~nha/widelands/graphics-refactor
Merge into: lp:widelands
Diff against target: 5718 lines (+1895/-2011)
57 files modified
src/CMakeLists.txt (+3/-3)
src/editor/editorinteractive.cc (+1/-0)
src/editor/ui_menus/editor_tool_set_terrain_options_menu.cc (+9/-10)
src/graphic/animation_gfx.h (+4/-5)
src/graphic/compositemode.h (+44/-0)
src/graphic/font_handler.cc (+25/-46)
src/graphic/font_handler.h (+2/-3)
src/graphic/graphic.cc (+384/-501)
src/graphic/graphic.h (+49/-34)
src/graphic/offscreensurface.h (+34/-0)
src/graphic/picture.cc (+22/-9)
src/graphic/picture.h (+29/-36)
src/graphic/picture_id.h (+2/-2)
src/graphic/pixelaccess.h (+110/-0)
src/graphic/render/animationgfx.cc (+48/-65)
src/graphic/render/gameview.cc (+11/-16)
src/graphic/render/gl_picture_texture.cc (+235/-0)
src/graphic/render/gl_picture_texture.h (+75/-0)
src/graphic/render/gl_surface_screen.cc (+286/-0)
src/graphic/render/gl_surface_screen.h (+74/-0)
src/graphic/render/gl_utils.cc (+100/-0)
src/graphic/render/gl_utils.h (+37/-0)
src/graphic/render/render_opengl.cc (+0/-269)
src/graphic/render/render_sdl.cc (+21/-10)
src/graphic/render/surface_opengl.cc (+0/-381)
src/graphic/render/surface_opengl.h (+0/-170)
src/graphic/render/surface_sdl.cc (+8/-3)
src/graphic/render/surface_sdl.h (+27/-18)
src/graphic/render/terrain_opengl.h (+6/-7)
src/graphic/render/terrain_sdl.h (+13/-12)
src/graphic/rendertarget.cc (+50/-125)
src/graphic/rendertarget.h (+10/-11)
src/graphic/surface.h (+13/-85)
src/graphic/surfaceptr.h (+31/-0)
src/graphic/texture.cc (+8/-13)
src/graphic/texture.h (+3/-3)
src/map_io/widelands_map_extradata_data_packet.cc (+3/-4)
src/ui_basic/button.cc (+36/-42)
src/ui_basic/button.h (+1/-1)
src/ui_basic/checkbox.cc (+2/-5)
src/ui_basic/editbox.cc (+1/-1)
src/ui_basic/icon.cc (+3/-3)
src/ui_basic/listselect.cc (+11/-13)
src/ui_basic/listselect.h (+1/-1)
src/ui_basic/multilineeditbox.cc (+1/-1)
src/ui_basic/multilinetextarea.cc (+4/-5)
src/ui_basic/panel.cc (+6/-9)
src/ui_basic/panel.h (+2/-1)
src/ui_basic/progresswindow.cc (+8/-26)
src/ui_basic/slider.cc (+28/-29)
src/ui_basic/slider.h (+2/-2)
src/ui_fsmenu/base.cc (+7/-15)
src/ui_fsmenu/base.h (+0/-1)
src/wui/interactive_gamebase.h (+0/-2)
src/wui/interactive_player.cc (+1/-9)
src/wui/plot_area.cc (+2/-2)
src/wui/waresqueuedisplay.cc (+2/-2)
To merge this branch: bzr merge lp:~nha/widelands/graphics-refactor
Reviewer Review Type Date Requested Status
Widelands Developers Pending
Review via email: mp+42016@code.launchpad.net

Description of the change

This merge contains a pretty huge refactoring that attempts to clarify the meaning of surfaces vs. pictures, and enforce it via the C++ type system.

From now on Pictures are things that can act as blit sources, while Surfaces are things that can act as blit destinations. In SDL mode, everything is both a Picture and a Surface; in OpenGL mode, this is not the case.

As a side-effect, this also fixes the scaling of menu backgrounds in OpenGL mode.

It's a pretty huge change, which is why I didn't want to commit it immediately. Some more testing is a good idea, and I didn't want to mess with people who are playing this weekend.

To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/CMakeLists.txt'
2--- src/CMakeLists.txt 2010-11-07 22:42:19 +0000
3+++ src/CMakeLists.txt 2010-11-29 19:01:16 +0000
4@@ -54,7 +54,7 @@
5 add_executable (widelands ${GUI_TYPE} main.cc build_info.cc ${WIN32_ICON_O})
6 else (DEFINED MINGW)
7 add_executable (widelands ${GUI_TYPE} main.cc build_info.cc)
8- endif (DEFINED MINGW)
9+ endif (DEFINED MINGW)
10 endif (DEFINED MSVC)
11
12 add_library (widelands_all ${WL_SRCS_CC} ${WL_SRCS_H})
13@@ -72,7 +72,7 @@
14 if (WIN32)
15 string(REGEX REPLACE "^.*:" "" sourcenoslash ${sourcenoslash})
16 endif (WIN32)
17- get_filename_component(sourcename ${sourcefile} NAME)
18+ get_filename_component(sourcename ${sourcefile} NAME)
19 set(stamp ${sourcename}_)
20 add_custom_command(
21 OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/codecheck_${sourcenoslash}"
22@@ -151,7 +151,7 @@
23
24 else (DEFINED MSVC)
25 target_link_libraries(widelands wsock32)
26- endif (DEFINED MSVC)
27+ endif (DEFINED MSVC)
28 endif (WIN32)
29
30 install(TARGETS widelands DESTINATION ${WLBUILD_INSTALL_BINDIR} COMPONENT ExecutableFiles)
31
32=== modified file 'src/editor/editorinteractive.cc'
33--- src/editor/editorinteractive.cc 2010-11-01 22:30:23 +0000
34+++ src/editor/editorinteractive.cc 2010-11-29 19:01:16 +0000
35@@ -594,6 +594,7 @@
36 editor.cleanup_objects();
37
38 g_gr->flush(PicMod_Game);
39+ g_gr->flush_animations();
40 g_anim.flush();
41 }
42
43
44=== modified file 'src/editor/ui_menus/editor_tool_set_terrain_options_menu.cc'
45--- src/editor/ui_menus/editor_tool_set_terrain_options_menu.cc 2010-11-01 22:30:23 +0000
46+++ src/editor/ui_menus/editor_tool_set_terrain_options_menu.cc 2010-11-29 19:01:16 +0000
47@@ -94,7 +94,7 @@
48 pos.y += TEXTURE_HEIGHT + vspacing();
49 }
50
51- PictureID surface;
52+ PictureID picture;
53
54 // If offscreen rendering is not available only the terrain (and not
55 // the terrain type) is shown.
56@@ -102,11 +102,11 @@
57 // or implement offscreen rendering for opengl
58 if (g_gr->caps().offscreen_rendering)
59 {
60- // create a surface for this
61- surface = g_gr->create_picture_surface(64, 64);
62+ OffscreenSurfacePtr offscreen = g_gr->create_offscreen_surface(64, 64);
63+ picture = g_gr->get_offscreen_picture(offscreen);
64
65 // get the rendertarget for this
66- RenderTarget & target = *g_gr->get_surface_renderer(surface);
67+ RenderTarget target(offscreen);
68
69 // first, blit the terrain texture
70 target.blit
71@@ -144,16 +144,16 @@
72 target.blit(pic, dry);
73 }
74 } else {
75- surface = g_gr->get_picture
76+ picture = g_gr->get_picture
77 (PicMod_Game,
78 g_gr->get_maptexture_data(world.terrain_descr(i).get_texture())
79 ->get_texture_picture());
80 }
81
82 // Save this surface, so we can free it later on.
83- m_surfaces.push_back(surface);
84+ m_surfaces.push_back(picture);
85
86- UI::Checkbox & cb = *new UI::Checkbox(this, pos, surface);
87+ UI::Checkbox & cb = *new UI::Checkbox(this, pos, picture);
88 cb.set_size(TEXTURE_WIDTH + 1, TEXTURE_HEIGHT + 1);
89 cb.set_id(i);
90 cb.set_state(m_tool.is_enabled(i));
91@@ -185,9 +185,8 @@
92 }
93
94
95-Editor_Tool_Set_Terrain_Options_Menu::~Editor_Tool_Set_Terrain_Options_Menu() {
96- container_iterate_const(std::vector<PictureID>, m_surfaces, i)
97- g_gr->free_picture_surface(*i.current);
98+Editor_Tool_Set_Terrain_Options_Menu::~Editor_Tool_Set_Terrain_Options_Menu()
99+{
100 }
101
102
103
104=== modified file 'src/graphic/animation_gfx.h'
105--- src/graphic/animation_gfx.h 2010-11-10 20:05:21 +0000
106+++ src/graphic/animation_gfx.h 2010-11-29 19:01:16 +0000
107@@ -22,23 +22,22 @@
108
109 #include "animation.h"
110 #include "logic/widelands.h"
111+#include "picture_id.h"
112 #include "rgbcolor.h"
113
114-struct Surface;
115-
116 struct AnimationGfx { /// The graphics belonging to an animation.
117 AnimationGfx(AnimationData const * data);
118 ~AnimationGfx();
119
120 const Point get_hotspot() const throw () {return m_hotspot;}
121- typedef std::vector<Surface *> Frames;
122+ typedef std::vector<PictureID> Frames;
123 typedef Frames::size_type Index;
124 Index nr_frames() const
125 {
126 assert((*m_plrframes)[0]); return m_plrframes[0].size();
127 }
128
129- Surface * get_frame
130+ const PictureID & get_frame
131 (Index const i,
132 Widelands::Player_Number const player_number,
133 RGBColor const * const playercolor)
134@@ -56,7 +55,7 @@
135 return m_plrframes[player_number][i];
136 }
137
138- Surface * get_frame(Index const i) const {
139+ const PictureID & get_frame(Index const i) const {
140 assert(i < nr_frames());
141 return m_plrframes[0][i];
142 }
143
144=== added file 'src/graphic/compositemode.h'
145--- src/graphic/compositemode.h 1970-01-01 00:00:00 +0000
146+++ src/graphic/compositemode.h 2010-11-29 19:01:16 +0000
147@@ -0,0 +1,44 @@
148+/*
149+ * Copyright (C) 2010 by the Widelands Development Team
150+ *
151+ * This program is free software; you can redistribute it and/or
152+ * modify it under the terms of the GNU General Public License
153+ * as published by the Free Software Foundation; either version 2
154+ * of the License, or (at your option) any later version.
155+ *
156+ * This program is distributed in the hope that it will be useful,
157+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
158+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
159+ * GNU General Public License for more details.
160+ *
161+ * You should have received a copy of the GNU General Public License
162+ * along with this program; if not, write to the Free Software
163+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
164+ *
165+ */
166+
167+#ifndef COMPOSITEMODE_H
168+#define COMPOSITEMODE_H
169+
170+/**
171+ * Defines composition operations performed while blitting.
172+ */
173+enum Composite {
174+ /**
175+ * Perform a normal blitting operation that respects the alpha
176+ * channel if present.
177+ */
178+ CM_Normal = 0,
179+
180+ /**
181+ * Perform a solid blit that ignores the alpha channel information.
182+ */
183+ CM_Solid,
184+
185+ /**
186+ * Copy all pixel information, including alpha channel information.
187+ */
188+ CM_Copy
189+};
190+
191+#endif // COMPOSITEMODE_H
192
193=== modified file 'src/graphic/font_handler.cc'
194--- src/graphic/font_handler.cc 2010-11-01 22:37:46 +0000
195+++ src/graphic/font_handler.cc 2010-11-29 19:01:16 +0000
196@@ -32,7 +32,6 @@
197 #include "rendertarget.h"
198 #include "surface.h"
199 #include "graphic/render/surface_sdl.h"
200-#include "graphic/render/surface_opengl.h"
201
202 #include <SDL_image.h>
203 #include <SDL_ttf.h>
204@@ -96,7 +95,7 @@
205 Align const align,
206 uint32_t const wrap,
207 Widget_Cache const widget_cache,
208- PictureID & widget_cache_id,
209+ PictureID * widget_cache_id,
210 uint32_t const caret,
211 bool const transparent)
212 {
213@@ -124,20 +123,17 @@
214 m_cache.erase (i);
215 }
216 } else {
217- //not cached, create a new surface
218+ //not cached, create a new surface and cache it
219 ci.picture_id =
220 create_text_surface
221 (font, fg, bg, text, align, wrap, 0, caret, transparent);
222- // Now cache it
223- assert(ci.picture_id->surface);
224 g_gr->get_picture_size(ci.picture_id, ci.w, ci.h);
225 ci.f = &font;
226 m_cache.push_front (ci);
227
228- while (m_cache.size() > CACHE_ARRAY_SIZE) {
229- g_gr->free_picture_surface(m_cache.back().picture_id);
230+ while (m_cache.size() > CACHE_ARRAY_SIZE)
231 m_cache.pop_back();
232- }
233+
234 //Set for alignment and blitting
235 picid = ci.picture_id;
236 w = ci.w;
237@@ -145,16 +141,16 @@
238 }
239 } else if (widget_cache == Widget_Cache_Use) {
240 // Widget gave us an explicit picid.
241- g_gr->get_picture_size(widget_cache_id, w, h);
242- picid = widget_cache_id;
243- } else { // We need to (re)create the picid for the widget.
244- if (widget_cache == Widget_Cache_Update)
245- g_gr->free_picture_surface(widget_cache_id);
246- widget_cache_id =
247+ g_gr->get_picture_size(*widget_cache_id, w, h);
248+ picid = *widget_cache_id;
249+ } else {
250+ // We need to (re)create the picid for the widget.
251+ // The old picture is freed automatically
252+ *widget_cache_id =
253 create_text_surface
254 (font, fg, bg, text, align, wrap, 0, caret, transparent);
255- g_gr->get_picture_size(widget_cache_id, w, h);
256- picid = widget_cache_id;
257+ g_gr->get_picture_size(*widget_cache_id, w, h);
258+ picid = *widget_cache_id;
259 }
260 do_align(align, dstpoint.x, dstpoint.y, w, h);
261 dst.blit(dstpoint, picid);
262@@ -347,14 +343,11 @@
263 TTF_SizeUTF8(&font, text_caret_pos.c_str(), &caret_x, &caret_y);
264 caret_x += LINE_MARGIN;
265
266- Surface * const caret_surf =
267- g_gr->get_picture_surface
268- (g_gr->get_picture(PicMod_Game, "pics/caret.png"));
269-
270 //TODO: Implement caret rendering for opengl
271 if (!g_opengl)
272 {
273- upcast(SurfaceSDL, sdlsurf, caret_surf);
274+ PictureID caret = g_gr->get_picture(PicMod_Game, "pics/caret.png");
275+ upcast(SurfaceSDL, sdlsurf, caret.get());
276 assert(sdlsurf);
277 SDL_Surface * const caret_surf_sdl = sdlsurf->get_sdl_surface();
278
279@@ -421,16 +414,13 @@
280 std::string text,
281 int32_t wrap,
282 Widget_Cache widget_cache,
283- PictureID & widget_cache_id,
284+ PictureID * widget_cache_id,
285 bool const transparent)
286 {
287 PictureID picid;
288 if (widget_cache == Widget_Cache_Use)
289- picid = widget_cache_id;
290+ picid = *widget_cache_id;
291 else {
292- if (widget_cache == Widget_Cache_Update) {
293- g_gr->free_picture_surface(widget_cache_id);
294- }
295 std::vector<Richtext_Block> blocks;
296 Text_Parser p;
297 p.parse(text, blocks);
298@@ -473,19 +463,18 @@
299 img_pos.x = img_surf_w;
300 img_pos.y = 0;
301 if
302- (Surface * const image =
303- g_gr->get_picture_surface // Not Font, but Game.
304- (g_gr->get_picture(PicMod_Game, img_it->c_str())))
305+ (PictureID const image =
306+ g_gr->get_picture(PicMod_Game, *img_it))
307 {
308 img_surf_h =
309 img_surf_h < static_cast<int32_t>(image->get_h()) ?
310 image->get_h() : img_surf_h;
311 img_surf_w = img_surf_w + image->get_w();
312
313- upcast(SurfaceSDL, sdlsurf, image);
314+ upcast(SurfaceSDL, sdlsurf, image.get());
315 if (sdlsurf)
316 rend_cur_images.push_back(sdlsurf->get_sdl_surface());
317-
318+ // TODO fix this for OpenGL
319 }
320 }
321 SDL_Surface * const block_images =
322@@ -701,7 +690,7 @@
323 convert_sdl_surface
324 (*join_sdl_surfaces(wrap, global_h, rend_blocks, bg),
325 bg, transparent);
326- widget_cache_id = picid;
327+ *widget_cache_id = picid;
328 }
329 dst.blit(dstpoint, picid);
330 }
331@@ -813,11 +802,7 @@
332 (&surface, SDL_SRCCOLORKEY,
333 SDL_MapRGB(surface.format, bg.r(), bg.g(), bg.b()));
334
335- Surface & surf = g_gr->create_surface(surface, transparent);
336-
337- PictureID picid = g_gr->get_picture(PicMod_Font, surf);
338-
339- return picid;
340+ return g_gr->convert_sdl_surface_to_picture(&surface, transparent);
341 }
342
343 //Sets dstx and dsty to values for a specified align
344@@ -846,15 +831,9 @@
345 /*
346 * Flushes the cached picture ids
347 */
348-void Font_Handler::flush_cache() {
349- while (!m_cache.empty()) {
350- g_gr->free_picture_surface (m_cache.front().picture_id);
351- m_cache.pop_front();
352- }
353-}
354-//Deletes widget controlled surface
355-void Font_Handler::delete_widget_cache(PictureID const widget_cache_id) {
356- g_gr->free_picture_surface(widget_cache_id);
357+void Font_Handler::flush_cache()
358+{
359+ m_cache.clear();
360 }
361
362 //Inserts linebreaks into a text, so it doesn't get bigger than max_width
363
364=== modified file 'src/graphic/font_handler.h'
365--- src/graphic/font_handler.h 2010-11-05 19:36:57 +0000
366+++ src/graphic/font_handler.h 2010-11-29 19:01:16 +0000
367@@ -56,7 +56,7 @@
368 Align align = Align_CenterLeft,
369 uint32_t wrap = std::numeric_limits<uint32_t>::max(),
370 Widget_Cache widget_cache = Widget_Cache_None,
371- PictureID & widget_cache_id = g_gr->get_no_picture(),
372+ PictureID * widget_cache_id = 0,
373 uint32_t caret = std::numeric_limits<uint32_t>::max(),
374 bool transparent = true);
375 void get_size
376@@ -79,7 +79,6 @@
377 // from the graphics code before the graphics are flushed,
378 // to make sure that everything is forgotten
379 void flush_cache();
380- void delete_widget_cache(PictureID widget_cache_id);
381 void draw_richtext
382 (RenderTarget &,
383 RGBColor bg,
384@@ -87,7 +86,7 @@
385 std::string text,
386 int32_t wrap,
387 Widget_Cache widget_cache = Widget_Cache_None,
388- PictureID & widget_cache_id = g_gr->get_no_picture(),
389+ PictureID * widget_cache_id = 0,
390 bool transparent = true);
391 void get_size_from_cache
392 (PictureID widget_cache_id, uint32_t & w, uint32_t & h);
393
394=== modified file 'src/graphic/graphic.cc'
395--- src/graphic/graphic.cc 2010-11-01 23:13:48 +0000
396+++ src/graphic/graphic.cc 2010-11-29 19:01:16 +0000
397@@ -32,11 +32,13 @@
398 #include "io/streamwrite.h"
399
400 #include "font_handler.h"
401+#include "picture.h"
402 #include "rendertarget.h"
403 #include "texture.h"
404
405 #include "render/surface_sdl.h"
406-#include "render/surface_opengl.h"
407+#include "render/gl_picture_texture.h"
408+#include "render/gl_surface_screen.h"
409
410 #include "logic/roadtype.h"
411 #include "logic/widelands_fileread.h"
412@@ -50,6 +52,7 @@
413
414 #include <cstring>
415 #include <iostream>
416+#include <boost/scoped_array.hpp>
417
418 Graphic * g_gr;
419 bool g_opengl;
420@@ -74,8 +77,6 @@
421 m_update_fullscreen(false),
422 m_roadtextures (0)
423 {
424- m_picturemap.resize(MaxModule);
425-
426 // Initialize the table used to create grayed pictures
427 for
428 (uint32_t i = 0, r = 0, g = 0, b = 0;
429@@ -150,9 +151,7 @@
430 log("Graphics: FULLSCREEN ENABLED\n");
431
432 // Set rendering capabilities for sdl. They are overwritten if in opengl mode
433- m_caps.resize_surfaces = true;
434 m_caps.offscreen_rendering = true;
435- m_caps.blit_resized = false;
436
437 #ifdef USE_OPENGL
438 if (0 != (sdlsurface->flags & SDL_OPENGL)) {
439@@ -199,9 +198,7 @@
440 (m_caps.gl.tex_power_of_two?"must have a size power of two\n":
441 "may have any size\n");
442
443- m_caps.resize_surfaces = false;
444 m_caps.offscreen_rendering = false;
445- m_caps.blit_resized = true;
446 }
447 #endif
448
449@@ -280,13 +277,16 @@
450 }
451
452 if (g_opengl)
453- m_screen = new SurfaceOpenGL(w, h);
454+ {
455+ m_screen.reset(new GLSurfaceScreen(w, h));
456+ }
457 else
458 #endif
459 {
460- m_screen = new SurfaceSDL(*sdlsurface);
461+ boost::shared_ptr<SurfaceSDL> screen(new SurfaceSDL(*sdlsurface));
462+ screen->set_isscreen(true);
463+ m_screen = screen;
464 }
465- m_screen->set_type(SURFACE_SCREEN);
466
467 m_sdl_screen = sdlsurface;
468 m_rendertarget = new RenderTarget(m_screen);
469@@ -297,12 +297,11 @@
470 */
471 Graphic::~Graphic()
472 {
473- for (size_t i = 1; i < m_picturemap.size(); ++i)
474- flush(static_cast<PicMod>(i));
475-
476 delete m_rendertarget;
477- delete m_screen;
478 delete m_roadtextures;
479+
480+ // Remove traces of cached pictures
481+ UI::g_fh->flush_cache();
482 }
483
484 /**
485@@ -401,33 +400,27 @@
486 }
487
488 /**
489- * Remove all resources (currently pictures) from the given modules.
490- * \note flush(0) does nothing <- obviously wrong it deletes a lot!
491-*/
492-void Graphic::flush(PicMod const module) {
493- // Flush pictures
494-
495- //pmit b, e = m_picturemap.end();
496- for (size_t i = 0; i < m_picturemap.size(); ++i) {
497- if (static_cast<PicMod>(i) == module) {
498- m_picturemap[i].clear();
499- }
500- }
501-
502- if (!module || module & PicMod_Game) {
503- container_iterate_const(std::vector<Texture *>, m_maptextures, i)
504- delete *i.current;
505- m_maptextures.clear();
506-
507- container_iterate_const(std::vector<AnimationGfx *>, m_animations, i)
508- delete *i.current;
509- m_animations.clear();
510-
511- delete m_roadtextures;
512- m_roadtextures = 0;
513- }
514-
515- if (not module or module & PicMod_UI) // Flush the cached Fontdatas
516+ * Clear all cached resources from the given module.
517+ *
518+ * \note This only removes the cache entries. If the corresonding resources
519+ * are still in use somewhere, they will not be freed.
520+ */
521+void Graphic::flush(PicMod const module)
522+{
523+ std::vector<std::string> eraselist;
524+
525+ for (pmit it = m_picturemap.begin(); it != m_picturemap.end(); ++it) {
526+ it->second.modules &= ~(1 << module);
527+ if (!it->second.modules)
528+ eraselist.push_back(it->first);
529+ }
530+
531+ while (!eraselist.empty()) {
532+ m_picturemap.erase(eraselist.back());
533+ eraselist.pop_back();
534+ }
535+
536+ if (module == PicMod_UI) // Flush the cached Fontdatas
537 UI::g_fh->flush_cache();
538 }
539
540@@ -440,7 +433,7 @@
541 }
542
543
544-Surface & Graphic::load_image(std::string const & fname, bool const alpha) {
545+PictureID Graphic::load_image(std::string const & fname, bool const alpha) {
546 //log("Graphic::LoadImage(\"%s\")\n", fname.c_str());
547 FileRead fr;
548 SDL_Surface * sdlsurf;
549@@ -453,9 +446,7 @@
550 if (!sdlsurf)
551 throw wexception("%s", IMG_GetError());
552
553- Surface & surf = create_surface(*sdlsurf, alpha);
554-
555- return surf;
556+ return convert_sdl_surface_to_picture(sdlsurf, alpha);
557 }
558
559 /**
560@@ -465,171 +456,197 @@
561 *
562 * \return 0 (a null-picture) if the picture cannot be loaded.
563 */
564-PictureID & Graphic::get_picture
565+const PictureID & Graphic::get_picture
566 (PicMod const module, const std::string & fname, bool alpha)
567 {
568 // Check if the picture is already loaded.
569- pmit it = m_picturemap[module].find(fname);
570+ pmit it = m_picturemap.find(fname);
571
572- if (it != m_picturemap[module].end()) {
573- return it->second;
574- } else {
575- Surface * surf;
576+ if (it == m_picturemap.end()) {
577+ PictureRec rec;
578
579 try {
580- surf = &load_image(fname, alpha);
581+ rec.picture = load_image(fname, alpha);
582 //log("Graphic::get_picture(): loading picture '%s'\n", fname.c_str());
583 } catch (std::exception const & e) {
584 log("WARNING: Could not open %s: %s\n", fname.c_str(), e.what());
585 return get_no_picture();
586 }
587- // Convert the surface accordingly
588-
589- // Fill in a free slot in the pictures array
590- Picture & pic = * new Picture();
591- PictureID id = PictureID(&pic);
592- m_picturemap[module].insert(std::make_pair(fname, id));
593-
594- assert(pic.fname == 0);
595- pic.fname = strdup(fname.c_str());
596-
597- // FIXME no proper check for NULL return value!
598- assert(pic.fname != 0);
599-
600- pic.surface = surf;
601-
602- it = m_picturemap[module].find(fname);
603+
604+ it = m_picturemap.insert(std::make_pair(fname, rec)).first;
605 }
606
607- it->second->module = module;
608-
609- return it->second;
610-}
611-
612-PictureID Graphic::get_picture
613- (PicMod const module, Surface & surf, std::string const & fname)
614-{
615- Picture & pic = * new Picture();
616- PictureID id = PictureID(&pic);
617- m_picturemap[module].insert(std::make_pair(fname, id));
618-
619- pic.module = module;
620- pic.surface = &surf;
621-
622- if (fname.size() != 0) {
623- assert(pic.fname == 0);
624- pic.fname = strdup(fname.c_str());
625- } else
626- pic.fname = 0;
627-
628- //return m_picturemap.find(fname);
629- return id;
630-}
631-
632-PictureID & Graphic::get_no_picture() const {
633- static PictureID invalid = PictureID(new Picture());
634- return invalid;
635+ it->second.modules |= 1 << module;
636+ return it->second.picture;
637+}
638+
639+/**
640+ * Add the given picture to the cache under the given name.
641+ *
642+ * This overwrites pre-existing cache entries, if any.
643+ */
644+void Graphic::add_picture_to_cache(PicMod module, const std::string & name, PictureID pic)
645+{
646+ PictureRec rec;
647+ rec.picture = pic;
648+ rec.modules = 1 << module;
649+ m_picturemap.insert(std::make_pair(name, rec));
650+}
651+
652+/**
653+ * \return an empty, invalid, null picture
654+ */
655+const PictureID & Graphic::get_no_picture() const
656+{
657+ return IPicture::null();
658 }
659
660 /**
661 * Produces a resized version of the specified picture
662 *
663- * This might not work with the renderer. Check g_gr->caps().resize_surfaces
664- * to be sure the resizing is possible.
665 * Might return same id if dimensions are the same
666 */
667 PictureID Graphic::get_resized_picture
668- (PictureID index,
669+ (PictureID src,
670 uint32_t const w, uint32_t const h,
671 ResizeMode const mode)
672 {
673- // Resizing is not possible with opengl surfaces
674- if (g_opengl)
675- g_gr->get_no_picture();
676-
677- Surface * const orig = index->surface;
678- if (orig->get_w() == w and orig->get_h() == h)
679- return index;
680-
681- uint32_t width = w;
682- uint32_t height = h;
683-
684- if (mode != ResizeMode_Loose) {
685- const double ratio_x = double(w) / orig->get_w();
686- const double ratio_y = double(h) / orig->get_h();
687-
688- // if proportions are to be kept, recalculate width and height
689- if ((ratio_x - ratio_y) > 0.00001) { // if not equal
690- double ratio = 0;
691-
692- if (ResizeMode_Clip == mode)
693- ratio = std::max (ratio_x, ratio_y);
694- else if (ResizeMode_LeaveBorder == mode)
695- ratio = std::max (ratio_x, ratio_y);
696- else // average
697- ratio = (ratio_x + ratio_y) / 2;
698-
699- width = uint32_t(orig->get_w() * ratio);
700- height = uint32_t(orig->get_h() * ratio);
701+ if (src->get_w() == w and src->get_h() == h)
702+ return src;
703+
704+ // First step: compute scaling factors
705+ Rect srcrect;
706+ Rect destrect;
707+
708+ if (mode == ResizeMode_Loose) {
709+ srcrect = Rect(Point(0, 0), src->get_w(), src->get_h());
710+ destrect = Rect(Point(0, 0), w, h);
711+ } else {
712+ const double ratio_x = double(w) / src->get_w();
713+ const double ratio_y = double(h) / src->get_h();
714+ double ratio;
715+
716+ if (ResizeMode_Clip == mode)
717+ ratio = std::max(ratio_x, ratio_y);
718+ else if (ResizeMode_LeaveBorder == mode)
719+ ratio = std::min(ratio_x, ratio_y);
720+ else // average
721+ ratio = (ratio_x + ratio_y) / 2;
722+
723+ uint32_t fullwidth(src->get_w() * ratio);
724+ uint32_t fullheight(src->get_h() * ratio);
725+
726+ if (fullwidth <= w) {
727+ srcrect.x = 0;
728+ srcrect.w = src->get_w();
729+ destrect.x = (w - fullwidth) / 2;
730+ destrect.w = fullwidth;
731+ } else {
732+ srcrect.w = std::min(src->get_w(), uint32_t(w / ratio));
733+ srcrect.x = (src->get_w() - srcrect.w) / 2;
734+ destrect.x = 0;
735+ destrect.w = w;
736+ }
737+
738+ if (fullheight <= h) {
739+ srcrect.y = 0;
740+ srcrect.h = src->get_h();
741+ destrect.y = (h - fullheight) / 2;
742+ destrect.h = fullheight;
743+ } else {
744+ srcrect.h = std::min(src->get_h(), uint32_t(h / ratio));
745+ srcrect.y = (src->get_h() - srcrect.h) / 2;
746+ destrect.y = 0;
747+ destrect.h = h;
748 }
749 }
750
751- PictureID pic = g_gr->create_picture_surface(w, h);
752+ // Second step: get source material
753+ SDL_Surface * srcsdl = 0;
754+ bool free_source = true;
755
756- if (mode == ResizeMode_Loose || (width == w && height == h)) {
757- if (g_opengl)
758+ if (upcast(SurfaceSDL, srcsurf, src.get())) {
759+ if
760+ (srcrect.x != 0 || srcrect.w != uint32_t(srcsurf->get_w()) ||
761+ srcrect.y != 0 || srcrect.h != uint32_t(srcsurf->get_h()))
762 {
763+ const SDL_PixelFormat & fmt = *srcsurf->get_sdl_surface()->format;
764+ srcsdl = SDL_CreateRGBSurface
765+ (SDL_SWSURFACE, srcrect.w, srcrect.h,
766+ fmt.BitsPerPixel, fmt.Rmask, fmt.Gmask, fmt.Bmask, fmt.Amask);
767+ SDL_Rect srcrc = {srcrect.x, srcrect.y, srcrect.w, srcrect.h};
768+ SDL_Rect dstrc = {0, 0, 0, 0};
769+ bool alpha = srcsurf->get_sdl_surface()->flags & SDL_SRCALPHA;
770+ uint8_t alphaval = srcsurf->get_sdl_surface()->format->alpha;
771+ SDL_SetAlpha(srcsurf->get_sdl_surface(), 0, 0);
772+ SDL_BlitSurface(srcsurf->get_sdl_surface(), &srcrc, srcsdl, &dstrc);
773+ SDL_SetAlpha(srcsurf->get_sdl_surface(), alpha ? SDL_SRCALPHA : 0, alphaval);
774 } else {
775- dynamic_cast<SurfaceSDL *>
776- (pic->surface)->set_sdl_surface(*resize(index, w, h));
777+ srcsdl = srcsurf->get_sdl_surface();
778+ free_source = false;
779 }
780 } else {
781- SurfaceSDL src(*resize(index, width, height));
782-
783- // apply rectangle by adjusted size
784- Rect srcrc;
785- srcrc.w = std::min(w, width);
786- srcrc.h = std::min(h, height);
787- srcrc.x = (width - srcrc.w) / 2;
788- srcrc.y = (height - srcrc.h) / 2;
789-
790-
791- g_gr->get_surface_renderer(pic)->blitrect // Get the rendertarget
792- (Point((w - srcrc.w) / 2, (h - srcrc.h) / 2),
793- get_picture(index->module, src), srcrc);
794- }
795- return pic;
796+ srcsdl = extract_sdl_surface(src->pixelaccess(), srcrect);
797+ }
798+
799+ // Third step: perform the zoom and placement
800+ SDL_Surface * zoomed = zoomSurface
801+ (srcsdl, double(destrect.w) / srcsdl->w, double(destrect.h) / srcsdl->h, 1);
802+ if (free_source)
803+ SDL_FreeSurface(srcsdl);
804+
805+ if (uint32_t(zoomed->w) != w || uint32_t(zoomed->h) != h) {
806+ const SDL_PixelFormat & fmt = *zoomed->format;
807+ SDL_Surface * placed = SDL_CreateRGBSurface
808+ (SDL_SWSURFACE, w, h,
809+ fmt.BitsPerPixel, fmt.Rmask, fmt.Gmask, fmt.Bmask, fmt.Amask);
810+ SDL_Rect srcrc = {0, 0, zoomed->w, zoomed->h};
811+ SDL_Rect dstrc = {destrect.x, destrect.y};
812+ SDL_SetAlpha(zoomed, 0, 0);
813+ SDL_BlitSurface(zoomed, &srcrc, placed, &dstrc);
814+ SDL_FreeSurface(zoomed);
815+ zoomed = placed;
816+ }
817+
818+ return convert_sdl_surface_to_picture(zoomed);
819 }
820
821 /**
822- * Produces a resized version of the specified picture. This works only for
823- * SDL rendering. Check g_gr->caps().resize_surfaces before calling this
824- * function.
825- *
826- * \param index position of the source picture in the stack
827- * \param w target width
828- * \param h target height
829- * \return resized version of picture
830+ * Create and return an \ref SDL_Surface that contains the given sub-rectangle
831+ * of the given pixel region.
832 */
833-SDL_Surface * Graphic::resize
834- (const PictureID index, uint32_t const w, uint32_t const h)
835+SDL_Surface * Graphic::extract_sdl_surface(IPixelAccess & pix, Rect srcrect)
836 {
837- Surface & orig = *g_gr->get_picture_surface(index);
838-
839- if (g_opengl)
840- throw wexception("Graphic::resize() not yet implemented for opengl");
841- else
842- {
843- SurfaceSDL & origsdl = dynamic_cast<SurfaceSDL &>(orig);
844- return
845- zoomSurface
846- (origsdl.get_sdl_surface(),
847- double(w) / orig.get_w(), double(h) / orig.get_h(),
848- 1);
849+ assert(srcrect.x >= 0);
850+ assert(srcrect.y >= 0);
851+ assert(srcrect.x + srcrect.w <= pix.get_w());
852+ assert(srcrect.y + srcrect.h <= pix.get_h());
853+
854+ const SDL_PixelFormat & fmt = pix.format();
855+ SDL_Surface * dest = SDL_CreateRGBSurface
856+ (SDL_SWSURFACE, srcrect.w, srcrect.h,
857+ fmt.BitsPerPixel, fmt.Rmask, fmt.Gmask, fmt.Bmask, fmt.Amask);
858+
859+ pix.lock(IPixelAccess::Lock_Normal);
860+ SDL_LockSurface(dest);
861+
862+ uint32_t srcpitch = pix.get_pitch();
863+ uint32_t rowsize = srcrect.w * fmt.BytesPerPixel;
864+ uint8_t * srcpix = pix.get_pixels() + srcpitch * srcrect.y + fmt.BytesPerPixel * srcrect.x;
865+ uint8_t * dstpix = static_cast<uint8_t *>(dest->pixels);
866+
867+ for (uint32_t y = 0; y < srcrect.h; ++y) {
868+ memcpy(dstpix, srcpix, rowsize);
869+ srcpix += srcpitch;
870+ dstpix += dest->pitch;
871 }
872+
873+ SDL_UnlockSurface(dest);
874+ pix.unlock(IPixelAccess::Unlock_NoChange);
875+
876+ return dest;
877 }
878
879-
880 /**
881 * Stores the picture size in pw and ph.
882 * Throws an exception if the picture doesn't exist.
883@@ -637,20 +654,27 @@
884 void Graphic::get_picture_size
885 (const PictureID & pic, uint32_t & w, uint32_t & h) const
886 {
887- assert (pic->surface);
888- Surface & bmp = *pic->surface;
889-
890- w = bmp.get_w();
891- h = bmp.get_h();
892-}
893-
894-/**
895- * Saves a surface to a png. This can be a file or part of a stream.
896+ w = pic->get_w();
897+ h = pic->get_h();
898+}
899+
900+/**
901+ * This is purely a convenience function intended to allow casting
902+ * pointers without including a whole bunch of headers.
903+ */
904+PictureID Graphic::get_offscreen_picture(OffscreenSurfacePtr surface) const
905+{
906+ return surface;
907+}
908+
909+
910+/**
911+ * Saves a pixel region to a png. This can be a file or part of a stream.
912 *
913 * @param surf The Surface to save
914 * @param sw a StreamWrite where the png is written to
915 */
916-void Graphic::save_png(Surface & surf, StreamWrite * sw) const
917+void Graphic::save_png(IPixelAccess & pix, StreamWrite * sw) const
918 {
919 // Save a png
920 png_structp png_ptr =
921@@ -686,7 +710,7 @@
922
923 // Fill info struct
924 png_set_IHDR
925- (png_ptr, info_ptr, surf.get_w(), surf.get_h(),
926+ (png_ptr, info_ptr, pix.get_w(), pix.get_h(),
927 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE,
928 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
929
930@@ -701,64 +725,31 @@
931 png_set_packing(png_ptr);
932
933 {
934- uint32_t surf_w = surf.get_w();
935- uint32_t surf_h = surf.get_h();
936+ uint32_t surf_w = pix.get_w();
937+ uint32_t surf_h = pix.get_h();
938 uint32_t row_size = 4 * surf_w;
939
940- png_bytep rowb = 0;
941- png_bytep rowp = 0;
942+ boost::scoped_array<png_byte> row(new png_byte[row_size]);
943
944 //Write each row
945- SDL_PixelFormat * fmt;
946- upcast(SurfaceSDL, sdlsurf, &surf);
947-#ifdef USE_OPENGL
948- upcast(SurfaceOpenGL, oglsurf, &surf);
949-#endif
950- if (sdlsurf)
951- {
952- fmt = const_cast<SDL_PixelFormat *>(&sdlsurf->format());
953- rowb = (new png_byte[row_size]);
954- if (!rowb)
955- throw wexception("Out of memory.");
956- }
957-#ifdef USE_OPENGL
958- else if (oglsurf) {
959- oglsurf->lock();
960- fmt = 0;
961- }
962-#endif
963- else
964- return;
965-
966+ const SDL_PixelFormat & fmt = pix.format();
967+ pix.lock(IPixelAccess::Lock_Normal);
968
969 // Write each row
970 for (uint32_t y = 0; y < surf_h; ++y) {
971- rowp = rowb;
972- if (sdlsurf)
973- for (uint32_t x = 0; x < surf_w; rowp += 4, ++x)
974- SDL_GetRGBA
975- (sdlsurf->get_pixel(x, y),
976- fmt,
977- rowp + 0, rowp + 1, rowp + 2, rowp + 3);
978-#ifdef USE_OPENGL
979- else if (oglsurf) {
980- rowb = static_cast<png_bytep>
981- (oglsurf->get_pixels() +
982- oglsurf->get_pitch() * (surf_h - y - 1));
983+ for (uint32_t x = 0; x < surf_w; ++x) {
984+ RGBAColor color;
985+ color.set(fmt, pix.get_pixel(x, y));
986+ row[4 * x] = color.r;
987+ row[4 * x + 1] = color.g;
988+ row[4 * x + 2] = color.b;
989+ row[4 * x + 3] = color.a;
990 }
991-#endif
992- else
993- throw wexception("Try to save save_png with unknown surface\n");
994
995- png_write_row(png_ptr, rowb);
996+ png_write_row(png_ptr, row.get());
997 }
998-#ifdef USE_OPENGL
999- if (oglsurf)
1000- oglsurf->unlock();
1001- else
1002-#endif
1003- if (sdlsurf)
1004- delete rowb;
1005+
1006+ pix.unlock(IPixelAccess::Unlock_NoChange);
1007 }
1008
1009 // End write
1010@@ -767,267 +758,175 @@
1011 }
1012
1013 /**
1014-* Saves a PictureID to a png. This can be a file or part of a stream. This
1015-* function retrieves the Surface for the PictureID and calls
1016-* save_png(Surface, StreamWrite)
1017-*
1018-* @param surf The Surface to save
1019-* @param sw a StreamWrite where the png is written to
1020-*/
1021+ * Saves a surface to a png. This can be a file or part of a stream.
1022+ *
1023+ * @param surf The Surface to save
1024+ * @param sw a StreamWrite where the png is written to
1025+ */
1026+void Graphic::save_png(SurfacePtr surf, StreamWrite * sw) const
1027+{
1028+ save_png(surf->pixelaccess(), sw);
1029+}
1030+
1031+/**
1032+ * Saves a PictureID to a png. This can be a file or part of a stream. This
1033+ * function retrieves the Surface for the PictureID and calls
1034+ * save_png(Surface, StreamWrite)
1035+ *
1036+ * @param surf The Surface to save
1037+ * @param sw a StreamWrite where the png is written to
1038+ */
1039 void Graphic::save_png(const PictureID & pic_index, StreamWrite * sw) const
1040 {
1041- Surface & surf = const_cast<Surface &>(*get_picture_surface(pic_index));
1042- save_png(surf, sw);
1043-}
1044-
1045-/**
1046- * Create a offscreen surface of specified size and return as PictureID.
1047- * The surface is put into a normal slot in the picture array so the surface
1048- * can be used in normal blit() operations. A RenderTarget for the surface can
1049- * be obtained using get_surface_renderer().
1050- * \note Surfaces do not belong to a module and must be freed explicitly.
1051- *
1052- * @param w width of the new surface
1053- * @param h height of the new surface
1054- * @param alpha if true the surface is created with alpha channel
1055- * @return PictureID of the new created offscreen surface
1056-*/
1057-PictureID Graphic::create_picture_surface(int32_t w, int32_t h, bool alpha)
1058-{
1059- //log(" Graphic::create_picture_surface(%d, %d)\n", w, h);
1060- Surface & surf = create_surface(w, h, alpha);
1061-
1062- Picture & pic = *new Picture();
1063- PictureID id = PictureID(&pic);
1064- m_picturemap[PicSurface].insert(std::make_pair("", id));
1065-
1066- pic.module = PicSurface; // mark as surface
1067- pic.surface = &surf;
1068- assert(pic.rendertarget == 0);
1069- pic.rendertarget = new RenderTarget(pic.surface);
1070-
1071- return id;
1072-}
1073-
1074-/**
1075- * Create a Surface from a SDL_Surface. This creates a Surface for OpenGL or
1076- * Software rendering depending on the actual setting. The SDL_Surface must
1077- * not be used after calling this. Surface takes care of the SDL_Surface.
1078- *
1079- * @param surf a SDL_Surface from which the Surface will be created
1080+ save_png(pic_index->pixelaccess(), sw);
1081+}
1082+
1083+/**
1084+ * Create a Picture from an SDL_Surface.
1085+ *
1086+ * @param surf a SDL_Surface from which the Surface will be created; this function
1087+ * takes ownership of surf
1088 * @param alpha if true the surface is created with alpha channel
1089 * @return the new Surface created from the SDL_Surface
1090 */
1091-Surface & Graphic::create_surface(SDL_Surface & surf, bool alpha)
1092+PictureID Graphic::convert_sdl_surface_to_picture(SDL_Surface * surf, bool alpha)
1093 {
1094 if (g_opengl)
1095 {
1096 #ifdef USE_OPENGL
1097- return *new SurfaceOpenGL(surf);
1098+ return PictureID(new GLPictureTexture(surf));
1099 #endif
1100 } else {
1101 SDL_Surface * surface;
1102 if (alpha)
1103- surface = SDL_DisplayFormatAlpha(&surf);
1104- else
1105- surface = SDL_DisplayFormat(&surf);
1106- SDL_FreeSurface(&surf);
1107- return *new SurfaceSDL(*surface);
1108- }
1109-}
1110-
1111-/**
1112-* Create a Surface from an other Surface. This makes a copy of a Surface.
1113-*
1114-* @param surf the surface which will be copied to the new surface
1115-* @param alpha if true the surface is created with alpha channel
1116-* @return the new Surface
1117-*/
1118-Surface & Graphic::create_surface(Surface & surf, bool alpha)
1119-{
1120- upcast(SurfaceSDL, sdlsurf, &surf);
1121- if (sdlsurf)
1122- {
1123- if (alpha)
1124- return
1125- *new SurfaceSDL
1126- (*SDL_DisplayFormatAlpha(sdlsurf->get_sdl_surface()));
1127- else
1128- return
1129- *new SurfaceSDL
1130- (*SDL_DisplayFormat(sdlsurf->get_sdl_surface()));
1131- }
1132- else
1133- {
1134- Surface & tsurf = create_surface(surf.get_w(), surf.get_h());
1135-
1136- surf.lock();
1137- tsurf.lock();
1138- for (unsigned int x = 0; x < surf.get_w(); x++)
1139- for (unsigned int y = 0; y < surf.get_h(); y++)
1140- {
1141- tsurf.set_pixel(x, y, surf.get_pixel(x, y));
1142- }
1143- surf.unlock();
1144- tsurf.unlock();
1145-
1146- return tsurf;
1147- }
1148-}
1149-
1150-/**
1151-* Create a empty offscreen surface of specified size.
1152-*
1153-* @param w width of the new surface
1154-* @param h height of the new surface
1155-* @param alpha if true the surface is created with alpha channel
1156-* @return the new created surface
1157-*/
1158-Surface & Graphic::create_surface(int32_t w, int32_t h, bool alpha)
1159-{
1160- if (g_opengl)
1161- {
1162-#ifdef USE_OPENGL
1163- return *new SurfaceOpenGL(w, h);
1164-#endif
1165- } else {
1166- const SDL_PixelFormat & format = m_screen->format();
1167- SDL_Surface & tsurf = *SDL_CreateRGBSurface
1168- (SDL_SWSURFACE,
1169- w, h,
1170- format.BitsPerPixel,
1171- format.Rmask, format.Gmask, format.Bmask, format.Amask);
1172- if (alpha) {
1173- SDL_Surface & surf = *SDL_DisplayFormatAlpha(&tsurf);
1174- SDL_FreeSurface(&tsurf);
1175- return *new SurfaceSDL(surf);
1176- }
1177- return *new SurfaceSDL(tsurf);
1178- }
1179-}
1180-
1181-/**
1182- * Free the given surface.
1183- * Unlike normal pictures, surfaces are not freed by flush().
1184- *
1185- * @param picid the PictureID ot to be freed
1186-*/
1187-void Graphic::free_picture_surface(const PictureID & picid) {
1188- if
1189- (picid->module != PicMod_Font &&
1190- picid->module != PicSurface)
1191- {
1192- log
1193- ("Graphic::free_surface ignoring free of %u %s\n",
1194- picid->module, picid->fname);
1195- return;
1196- }
1197- assert(picid->module == PicMod_Font || picid->module == PicSurface);
1198-
1199- delete picid->surface;
1200- picid->surface = 0;
1201- delete picid->rendertarget;
1202- picid->rendertarget = 0;
1203- delete picid->fname;
1204- picid->fname = 0;
1205-
1206- container_iterate(Picturemap, m_picturemap[picid->module], it)
1207- if (it.current->second == picid) {
1208- m_picturemap[picid->module].erase(it.current);
1209- break;
1210- }
1211-}
1212-
1213-/**
1214-* create a grayed version.
1215-*
1216-* @param picid the PictureID ot to grayed out
1217-* @return the gray version of the picture
1218-*/
1219-PictureID Graphic::create_grayed_out_pic(const PictureID & picid) {
1220- if (picid != get_no_picture()) {
1221- Surface & s = create_surface(*get_picture_surface(picid), true);
1222-#ifdef USE_OPENGL
1223- upcast(SurfaceOpenGL, gl_dest, &s);
1224- upcast(SurfaceOpenGL, gl_src, get_picture_surface(picid));
1225-#endif
1226- upcast(SurfaceSDL, sdl_s, &s);
1227- SDL_PixelFormat const * format = 0;
1228- if (sdl_s)
1229- format = &(sdl_s->format());
1230- uint32_t const w = s.get_w(), h = s.get_h();
1231-#ifdef USE_OPENGL
1232- if (gl_src)
1233- gl_src->lock();
1234-#endif
1235- s.lock();
1236- for (uint32_t y = 0; y < h; ++y)
1237- for (uint32_t x = 0; x < w; ++x) {
1238- uint8_t r, g, b, a;
1239-#ifdef USE_OPENGL
1240- if (gl_src)
1241- {
1242- uint32_t pixel = gl_src->get_pixel(x, y);
1243- r = pixel & 0xFF;
1244- g = (pixel & 0xFF00) >> 8;
1245- b = (pixel & 0xFF0000) >> 16;
1246- a = (pixel & 0xFF000000) >> 24;
1247- } else
1248-#endif
1249- // FIXME need for const_cast is SDL bug #421
1250- SDL_GetRGBA
1251- (sdl_s->get_pixel(x, y),
1252- const_cast<SDL_PixelFormat *>(format), &r, &g, &b, &a);
1253-
1254- // Halve the opacity to give some difference for pictures that are
1255- // grayscale to begin with.
1256- a >>= 1;
1257-
1258- uint8_t const gray =
1259- (luminance_table_r[r] +
1260- luminance_table_g[g] +
1261- luminance_table_b[b] +
1262- 8388608U) // compensate for truncation: .5 * 2^24
1263- >> 24;
1264-
1265- // NOTE const_cast is needed for SDL-1.2 older than revision 3008
1266-#ifdef USE_OPENGL
1267- if (gl_dest)
1268- {
1269- gl_dest->set_pixel(x, y, g + (g << 8) + (g << 16) + (a << 24));
1270- } else
1271-#endif
1272- sdl_s->set_pixel
1273- (x, y,
1274- SDL_MapRGBA
1275- (const_cast<SDL_PixelFormat *>(format),
1276- gray, gray, gray, a));
1277-
1278- }
1279- s.unlock();
1280-#ifdef USE_OPENGL
1281- if (gl_src)
1282- gl_src->unlock();
1283-#endif
1284- return get_picture(PicSurface, s);
1285- } else
1286+ surface = SDL_DisplayFormatAlpha(surf);
1287+ else
1288+ surface = SDL_DisplayFormat(surf);
1289+ SDL_FreeSurface(surf);
1290+ return PictureID(new SurfaceSDL(*surface));
1291+ }
1292+}
1293+
1294+/**
1295+ * Create a empty offscreen surface of specified size.
1296+ *
1297+ * @param w width of the new surface
1298+ * @param h height of the new surface
1299+ * @param alpha if true the surface is created with alpha channel
1300+ * @return the new created surface
1301+ */
1302+OffscreenSurfacePtr Graphic::create_offscreen_surface(int32_t w, int32_t h, bool alpha)
1303+{
1304+#ifdef USE_OPENGL
1305+ if (g_opengl)
1306+ {
1307+
1308+ throw wexception("OpenGL mode does not support offscreen surfaces");
1309+ }
1310+ else
1311+#endif
1312+ {
1313+ const SDL_PixelFormat & format = *m_sdl_screen->format;
1314+ SDL_Surface & tsurf = *SDL_CreateRGBSurface
1315+ (SDL_SWSURFACE,
1316+ w, h,
1317+ format.BitsPerPixel,
1318+ format.Rmask, format.Gmask, format.Bmask, format.Amask);
1319+ if (alpha) {
1320+ SDL_Surface & surf = *SDL_DisplayFormatAlpha(&tsurf);
1321+ SDL_FreeSurface(&tsurf);
1322+ return OffscreenSurfacePtr(new SurfaceSDL(surf));
1323+ }
1324+ return OffscreenSurfacePtr(new SurfaceSDL(tsurf));
1325+ }
1326+}
1327+
1328+/**
1329+ * Create a picture with initially undefined contents.
1330+ *
1331+ * Use \ref IPicture::pixelaccess to upload image data afterwards.
1332+ *
1333+ * @param w width of the new surface
1334+ * @param h height of the new surface
1335+ * @param alpha if true the surface is created with alpha channel
1336+ * @return the new created surface
1337+ */
1338+PictureID Graphic::create_picture(int32_t w, int32_t h, bool alpha)
1339+{
1340+#ifdef USE_OPENGL
1341+ if (g_opengl)
1342+ {
1343+ return PictureID(new GLPictureTexture(w, h));
1344+ }
1345+ else
1346+#endif
1347+ {
1348+ const SDL_PixelFormat & format = *m_sdl_screen->format;
1349+ SDL_Surface & tsurf = *SDL_CreateRGBSurface
1350+ (SDL_SWSURFACE,
1351+ w, h,
1352+ format.BitsPerPixel,
1353+ format.Rmask, format.Gmask, format.Bmask, format.Amask);
1354+ if (alpha) {
1355+ SDL_Surface & surf = *SDL_DisplayFormatAlpha(&tsurf);
1356+ SDL_FreeSurface(&tsurf);
1357+ return OffscreenSurfacePtr(new SurfaceSDL(surf));
1358+ }
1359+ return PictureID(new SurfaceSDL(tsurf));
1360+ }
1361+}
1362+
1363+
1364+/**
1365+ * Create a grayed version of the given picture.
1366+ *
1367+ * @param picid the PictureID ot to grayed out
1368+ * @return the gray version of the picture
1369+ */
1370+PictureID Graphic::create_grayed_out_pic(const PictureID & picid)
1371+{
1372+ if (!picid || !picid->valid())
1373 return get_no_picture();
1374-}
1375-
1376-
1377-/**
1378- * Returns the RenderTarget for the given surface
1379-*/
1380-RenderTarget * Graphic::get_surface_renderer(const PictureID & pic) {
1381- //assert(pic < m_pictures.size());
1382- // assert(m_pictures[pic].module == 0xff); fails showing terrains in editor
1383-
1384- RenderTarget & rt = *pic->rendertarget;
1385-
1386- rt.reset();
1387-
1388- return &rt;
1389-}
1390+
1391+ IPixelAccess & origpix = picid->pixelaccess();
1392+ uint32_t w = picid->get_w();
1393+ uint32_t h = picid->get_h();
1394+ const SDL_PixelFormat & origfmt = origpix.format();
1395+
1396+ PictureID destpicture = create_picture(w, h, origfmt.Amask);
1397+ IPixelAccess & destpix = destpicture->pixelaccess();
1398+ const SDL_PixelFormat & destfmt = destpix.format();
1399+
1400+ origpix.lock(IPixelAccess::Lock_Normal);
1401+ destpix.lock(IPixelAccess::Lock_Discard);
1402+ for (uint32_t y = 0; y < h; ++y) {
1403+ for (uint32_t x = 0; x < w; ++x) {
1404+ RGBAColor color;
1405+
1406+ color.set(origfmt, origpix.get_pixel(x, y));
1407+
1408+ // Halve the opacity to give some difference for pictures that are
1409+ // grayscale to begin with.
1410+ color.a >>= 1;
1411+
1412+ uint8_t const gray =
1413+ (luminance_table_r[color.r] +
1414+ luminance_table_g[color.g] +
1415+ luminance_table_b[color.b] +
1416+ 8388608U) // compensate for truncation: .5 * 2^24
1417+ >> 24;
1418+
1419+ color.r = color.g = color.b = gray;
1420+
1421+ destpix.set_pixel(x, y, color.map(destfmt));
1422+ }
1423+ }
1424+ origpix.unlock(IPixelAccess::Unlock_NoChange);
1425+ destpix.unlock(IPixelAccess::Unlock_Update);
1426+
1427+ return destpicture;
1428+}
1429+
1430
1431 /**
1432 * Creates a terrain texture.
1433@@ -1046,7 +945,7 @@
1434 {
1435 try {
1436 m_maptextures.push_back
1437- (new Texture(fnametempl, frametime, m_screen->format()));
1438+ (new Texture(fnametempl, frametime, *m_sdl_screen->format));
1439 } catch (std::exception const & e) {
1440 log("Failed to load maptexture %s: %s\n", &fnametempl, e.what());
1441 return 0;
1442@@ -1123,10 +1022,10 @@
1443 w = h = 0;
1444 } else {
1445 // Get the frame and its data. Ignore playerclrs.
1446- Surface const & frame =
1447- *gfx->get_frame((time / data->frametime) % gfx->nr_frames());
1448- w = frame.get_w();
1449- h = frame.get_h();
1450+ const PictureID & frame =
1451+ gfx->get_frame((time / data->frametime) % gfx->nr_frames());
1452+ w = frame->get_w();
1453+ h = frame->get_h();
1454 }
1455 }
1456
1457@@ -1137,7 +1036,7 @@
1458 {
1459 log("Save screenshot to %s\n", &fname);
1460 StreamWrite * sw = g_fs->OpenStreamWrite(std::string(&fname));
1461- save_png(*m_screen, sw);
1462+ save_png(m_screen, sw);
1463 delete sw;
1464 }
1465
1466@@ -1163,21 +1062,6 @@
1467 static_cast<StreamWrite *>(png_get_io_ptr(png_ptr))->Flush();
1468 }
1469
1470-
1471-/**
1472-* Returns the bitmap that belongs to the given picture ID.
1473-* May return 0 if the given picture does not exist.
1474-*/
1475-Surface * Graphic::get_picture_surface(const PictureID & id)
1476-{
1477- return id->surface;
1478-}
1479-
1480-const Surface * Graphic::get_picture_surface(const PictureID & id) const
1481-{
1482- return id->surface;
1483-}
1484-
1485 /**
1486 * Retrieve the animation with the given number.
1487 *
1488@@ -1210,7 +1094,7 @@
1489 * if not done yet.
1490 * \return The road texture
1491 */
1492-Surface * Graphic::get_road_texture(int32_t const roadtex)
1493+PictureID Graphic::get_road_texture(int32_t const roadtex)
1494 {
1495 if (not m_roadtextures) {
1496 // Load the road textures
1497@@ -1223,7 +1107,6 @@
1498 }
1499
1500 return
1501- get_picture_surface
1502- (roadtex == Widelands::Road_Normal ?
1503- m_roadtextures->pic_road_normal : m_roadtextures->pic_road_busy);
1504+ (roadtex == Widelands::Road_Normal ?
1505+ m_roadtextures->pic_road_normal : m_roadtextures->pic_road_busy);
1506 }
1507
1508=== modified file 'src/graphic/graphic.h'
1509--- src/graphic/graphic.h 2010-11-15 18:25:31 +0000
1510+++ src/graphic/graphic.h 2010-11-29 19:01:16 +0000
1511@@ -21,8 +21,8 @@
1512 #define GRAPHIC_H
1513
1514 #include "animation_gfx.h"
1515-#include "picture.h"
1516 #include "picture_id.h"
1517+#include "surfaceptr.h"
1518 #include "rect.h"
1519
1520 #include <png.h>
1521@@ -41,8 +41,7 @@
1522
1523 namespace UI {struct ProgressWindow;}
1524
1525-struct Surface;
1526-class Texture;
1527+struct IPixelAccess;
1528 struct RenderTarget;
1529 struct Graphic;
1530 struct Road_Textures;
1531@@ -84,15 +83,29 @@
1532 {
1533 /// The renderer allows rendering (blit, draw_line) to offscreen surfaces
1534 bool offscreen_rendering;
1535- /// It is possible to resize surfaces with get_resized_picture()
1536- bool resize_surfaces;
1537- /// It is possible to resize surfaces while bliting
1538- bool blit_resized;
1539 /// The capabilities of the opengl hardware and drive
1540 GLCaps gl;
1541 };
1542
1543 /**
1544+ * Picture caches (modules).
1545+ *
1546+ * \ref Graphic maintains a cache of \ref PictureID s to avoid continuous re-loading of
1547+ * pictures that may not be referenced all the time (e.g. UI elements).
1548+ *
1549+ * This cache is separated into different modules, and can be flushed per-module.
1550+ */
1551+enum PicMod {
1552+ PicMod_UI = 0,
1553+ PicMod_Menu,
1554+ PicMod_Game,
1555+
1556+ // Must be last
1557+ PicMod_Last
1558+};
1559+
1560+
1561+/**
1562 * A renderer to get pixels to a 16bit framebuffer.
1563 *
1564 * Picture IDs can be allocated using \ref get_picture() and used in
1565@@ -102,8 +115,7 @@
1566 * graphics system is unloaded, or when \ref flush() is called with the
1567 * appropriate module flag; the user can request to flush one single picture
1568 * alone, but this is only used (and useful) in the editor.
1569-*/
1570-
1571+ */
1572 struct Graphic {
1573 Graphic
1574 (int32_t w, int32_t h, int32_t bpp,
1575@@ -124,31 +136,26 @@
1576
1577 void flush(PicMod module);
1578 void flush_animations();
1579- Surface & load_image(std::string const &, bool alpha = false);
1580- PictureID & get_picture(PicMod, std::string const &, bool alpha = true)
1581+ PictureID load_image(std::string const &, bool alpha = false);
1582+ const PictureID & get_picture(PicMod, std::string const &, bool alpha = true)
1583 __attribute__ ((pure));
1584- PictureID get_picture
1585- (PicMod module, Surface &, const std::string & name = "");
1586- //__attribute__ ((pure));
1587- PictureID & get_no_picture() const;
1588-
1589- Surface * get_picture_surface(const PictureID & id);
1590- const Surface * get_picture_surface(const PictureID & id) const;
1591+ void add_picture_to_cache(PicMod, const std::string &, PictureID);
1592+ const PictureID & get_no_picture() const;
1593
1594 void get_picture_size
1595 (const PictureID & pic, uint32_t & w, uint32_t & h) const;
1596+ PictureID get_offscreen_picture(OffscreenSurfacePtr surface) const;
1597
1598 void save_png(const PictureID &, StreamWrite *) const;
1599- void save_png(Surface & surf, StreamWrite *) const;
1600-
1601- PictureID create_picture_surface(int32_t w, int32_t h, bool alpha = false);
1602- Surface & create_surface(SDL_Surface &, bool alpha = false);
1603- Surface & create_surface(Surface &, bool alpha = false);
1604- Surface & create_surface(int32_t w, int32_t h, bool alpha = false);
1605- void free_picture_surface(const PictureID & pic);
1606+ void save_png(SurfacePtr surf, StreamWrite *) const;
1607+ void save_png(IPixelAccess & pix, StreamWrite *) const;
1608+
1609+ PictureID convert_sdl_surface_to_picture(SDL_Surface *, bool alpha = false);
1610+
1611+ OffscreenSurfacePtr create_offscreen_surface(int32_t w, int32_t h, bool alpha = false);
1612+ PictureID create_picture(int32_t w, int32_t h, bool alpha = false);
1613
1614 PictureID create_grayed_out_pic(const PictureID & picid);
1615- RenderTarget * get_surface_renderer(const PictureID & pic);
1616
1617 enum ResizeMode {
1618 // do not worry about proportions, just sketch to requested size
1619@@ -163,7 +170,6 @@
1620
1621 PictureID get_resized_picture
1622 (PictureID, uint32_t w, uint32_t h, ResizeMode);
1623- SDL_Surface * resize(const PictureID index, uint32_t w, uint32_t h);
1624
1625 uint32_t get_maptexture(char const & fnametempl, uint32_t frametime);
1626 void animate_maptextures(uint32_t time);
1627@@ -183,10 +189,13 @@
1628 Texture * get_maptexture_data(uint32_t id);
1629 AnimationGfx * get_animation(uint32_t) const;
1630
1631- Surface * get_road_texture(int32_t roadtex);
1632+ PictureID get_road_texture(int32_t roadtex);
1633
1634 GraphicCaps const & caps() const throw () {return m_caps;}
1635
1636+private:
1637+ SDL_Surface * extract_sdl_surface(IPixelAccess & pix, Rect srcrect);
1638+
1639 protected:
1640 // Static helper function for png writing
1641 static void m_png_write_function
1642@@ -197,7 +206,7 @@
1643
1644 /// This is the main screen Surface.
1645 /// A RenderTarget for this can be retrieved with get_render_target()
1646- Surface * m_screen;
1647+ SurfacePtr m_screen;
1648 /// This saves a copy of the screen SDL_Surface. This is needed for
1649 /// opengl rendering as the SurfaceOpenGL does not use it. It allows
1650 /// manipulation the screen context.
1651@@ -214,12 +223,19 @@
1652 /// stores which features the current renderer has
1653 GraphicCaps m_caps;
1654
1655- /// hash of filename/picture ID pairs
1656- std::vector
1657- <std::map<std::string, boost::shared_ptr<Picture> > > m_picturemap;
1658- typedef std::map<std::string, boost::shared_ptr<Picture> > Picturemap;
1659+ struct PictureRec {
1660+ PictureID picture;
1661+
1662+ /// bit-mask of modules that this picture exists in
1663+ uint32_t modules;
1664+ };
1665+
1666+ typedef std::map<std::string, PictureRec> Picturemap;
1667 typedef Picturemap::iterator pmit;
1668
1669+ /// hash of cached filename/picture pairs
1670+ Picturemap m_picturemap;
1671+
1672 Road_Textures * m_roadtextures;
1673 std::vector<Texture *> m_maptextures;
1674 std::vector<AnimationGfx *> m_animations;
1675@@ -229,4 +245,3 @@
1676 extern bool g_opengl;
1677
1678 #endif
1679-
1680
1681=== added file 'src/graphic/offscreensurface.h'
1682--- src/graphic/offscreensurface.h 1970-01-01 00:00:00 +0000
1683+++ src/graphic/offscreensurface.h 2010-11-29 19:01:16 +0000
1684@@ -0,0 +1,34 @@
1685+/*
1686+ * Copyright (C) 2010 by the Widelands Development Team
1687+ *
1688+ * This program is free software; you can redistribute it and/or
1689+ * modify it under the terms of the GNU General Public License
1690+ * as published by the Free Software Foundation; either version 2
1691+ * of the License, or (at your option) any later version.
1692+ *
1693+ * This program is distributed in the hope that it will be useful,
1694+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1695+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1696+ * GNU General Public License for more details.
1697+ *
1698+ * You should have received a copy of the GNU General Public License
1699+ * along with this program; if not, write to the Free Software
1700+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
1701+ *
1702+ */
1703+
1704+#ifndef OFFSCREENSURFACE_H
1705+#define OFFSCREENSURFACE_H
1706+
1707+#include "picture.h"
1708+#include "pixelaccess.h"
1709+#include "surface.h"
1710+
1711+/**
1712+ * Interface to surfaces that can act conveniently both as
1713+ * source and as destination for rendering.
1714+ */
1715+struct IOffscreenSurface : Surface, IPicture, IPixelAccess {
1716+};
1717+
1718+#endif // OFFSCREENSURFACE_H
1719
1720=== modified file 'src/graphic/picture.cc'
1721--- src/graphic/picture.cc 2009-07-17 18:12:17 +0000
1722+++ src/graphic/picture.cc 2010-11-29 19:01:16 +0000
1723@@ -1,5 +1,5 @@
1724 /*
1725- * Copyright (C) 2009 by the Widelands Development Team
1726+ * Copyright (C) 2009-2010 by the Widelands Development Team
1727 *
1728 * This program is free software; you can redistribute it and/or
1729 * modify it under the terms of the GNU General Public License
1730@@ -19,12 +19,25 @@
1731
1732 #include "picture.h"
1733
1734-#include "surface.h"
1735-#include "rendertarget.h"
1736-
1737-Picture::~Picture() {
1738- delete surface;
1739- free(fname);
1740- delete rendertarget;
1741+#include "wexception.h"
1742+
1743+struct NullPicture : IPicture {
1744+ virtual bool valid() {return false;}
1745+
1746+ virtual uint32_t get_w() {return 0;}
1747+ virtual uint32_t get_h() {return 0;}
1748+
1749+ virtual IPixelAccess & pixelaccess() {throw wexception("pixelaccess() attempted on null picture");}
1750+ virtual Surface & surface() {throw wexception("surface() attempted on null picture");}
1751+};
1752+
1753+/**
1754+ * \return an invalid, null picture
1755+ *
1756+ * \see Graphic::get_no_picture
1757+ */
1758+const PictureID & IPicture::null()
1759+{
1760+ static PictureID thenull(new NullPicture);
1761+ return thenull;
1762 }
1763-
1764
1765=== modified file 'src/graphic/picture.h'
1766--- src/graphic/picture.h 2010-11-10 20:05:21 +0000
1767+++ src/graphic/picture.h 2010-11-29 19:01:16 +0000
1768@@ -1,5 +1,5 @@
1769 /*
1770- * Copyright (C) 2002-2004, 2006-2009 by the Widelands Development Team
1771+ * Copyright (C) 2002-2004, 2006-2010 by the Widelands Development Team
1772 *
1773 * This program is free software; you can redistribute it and/or
1774 * modify it under the terms of the GNU General Public License
1775@@ -20,43 +20,36 @@
1776 #ifndef PICTURE_H
1777 #define PICTURE_H
1778
1779-/***
1780- * Picture/PictureID
1781- *
1782- * PictureID is a reference to a picture
1783- * picmod is used to specify which buffer picture is loaded in.
1784- * warning: a picture can be loaded multiple times in multiple buffers
1785- * when buffer is flushed pictures will hang around till the last reference
1786- * is gone too
1787- ***/
1788-
1789-
1790-struct RenderTarget;
1791+#include <stdint.h>
1792+#include <string>
1793+
1794+#include "picture_id.h"
1795+
1796+struct IPixelAccess;
1797 struct Surface;
1798
1799-/// picture module flags
1800-enum PicMod {
1801- INVALID = 0,
1802- PicMod_UI = 1,
1803- PicMod_Menu = 2,
1804- PicMod_Game = 3,
1805- PicMod_Font = 4,
1806- PicSurface = 5,
1807- MaxModule = 6 //MaxModule ALWAYS has to be the 'size' of picmod
1808-};
1809-
1810-struct Picture {
1811- Picture() : module(INVALID), surface(0), fname(0), rendertarget(0) {}
1812- ~Picture();
1813- //void operator delete(void * p);
1814-
1815- //PicMod lists which 'buffer' to load the images in.
1816- // INVALID if unused, MaxModule not a legal module
1817- PicMod module;
1818- Surface * surface;
1819-
1820- char * fname; // module & (PicMod_UI|PicMod_Menu|PicMod_Game)
1821- RenderTarget * rendertarget; // module & (PicMod_Font | PicSurface)
1822+/**
1823+ * Interface to a bitmap that can act as the source of a rendering
1824+ * operation.
1825+ */
1826+struct IPicture {
1827+ IPicture() {}
1828+ virtual ~IPicture() {}
1829+
1830+ virtual bool valid() = 0;
1831+
1832+ virtual uint32_t get_w() = 0;
1833+ virtual uint32_t get_h() = 0;
1834+
1835+ virtual IPixelAccess & pixelaccess() = 0;
1836+
1837+private:
1838+ // forbid copying
1839+ IPicture(const IPicture &);
1840+ IPicture & operator= (const IPicture &);
1841+
1842+public:
1843+ static const PictureID & null();
1844 };
1845
1846 #endif
1847
1848=== modified file 'src/graphic/picture_id.h'
1849--- src/graphic/picture_id.h 2009-11-22 14:46:22 +0000
1850+++ src/graphic/picture_id.h 2010-11-29 19:01:16 +0000
1851@@ -21,8 +21,8 @@
1852
1853 #include <boost/shared_ptr.hpp>
1854
1855-struct Picture;
1856+struct IPicture;
1857
1858-typedef boost::shared_ptr<Picture> PictureID;
1859+typedef boost::shared_ptr<IPicture> PictureID;
1860
1861 #endif
1862
1863=== added file 'src/graphic/pixelaccess.h'
1864--- src/graphic/pixelaccess.h 1970-01-01 00:00:00 +0000
1865+++ src/graphic/pixelaccess.h 2010-11-29 19:01:16 +0000
1866@@ -0,0 +1,110 @@
1867+/*
1868+ * Copyright 2010 by the Widelands Development Team
1869+ *
1870+ * This program is free software; you can redistribute it and/or
1871+ * modify it under the terms of the GNU General Public License
1872+ * as published by the Free Software Foundation; either version 2
1873+ * of the License, or (at your option) any later version.
1874+ *
1875+ * This program is distributed in the hope that it will be useful,
1876+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1877+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1878+ * GNU General Public License for more details.
1879+ *
1880+ * You should have received a copy of the GNU General Public License
1881+ * along with this program; if not, write to the Free Software
1882+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
1883+ *
1884+ */
1885+
1886+#ifndef PIXELACCESS_H
1887+#define PIXELACCESS_H
1888+
1889+#include <stdint.h>
1890+
1891+struct SDL_PixelFormat;
1892+
1893+/**
1894+ * Interface that provides direct pixel access to a picture or surface.
1895+ *
1896+ * \note Direct pixel access should be used only carefully, since it can be
1897+ * extremely slow.
1898+ */
1899+struct IPixelAccess {
1900+ enum LockMode {
1901+ /**
1902+ * Normal mode preserves pre-existing pixel data so that it can
1903+ * be read or modified.
1904+ */
1905+ Lock_Normal = 0,
1906+
1907+ /**
1908+ * Discard mode discards pre-existing pixel data. All pixels
1909+ * will be undefined unless they are re-written.
1910+ */
1911+ Lock_Discard
1912+ };
1913+
1914+ enum UnlockMode {
1915+ /**
1916+ * Update mode will ensure that any changes in the pixel data
1917+ * will appear in subsequent operations.
1918+ */
1919+ Unlock_Update = 0,
1920+
1921+ /**
1922+ * NoChange mode indicates that the caller changed no pixel data.
1923+ *
1924+ * \note If the caller did change pixel data but specifies NoChange
1925+ * mode, the results are undefined.
1926+ */
1927+ Unlock_NoChange
1928+ };
1929+
1930+ IPixelAccess() {}
1931+ virtual ~IPixelAccess() {}
1932+
1933+ /// Get width and height
1934+ //@{
1935+ virtual uint32_t get_w() = 0;
1936+ virtual uint32_t get_h() = 0;
1937+ //@}
1938+
1939+ /// This returns the pixel format for direct pixel access.
1940+ virtual SDL_PixelFormat const & format() const = 0;
1941+
1942+ /**
1943+ * Lock/Unlock pairs must guard any of the direct pixel access using the
1944+ * functions below.
1945+ *
1946+ * \note Lock/Unlock pairs cannot be nested.
1947+ */
1948+ //@{
1949+ virtual void lock(LockMode) = 0;
1950+ virtual void unlock(UnlockMode) = 0;
1951+ //@}
1952+
1953+ //@{
1954+ virtual uint32_t get_pixel(uint32_t x, uint32_t y) = 0;
1955+ virtual void set_pixel(uint32_t x, uint32_t y, uint32_t clr) = 0;
1956+ //@}
1957+
1958+ /**
1959+ * \return Pitch of the raw pixel data, i.e. the number of bytes
1960+ * contained in each image row. This can be strictly larger than
1961+ * bytes per pixel times the width.
1962+ */
1963+ virtual uint16_t get_pitch() const = 0;
1964+
1965+ /**
1966+ * \return Pointer to the raw pixel data.
1967+ *
1968+ * \warning May only be called inside lock/unlock pairs.
1969+ */
1970+ virtual uint8_t * get_pixels() const = 0;
1971+
1972+private:
1973+ IPixelAccess & operator= (const IPixelAccess &);
1974+};
1975+
1976+#endif // PIXELSURFACE_H
1977
1978=== modified file 'src/graphic/render/animationgfx.cc'
1979--- src/graphic/render/animationgfx.cc 2010-05-18 19:34:36 +0000
1980+++ src/graphic/render/animationgfx.cc 2010-11-29 19:01:16 +0000
1981@@ -22,8 +22,8 @@
1982 #include "io/streamwrite.h"
1983
1984 #include "surface_sdl.h"
1985-#include "surface_opengl.h"
1986 #include "graphic/graphic.h"
1987+#include "graphic/picture.h"
1988
1989 #include "log.h"
1990 #include "upcast.h"
1991@@ -99,17 +99,17 @@
1992 strcpy(after_basename, extensions[extnr]);
1993 if (g_fs->FileExists(filename)) { // Is the frame actually there?
1994 try {
1995- Surface & surface = g_gr->load_image(filename, true);
1996+ PictureID pic = g_gr->load_image(filename, true);
1997 if (width == 0) { // This is the first frame.
1998- width = surface.get_w();
1999- height = surface.get_h();
2000- } else if (width != surface.get_w() or height != surface.get_h())
2001+ width = pic->get_w();
2002+ height = pic->get_h();
2003+ } else if (width != pic->get_w() or height != pic->get_h())
2004 throw wexception
2005 ("wrong size: (%u, %u), should be (%u, %u) like the "
2006 "first frame",
2007- surface.get_w(), surface.get_h(), width, height);
2008+ pic->get_w(), pic->get_h(), width, height);
2009 // Get a new AnimFrame.
2010- m_plrframes[0].push_back(&surface);
2011+ m_plrframes[0].push_back(pic);
2012 #ifdef VALIDATE_ANIMATION_CROPPING
2013 if (not data_in_x_min)
2014 for (int y = 0; y < height; ++y) {
2015@@ -179,13 +179,13 @@
2016 strcpy(after_basename + 3, extensions[extnr]);
2017 if (g_fs->FileExists(filename)) {
2018 try {
2019- Surface & surface = g_gr->load_image(filename, true);
2020- if (width != surface.get_w() or height != surface.get_h())
2021+ PictureID picture = g_gr->load_image(filename, true);
2022+ if (width != picture->get_w() or height != picture->get_h())
2023 throw wexception
2024 ("playercolor mask has wrong size: (%u, %u), should "
2025 "be (%u, %u) like the animation frame",
2026- surface.get_w(), surface.get_h(), width, height);
2027- m_pcmasks.push_back(&surface);
2028+ picture->get_w(), picture->get_h(), width, height);
2029+ m_pcmasks.push_back(picture);
2030 break;
2031 } catch (std::exception const & e) {
2032 throw wexception
2033@@ -243,14 +243,6 @@
2034
2035 AnimationGfx::~AnimationGfx()
2036 {
2037- for (Widelands::Player_Number i = 0; i <= MAX_PLAYERS; ++i) {
2038- std::vector<Surface *> & frames = m_plrframes[i];
2039- for (uint32_t j = 0; j < frames.size(); ++j)
2040- delete frames[j];
2041- }
2042-
2043- for (uint32_t j = 0; j < m_pcmasks.size(); ++j)
2044- delete m_pcmasks[j];
2045 }
2046
2047
2048@@ -262,47 +254,36 @@
2049 void AnimationGfx::encode(uint8_t const plr, RGBColor const * const plrclrs)
2050 {
2051 assert(m_plrframes[0].size() == m_pcmasks.size());
2052- std::vector<Surface *> & frames = m_plrframes[plr];
2053+ std::vector<PictureID> & frames = m_plrframes[plr];
2054
2055 for (uint32_t i = 0; i < m_plrframes[0].size(); ++i) {
2056 // Copy the old surface.
2057- Surface & origsurface = *m_plrframes[0][i];
2058- Surface & newsurface = g_gr->create_surface(origsurface, true);
2059-
2060- Surface & pcmask = *m_pcmasks[i];
2061- SDL_PixelFormat * fmt, * fmt_pc;
2062-
2063-#ifdef USE_OPENGL
2064- upcast(SurfaceOpenGL, oglsurf, &origsurface);
2065-
2066- if (oglsurf)
2067- {
2068- fmt_pc = fmt = new SDL_PixelFormat;
2069- memset(fmt, 0, sizeof(SDL_PixelFormat));
2070- fmt->BitsPerPixel = 32; fmt->BytesPerPixel = 4;
2071- fmt->Amask = 0xFF000000; fmt->Ashift = 24;
2072- fmt->Bmask = 0x00FF0000; fmt->Bshift = 16;
2073- fmt->Gmask = 0x0000FF00; fmt->Gshift = 8;
2074- fmt->Rmask = 0x000000FF; fmt->Rshift = 0;
2075- } else
2076-#endif
2077- {
2078- fmt = const_cast<SDL_PixelFormat *>(&newsurface.format());
2079- fmt_pc = const_cast<SDL_PixelFormat *>(&pcmask.format());
2080- }
2081-
2082- origsurface.lock();
2083- pcmask.lock();
2084- newsurface.lock();
2085+ PictureID origpic = m_plrframes[0][i];
2086+ uint32_t w = origpic->get_w();
2087+ uint32_t h = origpic->get_h();
2088+ IPixelAccess & origpix = m_plrframes[0][i]->pixelaccess();
2089+ IPixelAccess & pcmask = m_pcmasks[i]->pixelaccess();
2090+
2091+ PictureID newpicture = g_gr->create_picture(w, h, true);
2092+ IPixelAccess & newpix = newpicture->pixelaccess();
2093+
2094+ const SDL_PixelFormat & fmt = origpix.format();
2095+ const SDL_PixelFormat & fmt_pc = pcmask.format();
2096+ const SDL_PixelFormat & destfmt = newpix.format();
2097+
2098+ origpix.lock(IPixelAccess::Lock_Normal);
2099+ pcmask.lock(IPixelAccess::Lock_Normal);
2100+ newpix.lock(IPixelAccess::Lock_Discard);
2101 // This could be done significantly faster, but since we
2102 // cache the result, let's keep it simple for now.
2103- for (uint32_t y = 0; y < newsurface.get_h(); ++y) {
2104- for (uint32_t x = 0; x < newsurface.get_w(); ++x) {
2105+ for (uint32_t y = 0; y < h; ++y) {
2106+ for (uint32_t x = 0; x < w; ++x) {
2107 RGBAColor source;
2108 RGBAColor mask;
2109+ RGBAColor product;
2110
2111- source.set(*fmt, newsurface.get_pixel(x, y));
2112- mask.set(*fmt_pc, pcmask.get_pixel(x, y));
2113+ source.set(fmt, origpix.get_pixel(x, y));
2114+ mask.set(fmt_pc, pcmask.get_pixel(x, y));
2115
2116 if
2117 (uint32_t const influence =
2118@@ -320,23 +301,25 @@
2119 plrclr.g = (plrclrs[3].g() * intensity) >> 8;
2120 plrclr.b = (plrclrs[3].b() * intensity) >> 8;
2121
2122- RGBAColor dest(source);
2123- dest.r =
2124- (plrclr.r * influence + dest.r * (65536 - influence)) >> 16;
2125- dest.g =
2126- (plrclr.g * influence + dest.g * (65536 - influence)) >> 16;
2127- dest.b =
2128- (plrclr.b * influence + dest.b * (65536 - influence)) >> 16;
2129-
2130- newsurface.set_pixel(x, y, dest.map(*fmt));
2131+ product.r =
2132+ (plrclr.r * influence + source.r * (65536 - influence)) >> 16;
2133+ product.g =
2134+ (plrclr.g * influence + source.g * (65536 - influence)) >> 16;
2135+ product.b =
2136+ (plrclr.b * influence + source.b * (65536 - influence)) >> 16;
2137+ product.a = source.a;
2138+ } else {
2139+ product = source;
2140 }
2141+
2142+ newpix.set_pixel(x, y, product.map(destfmt));
2143 }
2144 }
2145- origsurface.unlock();
2146- pcmask.unlock();
2147- newsurface.unlock();
2148+ origpix.unlock(IPixelAccess::Unlock_NoChange);
2149+ pcmask.unlock(IPixelAccess::Unlock_NoChange);
2150+ newpix.unlock(IPixelAccess::Unlock_Update);
2151
2152- frames.push_back(&newsurface);
2153+ frames.push_back(newpicture);
2154 }
2155 }
2156
2157
2158=== modified file 'src/graphic/render/gameview.cc'
2159--- src/graphic/render/gameview.cc 2010-11-02 00:07:12 +0000
2160+++ src/graphic/render/gameview.cc 2010-11-29 19:01:16 +0000
2161@@ -33,7 +33,6 @@
2162 #include "graphic/graphic.h"
2163 #include "graphic/rendertarget.h"
2164 #include "graphic/surface.h"
2165-#include "surface_opengl.h"
2166 #include "surface_sdl.h"
2167 #include "graphic/texture.h"
2168
2169@@ -973,13 +972,10 @@
2170 Texture const & f_d_texture,
2171 Texture const & f_r_texture)
2172 {
2173- upcast(SurfaceSDL, sdlsurf, m_surface);
2174-#ifdef USE_OPENGL
2175- upcast(SurfaceOpenGL, oglsurf, m_surface);
2176-#endif
2177+ upcast(SurfaceSDL, sdlsurf, m_surface.get());
2178 if (sdlsurf)
2179 {
2180- dynamic_cast<SurfaceSDL *>(m_surface)->set_subwin(subwin);
2181+ sdlsurf->set_subwin(subwin);
2182 switch (sdlsurf->format().BytesPerPixel) {
2183 case 2:
2184 draw_field_int<Uint16>
2185@@ -998,16 +994,17 @@
2186 default:
2187 assert(false);
2188 }
2189- dynamic_cast<SurfaceSDL *>(m_surface)->unset_subwin();
2190+ sdlsurf->unset_subwin();
2191 }
2192 #ifdef USE_OPENGL
2193- else if (oglsurf) {
2194+ else
2195+ {
2196 // Draw triangle right (bottom) of the field
2197 draw_field_opengl
2198- (*oglsurf, subwin, f_vert, br_vert, r_vert, f_r_texture);
2199+ (subwin, f_vert, br_vert, r_vert, f_r_texture);
2200 // Draw triangle bottom of the field
2201 draw_field_opengl
2202- (*oglsurf, subwin, f_vert, bl_vert, br_vert, f_d_texture);
2203+ (subwin, f_vert, bl_vert, br_vert, f_d_texture);
2204 // Draw the roads
2205 draw_roads_opengl(subwin, roads, f_vert, r_vert, bl_vert, br_vert);
2206 }
2207@@ -1273,7 +1270,7 @@
2208 // necesary. The created surface could be cached and only redrawn two
2209 // or three times per second
2210 const SDL_PixelFormat & fmt =
2211- g_gr->get_render_target()->get_surface().format();
2212+ g_gr->get_render_target()->get_surface()->pixelaccess().format();
2213 SDL_Surface * surface =
2214 SDL_CreateRGBSurface
2215 (SDL_SWSURFACE,
2216@@ -1312,11 +1309,9 @@
2217
2218 SDL_UnlockSurface(surface);
2219
2220- Surface & surf = g_gr->create_surface(*surface);
2221-
2222- m_surface->blit(Point(rc.x, rc.y), &surf, rc2, false);
2223-
2224- delete &surf;
2225+ PictureID picture = g_gr->convert_sdl_surface_to_picture(surface);
2226+
2227+ m_surface->blit(Point(rc.x, rc.y), picture, rc2);
2228 }
2229
2230 void GameView::rendermap_init()
2231
2232=== added file 'src/graphic/render/gl_picture_texture.cc'
2233--- src/graphic/render/gl_picture_texture.cc 1970-01-01 00:00:00 +0000
2234+++ src/graphic/render/gl_picture_texture.cc 2010-11-29 19:01:16 +0000
2235@@ -0,0 +1,235 @@
2236+/*
2237+ * Copyright 2010 by the Widelands Development Team
2238+ *
2239+ * This program is free software; you can redistribute it and/or
2240+ * modify it under the terms of the GNU General Public License
2241+ * as published by the Free Software Foundation; either version 2
2242+ * of the License, or (at your option) any later version.
2243+ *
2244+ * This program is distributed in the hope that it will be useful,
2245+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2246+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2247+ * GNU General Public License for more details.
2248+ *
2249+ * You should have received a copy of the GNU General Public License
2250+ * along with this program; if not, write to the Free Software
2251+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
2252+ */
2253+
2254+#include "gl_picture_texture.h"
2255+
2256+#include <SDL_video.h>
2257+
2258+#include "gl_utils.h"
2259+#include "graphic/graphic.h"
2260+#include "wexception.h"
2261+
2262+
2263+/**
2264+ * Initialize an OpenGL texture of the given dimensions.
2265+ *
2266+ * The initial data of the texture is undefined.
2267+ */
2268+GLPictureTexture::GLPictureTexture(int w, int h)
2269+{
2270+ init(w, h);
2271+}
2272+
2273+/**
2274+ * Initialize an OpenGL texture with the contents of the given surface.
2275+ *
2276+ * \note Takes ownership of the given surface.
2277+ */
2278+GLPictureTexture::GLPictureTexture(SDL_Surface * surface)
2279+{
2280+ init(surface->w, surface->h);
2281+
2282+ // Convert image data
2283+ uint8_t bpp = surface->format->BytesPerPixel;
2284+
2285+ if
2286+ (surface->format->palette or (surface->format->colorkey > 0) or
2287+ m_tex_w != static_cast<uint32_t>(surface->w) or
2288+ m_tex_h != static_cast<uint32_t>(surface->h) or
2289+ (bpp != 3 && bpp != 4))
2290+ {
2291+ SDL_Surface * converted = SDL_CreateRGBSurface
2292+ (SDL_SWSURFACE, m_tex_w, m_tex_h,
2293+ 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
2294+ assert(converted);
2295+ SDL_SetAlpha(converted, 0, 0);
2296+ SDL_SetAlpha(surface, 0, 0);
2297+ SDL_BlitSurface(surface, 0, converted, 0);
2298+ SDL_FreeSurface(surface);
2299+ surface = converted;
2300+ bpp = surface->format->BytesPerPixel;
2301+ }
2302+
2303+ SDL_PixelFormat const & fmt = *surface->format;
2304+ GLenum pixels_format;
2305+
2306+ glPushAttrib(GL_PIXEL_MODE_BIT);
2307+
2308+ if (bpp == 4) {
2309+ if
2310+ (fmt.Rmask == 0x000000ff and fmt.Gmask == 0x0000ff00 and
2311+ fmt.Bmask == 0x00ff0000)
2312+ {
2313+ if (fmt.Amask == 0xff000000) {
2314+ pixels_format = GL_RGBA;
2315+ } else {
2316+ pixels_format = GL_RGBA;
2317+ // Read four bytes per pixel but ignore the alpha value
2318+ glPixelTransferi(GL_ALPHA_SCALE, 0.0f);
2319+ glPixelTransferi(GL_ALPHA_BIAS, 1.0f);
2320+ }
2321+ } else if
2322+ (fmt.Bmask == 0x000000ff and fmt.Gmask == 0x0000ff00 and
2323+ fmt.Rmask == 0x00ff0000)
2324+ {
2325+ if (fmt.Amask == 0xff000000) {
2326+ pixels_format = GL_BGRA;
2327+ } else {
2328+ pixels_format = GL_BGRA;
2329+ // Read four bytes per pixel but ignore the alpha value
2330+ glPixelTransferi(GL_ALPHA_SCALE, 0.0f);
2331+ glPixelTransferi(GL_ALPHA_BIAS, 1.0f);
2332+ }
2333+ } else
2334+ throw wexception("OpenGL: Unknown pixel format");
2335+ } else if (bpp == 3) {
2336+ if
2337+ (fmt.Rmask == 0x000000ff and fmt.Gmask == 0x0000ff00 and
2338+ fmt.Bmask == 0x00ff0000)
2339+ {
2340+ pixels_format = GL_RGB;
2341+ } else if
2342+ (fmt.Bmask == 0x000000ff and fmt.Gmask == 0x0000ff00 and
2343+ fmt.Rmask == 0x00ff0000)
2344+ {
2345+ pixels_format = GL_BGR;
2346+ } else
2347+ throw wexception("OpenGL: Unknown pixel format");
2348+ } else
2349+ throw wexception("OpenGL: Unknown pixel format");
2350+
2351+ SDL_LockSurface(surface);
2352+
2353+ glTexImage2D
2354+ (GL_TEXTURE_2D, 0, GL_RGBA, m_tex_w, m_tex_h, 0,
2355+ pixels_format, GL_UNSIGNED_BYTE, surface->pixels);
2356+
2357+ SDL_UnlockSurface(surface);
2358+ SDL_FreeSurface(surface);
2359+
2360+ glPopAttrib();
2361+ handle_glerror();
2362+}
2363+
2364+GLPictureTexture::~GLPictureTexture()
2365+{
2366+ glDeleteTextures(1, &m_texture);
2367+}
2368+
2369+void GLPictureTexture::init(uint32_t w, uint32_t h)
2370+{
2371+ handle_glerror();
2372+
2373+ m_w = w;
2374+ m_h = h;
2375+
2376+ if (g_gr->caps().gl.tex_power_of_two) {
2377+ m_tex_w = next_power_of_two(w);
2378+ m_tex_h = next_power_of_two(h);
2379+ } else {
2380+ m_tex_w = w;
2381+ m_tex_h = h;
2382+ }
2383+
2384+ glGenTextures(1, &m_texture);
2385+ glBindTexture(GL_TEXTURE_2D, m_texture);
2386+
2387+ // set texture filter to use linear filtering. This looks nicer for resized
2388+ // texture. Most textures and images are not resized so the filtering
2389+ // makes no difference
2390+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2391+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2392+
2393+ handle_glerror();
2394+}
2395+
2396+bool GLPictureTexture::valid()
2397+{
2398+ return true;
2399+}
2400+
2401+uint32_t GLPictureTexture::get_w()
2402+{
2403+ return m_w;
2404+}
2405+
2406+uint32_t GLPictureTexture::get_h()
2407+{
2408+ return m_h;
2409+}
2410+
2411+const SDL_PixelFormat & GLPictureTexture::format() const
2412+{
2413+ return gl_rgba_format();
2414+}
2415+
2416+void GLPictureTexture::lock(LockMode mode)
2417+{
2418+ assert(!m_pixels);
2419+
2420+ m_pixels.reset(new uint8_t[m_tex_w * m_tex_h * 4]);
2421+
2422+ if (mode == Lock_Normal) {
2423+ glBindTexture(GL_TEXTURE_2D, m_texture);
2424+ glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_pixels.get());
2425+ }
2426+}
2427+
2428+void GLPictureTexture::unlock(UnlockMode mode)
2429+{
2430+ assert(m_pixels);
2431+
2432+ if (mode == Unlock_Update) {
2433+ glBindTexture(GL_TEXTURE_2D, m_texture);
2434+ glTexImage2D
2435+ (GL_TEXTURE_2D, 0, GL_RGBA, m_tex_w, m_tex_h, 0, GL_RGBA,
2436+ GL_UNSIGNED_BYTE, m_pixels.get());
2437+ }
2438+
2439+ m_pixels.reset(0);
2440+}
2441+
2442+uint16_t GLPictureTexture::get_pitch() const
2443+{
2444+ return 4 * m_tex_w;
2445+}
2446+
2447+uint8_t * GLPictureTexture::get_pixels() const
2448+{
2449+ return m_pixels.get();
2450+}
2451+
2452+uint32_t GLPictureTexture::get_pixel(uint32_t x, uint32_t y)
2453+{
2454+ assert(m_pixels);
2455+ assert(x < m_w);
2456+ assert(y < m_h);
2457+
2458+ uint8_t * data = &m_pixels[(y * m_tex_w + x) * 4];
2459+ return *(reinterpret_cast<uint32_t *>(data));
2460+}
2461+
2462+void GLPictureTexture::set_pixel(uint32_t x, uint32_t y, uint32_t clr)
2463+{
2464+ assert(m_pixels);
2465+ assert(x < m_w);
2466+ assert(y < m_h);
2467+
2468+ uint8_t * data = &m_pixels[(y * m_tex_w + x) * 4];
2469+ *(reinterpret_cast<uint32_t *>(data)) = clr;
2470+}
2471
2472=== added file 'src/graphic/render/gl_picture_texture.h'
2473--- src/graphic/render/gl_picture_texture.h 1970-01-01 00:00:00 +0000
2474+++ src/graphic/render/gl_picture_texture.h 2010-11-29 19:01:16 +0000
2475@@ -0,0 +1,75 @@
2476+/*
2477+ * Copyright 2010 by the Widelands Development Team
2478+ *
2479+ * This program is free software; you can redistribute it and/or
2480+ * modify it under the terms of the GNU General Public License
2481+ * as published by the Free Software Foundation; either version 2
2482+ * of the License, or (at your option) any later version.
2483+ *
2484+ * This program is distributed in the hope that it will be useful,
2485+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2486+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2487+ * GNU General Public License for more details.
2488+ *
2489+ * You should have received a copy of the GNU General Public License
2490+ * along with this program; if not, write to the Free Software
2491+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
2492+ */
2493+
2494+#ifndef GL_PICTURE_TEXTURE_H
2495+#define GL_PICTURE_TEXTURE_H
2496+
2497+#include <boost/scoped_array.hpp>
2498+
2499+#include <SDL_opengl.h>
2500+
2501+#include "graphic/picture.h"
2502+#include "graphic/pixelaccess.h"
2503+
2504+struct SDL_Surface;
2505+
2506+struct GLPictureTexture : IPicture, IPixelAccess {
2507+ GLPictureTexture(SDL_Surface * surface);
2508+ GLPictureTexture(int w, int h);
2509+ ~GLPictureTexture();
2510+
2511+ /// Interface implementation
2512+ //@{
2513+ virtual bool valid();
2514+
2515+ virtual uint32_t get_w();
2516+ virtual uint32_t get_h();
2517+
2518+ virtual const SDL_PixelFormat & format() const;
2519+ virtual void lock(LockMode);
2520+ virtual void unlock(UnlockMode);
2521+ virtual uint16_t get_pitch() const;
2522+ virtual uint8_t * get_pixels() const;
2523+ virtual void set_pixel(uint32_t x, uint32_t y, uint32_t clr);
2524+ virtual uint32_t get_pixel(uint32_t x, uint32_t y);
2525+
2526+ virtual IPixelAccess & pixelaccess() {return *this;}
2527+ //@}
2528+
2529+ GLuint get_gl_texture() const {return m_texture;}
2530+ uint32_t get_tex_w() const {return m_tex_w;}
2531+ uint32_t get_tex_h() const {return m_tex_h;}
2532+
2533+private:
2534+ void init(uint32_t w, uint32_t h);
2535+
2536+private:
2537+ GLuint m_texture;
2538+
2539+ /// Logical width and height of the surface
2540+ uint32_t m_w, m_h;
2541+
2542+ /// Keep the size of the opengl texture. This is necessary because some
2543+ /// systems support only a power of two for texture sizes.
2544+ uint32_t m_tex_w, m_tex_h;
2545+
2546+ /// Pixel data, while the texture is locked
2547+ boost::scoped_array<uint8_t> m_pixels;
2548+};
2549+
2550+#endif //GL_PICTURE_TEXTURE_H
2551
2552=== added file 'src/graphic/render/gl_surface_screen.cc'
2553--- src/graphic/render/gl_surface_screen.cc 1970-01-01 00:00:00 +0000
2554+++ src/graphic/render/gl_surface_screen.cc 2010-11-29 19:01:16 +0000
2555@@ -0,0 +1,286 @@
2556+/*
2557+ * Copyright 2010 by the Widelands Development Team
2558+ *
2559+ * This program is free software; you can redistribute it and/or
2560+ * modify it under the terms of the GNU General Public License
2561+ * as published by the Free Software Foundation; either version 2
2562+ * of the License, or (at your option) any later version.
2563+ *
2564+ * This program is distributed in the hope that it will be useful,
2565+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2566+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2567+ * GNU General Public License for more details.
2568+ *
2569+ * You should have received a copy of the GNU General Public License
2570+ * along with this program; if not, write to the Free Software
2571+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
2572+ */
2573+
2574+#include "gl_surface_screen.h"
2575+
2576+#include "gl_picture_texture.h"
2577+#include "gl_utils.h"
2578+#include "graphic/graphic.h"
2579+#include "upcast.h"
2580+
2581+GLSurfaceScreen::GLSurfaceScreen(uint32_t w, uint32_t h)
2582+{
2583+ m_w = w;
2584+ m_h = h;
2585+}
2586+
2587+bool GLSurfaceScreen::valid()
2588+{
2589+ return true;
2590+}
2591+
2592+uint32_t GLSurfaceScreen::get_w()
2593+{
2594+ return m_w;
2595+}
2596+
2597+uint32_t GLSurfaceScreen::get_h()
2598+{
2599+ return m_h;
2600+}
2601+
2602+void GLSurfaceScreen::update()
2603+{
2604+ assert(g_opengl);
2605+ SDL_GL_SwapBuffers();
2606+}
2607+
2608+const SDL_PixelFormat & GLSurfaceScreen::format() const
2609+{
2610+ return gl_rgba_format();
2611+}
2612+
2613+void GLSurfaceScreen::lock(IPixelAccess::LockMode mode)
2614+{
2615+ assert(!m_pixels);
2616+
2617+ m_pixels.reset(new uint8_t[m_w * m_h * 4]);
2618+
2619+ if (mode == Lock_Normal)
2620+ glReadPixels(0, 0, m_w, m_h, GL_RGBA, GL_UNSIGNED_BYTE, m_pixels.get());
2621+}
2622+
2623+void GLSurfaceScreen::unlock(IPixelAccess::UnlockMode mode)
2624+{
2625+ assert(m_pixels);
2626+
2627+ if (mode == Unlock_Update)
2628+ glDrawPixels(m_w, m_h, GL_RGBA, GL_UNSIGNED_BYTE, m_pixels.get());
2629+
2630+ m_pixels.reset(0);
2631+}
2632+
2633+uint16_t GLSurfaceScreen::get_pitch() const
2634+{
2635+ return 4 * m_w;
2636+}
2637+
2638+uint8_t * GLSurfaceScreen::get_pixels() const
2639+{
2640+ return m_pixels.get();
2641+}
2642+
2643+uint32_t GLSurfaceScreen::get_pixel(uint32_t x, uint32_t y)
2644+{
2645+ assert(m_pixels);
2646+ assert(x < m_w);
2647+ assert(y < m_h);
2648+
2649+ uint8_t * data = &m_pixels[4 * (y * m_w + x)];
2650+ return *(reinterpret_cast<uint32_t *>(data));
2651+}
2652+
2653+void GLSurfaceScreen::set_pixel(uint32_t x, uint32_t y, Uint32 clr)
2654+{
2655+ assert(m_pixels);
2656+ assert(x < m_w);
2657+ assert(y < m_h);
2658+
2659+ uint8_t * data = &m_pixels[4 * (y * m_w + x)];
2660+ *(reinterpret_cast<uint32_t *>(data)) = clr;
2661+}
2662+
2663+/**
2664+ * Draws the outline of a rectangle
2665+ */
2666+void GLSurfaceScreen::draw_rect(const Rect rc, const RGBColor clr)
2667+{
2668+ assert(g_opengl);
2669+ glDisable(GL_BLEND);
2670+ glDisable(GL_TEXTURE_2D);
2671+
2672+ glBegin(GL_LINE_LOOP); {
2673+ glColor3ub(clr.r(), clr.g(), clr.b());
2674+ glVertex2f(rc.x + 0.5f, rc.y + 0.5f);
2675+ glVertex2f(rc.x + rc.w - 0.5f, rc.y + 0.5f);
2676+ glVertex2f(rc.x + rc.w - 0.5f, rc.y + rc.h - 0.5f);
2677+ glVertex2f(rc.x + 0.5f, rc.y + rc.h - 0.5f);
2678+ } glEnd();
2679+ glEnable(GL_TEXTURE_2D);
2680+}
2681+
2682+
2683+/**
2684+ * Draws a filled rectangle
2685+ */
2686+void GLSurfaceScreen::fill_rect(const Rect rc, const RGBAColor clr) {
2687+ assert(rc.x >= 0);
2688+ assert(rc.y >= 0);
2689+ assert(rc.w >= 0);
2690+ assert(rc.h >= 0);
2691+ assert(g_opengl);
2692+
2693+ glDisable(GL_TEXTURE_2D);
2694+ glDisable(GL_BLEND);
2695+
2696+ glBegin(GL_QUADS); {
2697+ glColor4ub(clr.r, clr.g, clr.b, clr.a);
2698+ glVertex2f(rc.x, rc.y);
2699+ glVertex2f(rc.x + rc.w, rc.y);
2700+ glVertex2f(rc.x + rc.w, rc.y + rc.h);
2701+ glVertex2f(rc.x, rc.y + rc.h);
2702+ } glEnd();
2703+ glEnable(GL_TEXTURE_2D);
2704+}
2705+
2706+/**
2707+ * Change the brightness of the given rectangle
2708+ */
2709+void GLSurfaceScreen::brighten_rect(const Rect rc, const int32_t factor)
2710+{
2711+ if (!factor)
2712+ return;
2713+
2714+ assert(rc.x >= 0);
2715+ assert(rc.y >= 0);
2716+ assert(rc.w >= 1);
2717+ assert(rc.h >= 1);
2718+ assert(g_opengl);
2719+
2720+ /* glBlendFunc is a very nice feature of opengl. You can specify how the
2721+ * color is calculated.
2722+ *
2723+ * glBlendFunc(GL_ONE, GL_ONE) means the following:
2724+ * Rnew = Rdest + Rsrc
2725+ * Gnew = Gdest + Gsrc
2726+ * Bnew = Bdest + Bsrc
2727+ * Anew = Adest + Asrc
2728+ * where Xnew is the new calculated color for destination, Xdest is the old
2729+ * color of the destination and Xsrc is the color of the source.
2730+ */
2731+ glEnable(GL_BLEND);
2732+ glDisable(GL_TEXTURE_2D);
2733+ glBlendFunc(GL_ONE, GL_ONE);
2734+
2735+ // And now simply draw a rect with facor as the color
2736+ // (this is the source color) over the region
2737+ glBegin(GL_QUADS); {
2738+ glColor3f
2739+ ((static_cast<GLfloat>(factor) / 256.0f),
2740+ (static_cast<GLfloat>(factor) / 256.0f),
2741+ (static_cast<GLfloat>(factor) / 256.0f));
2742+ glVertex2f(rc.x, rc.y);
2743+ glVertex2f(rc.x + rc.w, rc.y);
2744+ glVertex2f(rc.x + rc.w, rc.y + rc.h);
2745+ glVertex2f(rc.x, rc.y + rc.h);
2746+ } glEnd();
2747+}
2748+
2749+void GLSurfaceScreen::draw_line
2750+ (int32_t x1,
2751+ int32_t y1,
2752+ int32_t x2,
2753+ int32_t y2,
2754+ RGBColor color,
2755+ const Rect * clip)
2756+{
2757+ if (clip) {
2758+ glPushAttrib(GL_ENABLE_BIT | GL_SCISSOR_BIT);
2759+ glScissor
2760+ (clip->x, g_gr->get_yres() - clip->y - clip->h, clip->w, clip->h);
2761+ glEnable(GL_SCISSOR_TEST);
2762+ }
2763+ glDisable(GL_BLEND);
2764+ glDisable(GL_TEXTURE_2D);
2765+ glBegin(GL_LINES); {
2766+ glColor3ub(color.r(), color.g(), color.b());
2767+ glVertex2f(x1 + 0.5f, y1 + 0.5f);
2768+ glVertex2f(x2 + 0.5f, y2 + 0.5f);
2769+ } glEnd();
2770+ if (clip) {
2771+ glPopAttrib();
2772+ }
2773+}
2774+
2775+/**
2776+ * Clear the entire screen to black
2777+ */
2778+void GLSurfaceScreen::clear()
2779+{
2780+ assert(g_opengl);
2781+ glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
2782+ glClear(GL_COLOR_BUFFER_BIT);
2783+}
2784+
2785+
2786+void GLSurfaceScreen::blit
2787+ (Point const dst, PictureID const src, Rect const srcrc, Composite cm)
2788+{
2789+ upcast(GLPictureTexture, oglsrc, src.get());
2790+ assert(oglsrc);
2791+ assert(g_opengl);
2792+
2793+ /* Set a texture scaling factor. Normaly texture coordiantes
2794+ * (see glBegin()...glEnd() Block below) are given in the range 0-1
2795+ * to avoid the calculation (and let opengl do it) the texture
2796+ * space is modified. glMatrixMode select which matrix to manipulate
2797+ * (the texture transformation matrix in this case). glLoadIdentity()
2798+ * resets the (selected) matrix to the identity matrix. And finally
2799+ * glScalef() calculates the texture matrix.
2800+ */
2801+ glMatrixMode(GL_TEXTURE);
2802+ glLoadIdentity();
2803+ glScalef
2804+ (1.0f / static_cast<GLfloat>(oglsrc->get_tex_w()),
2805+ 1.0f / static_cast<GLfloat>(oglsrc->get_tex_h()), 1);
2806+
2807+ // Enable Alpha blending
2808+ if (cm == CM_Normal) {
2809+ glEnable(GL_BLEND);
2810+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2811+ } else {
2812+ glDisable(GL_BLEND);
2813+ }
2814+
2815+ glEnable(GL_TEXTURE_2D);
2816+ glBindTexture(GL_TEXTURE_2D, oglsrc->get_gl_texture());
2817+
2818+ glBegin(GL_QUADS); {
2819+ // set color white, otherwise textures get mixed with color
2820+ glColor3f(1.0, 1.0, 1.0);
2821+ // top-left
2822+ glTexCoord2i(srcrc.x, srcrc.y);
2823+ glVertex2i (dst.x, dst.y);
2824+ // top-right
2825+ glTexCoord2i(srcrc.x + srcrc.w, srcrc.y);
2826+ glVertex2f (dst.x + srcrc.w, dst.y);
2827+ // bottom-right
2828+ glTexCoord2i(srcrc.x + srcrc.w, srcrc.y + srcrc.h);
2829+ glVertex2f (dst.x + srcrc.w, dst.y + srcrc.h);
2830+ // bottom-left
2831+ glTexCoord2i(srcrc.x, srcrc.y + srcrc.h);
2832+ glVertex2f (dst.x, dst.y + srcrc.h);
2833+ } glEnd();
2834+
2835+ glLoadIdentity();
2836+}
2837+
2838+void GLSurfaceScreen::fast_blit(PictureID src)
2839+{
2840+ blit(Point(0, 0), src, Rect(Point(0, 0), src->get_w(), src->get_h()), CM_Normal);
2841+}
2842
2843=== added file 'src/graphic/render/gl_surface_screen.h'
2844--- src/graphic/render/gl_surface_screen.h 1970-01-01 00:00:00 +0000
2845+++ src/graphic/render/gl_surface_screen.h 2010-11-29 19:01:16 +0000
2846@@ -0,0 +1,74 @@
2847+/*
2848+ * Copyright 2010 by the Widelands Development Team
2849+ *
2850+ * This program is free software; you can redistribute it and/or
2851+ * modify it under the terms of the GNU General Public License
2852+ * as published by the Free Software Foundation; either version 2
2853+ * of the License, or (at your option) any later version.
2854+ *
2855+ * This program is distributed in the hope that it will be useful,
2856+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2857+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2858+ * GNU General Public License for more details.
2859+ *
2860+ * You should have received a copy of the GNU General Public License
2861+ * along with this program; if not, write to the Free Software
2862+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
2863+ */
2864+
2865+#ifndef GL_SURFACE_SCREEN_H
2866+#define GL_SURFACE_SCREEN_H
2867+
2868+#include <boost/scoped_array.hpp>
2869+
2870+#include "graphic/picture_id.h"
2871+#include "graphic/pixelaccess.h"
2872+#include "graphic/surface.h"
2873+
2874+/**
2875+ * This surface represents the screen in OpenGL mode.
2876+ */
2877+struct GLSurfaceScreen : Surface, IPixelAccess {
2878+ GLSurfaceScreen(uint32_t w, uint32_t h);
2879+
2880+ /// Interface implementations
2881+ //@{
2882+ virtual bool valid();
2883+
2884+ virtual uint32_t get_w();
2885+ virtual uint32_t get_h();
2886+
2887+ virtual void update();
2888+
2889+ virtual const SDL_PixelFormat & format() const;
2890+ virtual void lock(LockMode);
2891+ virtual void unlock(UnlockMode);
2892+ virtual uint16_t get_pitch() const;
2893+ virtual uint8_t * get_pixels() const;
2894+ virtual void set_pixel(uint32_t x, uint32_t y, Uint32 clr);
2895+ virtual uint32_t get_pixel(uint32_t x, uint32_t y);
2896+ virtual IPixelAccess & pixelaccess() {return *this;}
2897+
2898+ virtual void clear();
2899+ virtual void draw_rect(Rect, RGBColor);
2900+ virtual void fill_rect(Rect, RGBAColor);
2901+ virtual void brighten_rect(Rect, int32_t factor);
2902+
2903+ virtual void draw_line
2904+ (int32_t x1, int32_t y1,
2905+ int32_t x2, int32_t y2,
2906+ RGBColor, Rect const * clip = 0);
2907+
2908+ virtual void blit(Point, PictureID, Rect srcrc, Composite cm);
2909+ virtual void fast_blit(PictureID);
2910+ //@}
2911+
2912+private:
2913+ /// Size of the screen
2914+ uint32_t m_w, m_h;
2915+
2916+ /// Pixel data while locked
2917+ boost::scoped_array<uint8_t> m_pixels;
2918+};
2919+
2920+#endif // GL_SURFACE_SCREEN_H
2921
2922=== added file 'src/graphic/render/gl_utils.cc'
2923--- src/graphic/render/gl_utils.cc 1970-01-01 00:00:00 +0000
2924+++ src/graphic/render/gl_utils.cc 2010-11-29 19:01:16 +0000
2925@@ -0,0 +1,100 @@
2926+/*
2927+ * Copyright 2010 by the Widelands Development Team
2928+ *
2929+ * This program is free software; you can redistribute it and/or
2930+ * modify it under the terms of the GNU General Public License
2931+ * as published by the Free Software Foundation; either version 2
2932+ * of the License, or (at your option) any later version.
2933+ *
2934+ * This program is distributed in the hope that it will be useful,
2935+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2936+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2937+ * GNU General Public License for more details.
2938+ *
2939+ * You should have received a copy of the GNU General Public License
2940+ * along with this program; if not, write to the Free Software
2941+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
2942+ */
2943+
2944+#include "gl_utils.h"
2945+
2946+#include <SDL_video.h>
2947+
2948+#include "log.h"
2949+
2950+/**
2951+ * Return the smallest power of two greater than or equal to \p x.
2952+ */
2953+uint32_t next_power_of_two(uint32_t x)
2954+{
2955+ uint32_t pot = 1;
2956+
2957+ while (pot < x)
2958+ pot *= 2;
2959+
2960+ return pot;
2961+}
2962+
2963+/**
2964+ * \return the standard 32-bit RGBA format that we use in OpenGL
2965+ */
2966+const SDL_PixelFormat & gl_rgba_format()
2967+{
2968+ static SDL_PixelFormat format;
2969+ static bool init = false;
2970+ if (init)
2971+ return format;
2972+
2973+ init = true;
2974+ memset(&format, 0, sizeof(format));
2975+ format.BitsPerPixel = 32;
2976+ format.BytesPerPixel = 4;
2977+ format.Rmask = 0x000000ff;
2978+ format.Gmask = 0x0000ff00;
2979+ format.Bmask = 0x00ff0000;
2980+ format.Amask = 0xff000000;
2981+ format.Rshift = 0;
2982+ format.Gshift = 8;
2983+ format.Bshift = 16;
2984+ format.Ashift = 24;
2985+ return format;
2986+}
2987+
2988+GLenum _handle_glerror(const char * file, unsigned int line)
2989+{
2990+ GLenum err = glGetError();
2991+#ifdef DEBUG
2992+ if (err == GL_NO_ERROR)
2993+ return err;
2994+
2995+ log("%s:%d: OpenGL ERROR: ", file, line);
2996+
2997+ switch (err)
2998+ {
2999+ case GL_INVALID_VALUE:
3000+ log("invalid value\n");
3001+ break;
3002+ case GL_INVALID_ENUM:
3003+ log("invalid enum\n");
3004+ break;
3005+ case GL_INVALID_OPERATION:
3006+ log("invalid operation\n");
3007+ break;
3008+ case GL_STACK_OVERFLOW:
3009+ log("stack overflow\n");
3010+ break;
3011+ case GL_STACK_UNDERFLOW:
3012+ log("stack undeflow\n");
3013+ break;
3014+ case GL_OUT_OF_MEMORY:
3015+ log("out of memory\n");
3016+ break;
3017+ case GL_TABLE_TOO_LARGE:
3018+ log("table too large\n");
3019+ break;
3020+ default:
3021+ log("unknown\n");
3022+ }
3023+#endif
3024+ return err;
3025+}
3026
3027=== added file 'src/graphic/render/gl_utils.h'
3028--- src/graphic/render/gl_utils.h 1970-01-01 00:00:00 +0000
3029+++ src/graphic/render/gl_utils.h 2010-11-29 19:01:16 +0000
3030@@ -0,0 +1,37 @@
3031+/*
3032+ * Copyright 2010 by the Widelands Development Team
3033+ *
3034+ * This program is free software; you can redistribute it and/or
3035+ * modify it under the terms of the GNU General Public License
3036+ * as published by the Free Software Foundation; either version 2
3037+ * of the License, or (at your option) any later version.
3038+ *
3039+ * This program is distributed in the hope that it will be useful,
3040+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3041+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3042+ * GNU General Public License for more details.
3043+ *
3044+ * You should have received a copy of the GNU General Public License
3045+ * along with this program; if not, write to the Free Software
3046+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
3047+ */
3048+
3049+#ifndef GL_UTILS_H
3050+#define GL_UTILS_H
3051+
3052+#include <stdint.h>
3053+#include <SDL_opengl.h>
3054+
3055+struct SDL_PixelFormat;
3056+
3057+uint32_t next_power_of_two(uint32_t x);
3058+const SDL_PixelFormat & gl_rgba_format();
3059+GLenum _handle_glerror(const char * file, unsigned int line);
3060+
3061+/**
3062+ * handle_glerror() is intended to make debugging of oengl easier. It logs the
3063+ * error code returned by glGetError and returns the error code.
3064+ */
3065+#define handle_glerror() _handle_glerror(__FILE__, __LINE__)
3066+
3067+#endif // GL_UTILS_H
3068
3069=== removed file 'src/graphic/render/render_opengl.cc'
3070--- src/graphic/render/render_opengl.cc 2010-11-01 22:37:46 +0000
3071+++ src/graphic/render/render_opengl.cc 1970-01-01 00:00:00 +0000
3072@@ -1,269 +0,0 @@
3073-/*
3074- * Copyright 2010 by the Widelands Development Team
3075- *
3076- * This program is free software; you can redistribute it and/or
3077- * modify it under the terms of the GNU General Public License
3078- * as published by the Free Software Foundation; either version 2
3079- * of the License, or (at your option) any later version.
3080- *
3081- * This program is distributed in the hope that it will be useful,
3082- * but WITHOUT ANY WARRANTY; without even the implied warranty of
3083- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3084- * GNU General Public License for more details.
3085- *
3086- * You should have received a copy of the GNU General Public License
3087- * along with this program; if not, write to the Free Software
3088- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
3089- */
3090-
3091-#include "graphic/graphic.h"
3092-#include "surface_opengl.h"
3093-
3094-#include "log.h"
3095-#include "upcast.h"
3096-#include "wexception.h"
3097-
3098-#include <SDL.h>
3099-
3100-
3101-#ifdef USE_OPENGL
3102-
3103-/*
3104- * Updating the whole Surface
3105- */
3106-void SurfaceOpenGL::update() {
3107- assert(g_opengl);
3108- SDL_GL_SwapBuffers();
3109-}
3110-
3111-/*
3112-===============
3113-Draws the outline of a rectangle
3114-===============
3115-*/
3116-void SurfaceOpenGL::draw_rect(const Rect rc, const RGBColor clr) {
3117- assert(g_opengl);
3118- //log("SurfaceOpenGL::draw_rect() for opengl is experimental\n");
3119- glDisable(GL_BLEND);
3120- glDisable(GL_TEXTURE_2D);
3121-
3122- glBegin(GL_LINE_LOOP); {
3123- glColor3ub(clr.r(), clr.g(), clr.b());
3124- glVertex2f(m_offsx + rc.x + 0.5f, m_offsy + rc.y + 0.5f);
3125- glVertex2f(m_offsx + rc.x + rc.w - 0.5f, m_offsy + rc.y + 0.5f);
3126- glVertex2f(m_offsx + rc.x + rc.w - 0.5f, m_offsy + rc.y + rc.h - 0.5f);
3127- glVertex2f(m_offsx + rc.x + 0.5f, m_offsy + rc.y + rc.h - 0.5f);
3128- } glEnd();
3129- glEnable(GL_TEXTURE_2D);
3130-}
3131-
3132-
3133-/*
3134-===============
3135-Draws a filled rectangle
3136-===============
3137-*/
3138-void SurfaceOpenGL::fill_rect(const Rect rc, const RGBAColor clr) {
3139- assert(rc.x >= 0);
3140- assert(rc.y >= 0);
3141- assert(rc.w >= 0);
3142- assert(rc.h >= 0);
3143- assert(g_opengl);
3144-
3145- glDisable(GL_TEXTURE_2D);
3146- glDisable(GL_BLEND);
3147-
3148- glBegin(GL_QUADS); {
3149- glColor4ub(clr.r, clr.g, clr.b, clr.a);
3150- glVertex2f(m_offsx + rc.x, m_offsy + rc.y);
3151- glVertex2f(m_offsx + rc.x + rc.w, m_offsy + rc.y);
3152- glVertex2f(m_offsx + rc.x + rc.w, m_offsy + rc.y + rc.h);
3153- glVertex2f(m_offsx + rc.x, m_offsy + rc.y + rc.h);
3154- } glEnd();
3155- glEnable(GL_TEXTURE_2D);
3156-}
3157-
3158-/*
3159-===============
3160-Change the brightness of the given rectangle
3161-This function is slow as hell.
3162-
3163-* This function is a possible point to optimize on
3164- slow system. It takes a lot of cpu time atm and is
3165- not needed. It is used by the ui_basic stuff to
3166- highlight things.
3167-===============
3168-*/
3169-void SurfaceOpenGL::brighten_rect(const Rect rc, const int32_t factor) {
3170- if (!factor)
3171- return;
3172-
3173- assert(rc.x >= 0);
3174- assert(rc.y >= 0);
3175- assert(rc.w >= 1);
3176- assert(rc.h >= 1);
3177- assert(g_opengl);
3178-
3179- /* glBlendFunc is a very nice feature of opengl. You can specify how the
3180- * color is calculated.
3181- *
3182- * glBlendFunc(GL_ONE, GL_ONE) means the following:
3183- * Rnew = Rdest + Rsrc
3184- * Gnew = Gdest + Gsrc
3185- * Bnew = Bdest + Bsrc
3186- * Anew = Adest + Asrc
3187- * where Xnew is the new calculated color for destination, Xdest is the old
3188- * color of the destination and Xsrc is the color of the source.
3189- */
3190- glEnable(GL_BLEND);
3191- glDisable(GL_TEXTURE_2D);
3192- glBlendFunc(GL_ONE, GL_ONE);
3193-
3194- // And now simply draw a rect with facor as the color
3195- // (this is the source color) over the region
3196- glBegin(GL_QUADS); {
3197- glColor3f
3198- ((static_cast<GLfloat>(factor) / 256.0f),
3199- (static_cast<GLfloat>(factor) / 256.0f),
3200- (static_cast<GLfloat>(factor) / 256.0f));
3201- glVertex2f(m_offsx + rc.x, m_offsy + rc.y);
3202- glVertex2f(m_offsx + rc.x + rc.w, m_offsy + rc.y);
3203- glVertex2f(m_offsx + rc.x + rc.w, m_offsy + rc.y + rc.h);
3204- glVertex2f(m_offsx + rc.x, m_offsy + rc.y + rc.h);
3205- } glEnd();
3206-}
3207-
3208-void SurfaceOpenGL::draw_line
3209- (int32_t x1,
3210- int32_t y1,
3211- int32_t x2,
3212- int32_t y2,
3213- RGBColor color,
3214- const Rect * clip)
3215-{
3216- if (clip) {
3217- glPushAttrib(GL_ENABLE_BIT | GL_SCISSOR_BIT);
3218- glScissor
3219- (clip->x, g_gr->get_yres() - clip->y - clip->h, clip->w, clip->h);
3220- glEnable(GL_SCISSOR_TEST);
3221- }
3222- glDisable(GL_BLEND);
3223- glDisable(GL_TEXTURE_2D);
3224- glBegin(GL_LINES); {
3225- glColor3ub(color.r(), color.g(), color.b());
3226- glVertex2f(x1 + m_offsx + 0.5f, y1 + m_offsy + 0.5f);
3227- glVertex2f(x2 + m_offsx + 0.5f, y2 + m_offsy + 0.5f);
3228- } glEnd();
3229- if (clip) {
3230- glPopAttrib();
3231- }
3232-}
3233-
3234-/*
3235-===============
3236-Clear the entire bitmap to black
3237-===============
3238-*/
3239-void SurfaceOpenGL::clear()
3240-{
3241- assert(g_opengl);
3242- glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
3243- glClear(GL_COLOR_BUFFER_BIT);
3244- return;
3245-}
3246-
3247-
3248-void SurfaceOpenGL::blit
3249- (Point const dst, Surface * const src, Rect const srcrc, bool enable_alpha)
3250-{
3251- blit(Rect(dst, srcrc.w, srcrc.h), src, srcrc, enable_alpha);
3252-}
3253-
3254-
3255-void SurfaceOpenGL::blit
3256- (Rect dst, Surface * src, Rect srcrc, bool enable_alpha)
3257-{
3258- upcast(SurfaceOpenGL, oglsrc, src);
3259-
3260- assert(g_opengl);
3261-#ifdef DEBUG
3262- if (m_surf_type != SURFACE_SCREEN)
3263- {
3264- throw wexception
3265- ("Surface not the screen: Offscreen rendering not possible");
3266- return;
3267- }
3268-
3269- if (not oglsrc)
3270- {
3271- throw wexception("Invalid surface: Not a opengl surface");
3272- }
3273-#endif
3274- GLuint tex;
3275-
3276- try {
3277- tex = oglsrc->get_texture();
3278- } catch (...) {
3279- throw wexception
3280- ("SurfaceOpenGL::blit(): Source surface has no texture\n");
3281- return;
3282- }
3283-
3284- /* Set a texture scaling factor. Normaly texture coordiantes
3285- * (see glBegin()...glEnd() Block below) are given in the range 0-1
3286- * to avoid the calculation (and let opengl do it) the texture
3287- * space is modified. glMatrixMode select which matrix to manipulate
3288- * (the texture transformation matrix in this case). glLoadIdentity()
3289- * resets the (selected) matrix to the identity matrix. And finally
3290- * glScalef() calculates the texture matrix.
3291- */
3292- glMatrixMode(GL_TEXTURE);
3293- glLoadIdentity();
3294- glScalef
3295- (1.0f / static_cast<GLfloat>(oglsrc->get_tex_w()),
3296- 1.0f / static_cast<GLfloat>(oglsrc->get_tex_h()), 1);
3297-
3298- // Enable Alpha blending
3299- if (enable_alpha) {
3300- glEnable(GL_BLEND);
3301- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3302- } else
3303- glDisable(GL_BLEND);
3304-
3305- /* select the texture to paint on the screen
3306- * openGL does not know anything about SDL_Surfaces
3307- * opengl uses textures to handle images
3308- * getTexture() returns the texture id of the Surface. It creates
3309- * the texture from the SDL_Surface if it doesn't exist
3310- */
3311- glEnable(GL_TEXTURE_2D);
3312- glBindTexture(GL_TEXTURE_2D, tex);
3313-
3314- /* This block between blBegin() and glEnd() does the blit.
3315- * It draws a textured rectangle. glTexCoord2i() set the Texture
3316- * Texture cooardinates. This is the source rectangle.
3317- * glVertex2f() sets the screen coordiantes which belong to the
3318- * previous texture coordinate. This is the destination rectangle
3319- */
3320-
3321- glBegin(GL_QUADS); {
3322- // set color white, otherwise textures get mixed with color
3323- glColor3f(1.0, 1.0, 1.0);
3324- // top-left
3325- glTexCoord2i(srcrc.x, srcrc.y);
3326- glVertex2i (m_offsx + dst.x, m_offsy + dst.y);
3327- // top-right
3328- glTexCoord2i(srcrc.x + srcrc.w, srcrc.y);
3329- glVertex2f (m_offsx + dst.x + dst.w, m_offsy + dst.y);
3330- // bottom-right
3331- glTexCoord2i(srcrc.x + srcrc.w, srcrc.y + srcrc.h);
3332- glVertex2f (m_offsx + dst.x + dst.w, m_offsy + dst.y + dst.h);
3333- // bottom-left
3334- glTexCoord2i(srcrc.x, srcrc.y + srcrc.h);
3335- glVertex2f (m_offsx + dst.x, m_offsy + dst.y + dst.h);
3336- } glEnd();
3337-
3338- glLoadIdentity();
3339-}
3340-
3341-#endif //USE_OPENGL
3342
3343=== modified file 'src/graphic/render/render_sdl.cc'
3344--- src/graphic/render/render_sdl.cc 2010-11-01 22:37:46 +0000
3345+++ src/graphic/render/render_sdl.cc 2010-11-29 19:01:16 +0000
3346@@ -49,7 +49,7 @@
3347 * Updating the whole Surface
3348 */
3349 void SurfaceSDL::update() {
3350- if (m_surf_type == SURFACE_SCREEN) {
3351+ if (m_isscreen) {
3352 //flip defaults to SDL_UpdateRect(m_surface, 0, 0, 0, 0);
3353 SDL_Flip(m_surface);
3354 //log("SurfaceSDL::update(): update complete screen\n");
3355@@ -128,7 +128,7 @@
3356
3357 const Point bl = rc.bottom_left();
3358
3359- lock();
3360+ lock(IPixelAccess::Lock_Normal);
3361
3362 if (m_surface->format->BytesPerPixel == 4)
3363 {
3364@@ -183,7 +183,7 @@
3365 SDL_MapRGB(m_surface->format, r, g, b);
3366 }
3367 }
3368- unlock();
3369+ unlock(IPixelAccess::Unlock_Update);
3370 }
3371
3372 #define draw_pixel(p, r, clr) \
3373@@ -257,24 +257,35 @@
3374
3375
3376 void SurfaceSDL::blit
3377- (Point const dst, Surface * const src, Rect const srcrc, bool enable_alpha)
3378+ (Point const dst, PictureID src, Rect const srcrc, Composite cm)
3379 {
3380- assert(src);
3381+ upcast(SurfaceSDL, sdlsurf, src.get());
3382+ assert(sdlsurf);
3383 assert(this);
3384 SDL_Rect srcrect = {srcrc.x, srcrc.y, srcrc.w, srcrc.h};
3385 SDL_Rect dstrect = {dst.x, dst.y, 0, 0};
3386
3387- SDL_BlitSurface
3388- (dynamic_cast<SurfaceSDL *>(src)->get_sdl_surface(),
3389- &srcrect, m_surface, &dstrect);
3390+ bool alpha;
3391+ uint8_t alphaval;
3392+ if (cm == CM_Solid || cm == CM_Copy) {
3393+ alpha = sdlsurf->get_sdl_surface()->flags & SDL_SRCALPHA;
3394+ alphaval = sdlsurf->get_sdl_surface()->format->alpha;
3395+ SDL_SetAlpha(sdlsurf->get_sdl_surface(), 0, 0);
3396+ }
3397+
3398+ SDL_BlitSurface(sdlsurf->get_sdl_surface(), &srcrect, m_surface, &dstrect);
3399+
3400+ if (cm == CM_Solid || cm == CM_Copy) {
3401+ SDL_SetAlpha(sdlsurf->get_sdl_surface(), alpha?SDL_SRCALPHA:0, alphaval);
3402+ }
3403 }
3404
3405
3406 /*
3407 * Fast blit, simply copy the source to the destination
3408 */
3409-void SurfaceSDL::fast_blit(Surface * const src) {
3410+void SurfaceSDL::fast_blit(PictureID const src) {
3411 SDL_BlitSurface
3412- (dynamic_cast<SurfaceSDL *>(src)->get_sdl_surface(),
3413+ (dynamic_cast<SurfaceSDL *>(src.get())->get_sdl_surface(),
3414 0, m_surface, 0);
3415 }
3416
3417=== removed file 'src/graphic/render/surface_opengl.cc'
3418--- src/graphic/render/surface_opengl.cc 2010-11-01 22:37:46 +0000
3419+++ src/graphic/render/surface_opengl.cc 1970-01-01 00:00:00 +0000
3420@@ -1,381 +0,0 @@
3421-/*
3422- * Copyright 2010 by the Widelands Development Team
3423- *
3424- * This program is free software; you can redistribute it and/or
3425- * modify it under the terms of the GNU General Public License
3426- * as published by the Free Software Foundation; either version 2
3427- * of the License, or (at your option) any later version.
3428- *
3429- * This program is distributed in the hope that it will be useful,
3430- * but WITHOUT ANY WARRANTY; without even the implied warranty of
3431- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3432- * GNU General Public License for more details.
3433- *
3434- * You should have received a copy of the GNU General Public License
3435- * along with this program; if not, write to the Free Software
3436- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
3437- */
3438-
3439-#include "surface_opengl.h"
3440-#include "log.h"
3441-#include "graphic/graphic.h"
3442-
3443-#include <cassert>
3444-#include <cmath>
3445-
3446-#ifdef USE_OPENGL
3447-
3448-long unsigned int pix_used = 0;
3449-long unsigned int pix_aloc = 0;
3450-long unsigned int num_tex = 0;
3451-
3452-#define handle_glerror() _handle_glerror(__FILE__, __LINE__)
3453-
3454-SDL_PixelFormat * rgbafmt = 0;
3455-
3456-/* handle_glerror() is intended to make debugging of oengl easier. It logs the
3457- * error code returned by glGetError and returns the error code.
3458- */
3459-GLenum _handle_glerror(const char * file, unsigned int line)
3460-{
3461- GLenum err = glGetError();
3462-#ifdef DEBUG
3463- if (err == GL_NO_ERROR)
3464- return err;
3465-
3466- log("%s:%d: OpenGL ERROR: ", file, line);
3467-
3468- switch (err)
3469- {
3470- case GL_INVALID_VALUE:
3471- log("invalid value\n");
3472- break;
3473- case GL_INVALID_ENUM:
3474- log("invalid enum\n");
3475- break;
3476- case GL_INVALID_OPERATION:
3477- log("invalid operation\n");
3478- break;
3479- case GL_STACK_OVERFLOW:
3480- log("stack overflow\n");
3481- break;
3482- case GL_STACK_UNDERFLOW:
3483- log("stack undeflow\n");
3484- break;
3485- case GL_OUT_OF_MEMORY:
3486- log("out of memory\n");
3487- break;
3488- case GL_TABLE_TOO_LARGE:
3489- log("table too large\n");
3490- break;
3491- default:
3492- log("unknown\n");
3493- }
3494-#endif
3495- return err;
3496-}
3497-
3498-SurfaceOpenGL::SurfaceOpenGL(SDL_Surface & par_surface):
3499- Surface(par_surface.w, par_surface.h, SURFACE_SOURCE),
3500- m_glTexUpdate(false),
3501- m_pixels (0),
3502- m_locked(false)
3503-{
3504- GLuint texture;
3505- SDL_Surface * surface;
3506- GLenum pixels_format, pixels_type;
3507- GLint Bpp;
3508-
3509- handle_glerror();
3510-
3511- surface = &par_surface;
3512-
3513- if (g_gr->caps().gl.tex_power_of_two)
3514- {
3515- int wexp = log(static_cast<float>(surface->w)) / log(2.0f);
3516- int hexp = log(static_cast<float>(surface->h)) / log(2.0f);
3517- if (pow(2.0f, wexp) < surface->w)
3518- wexp++;
3519- if (pow(2.0f, hexp) < surface->h)
3520- hexp++;
3521-
3522- m_tex_w = pow(2.0f, wexp);
3523- m_tex_h = pow(2.0f, hexp);
3524- } else {
3525- m_tex_w = surface->w;
3526- m_tex_h = surface->h;
3527- }
3528-
3529- if
3530- (surface->format->palette or (surface->format->colorkey > 0) or
3531- m_tex_w != static_cast<uint32_t>(surface->w) or
3532- m_tex_h != static_cast<uint32_t>(surface->h))
3533- {
3534- //log("SurfaceOpenGL: convert surface for opengl\n");
3535- surface = SDL_CreateRGBSurface
3536- (SDL_SWSURFACE, m_tex_w, m_tex_h,
3537- 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
3538- assert(surface);
3539- //SDL_DisplayFormatAlpha(&par_surface);
3540- SDL_SetAlpha(surface, 0, 0);
3541- SDL_SetAlpha(&par_surface, 0, 0);
3542- SDL_BlitSurface(&par_surface, 0, surface, 0);
3543- SDL_FreeSurface(&par_surface);
3544- }
3545-
3546- SDL_PixelFormat const & fmt = *surface->format;
3547- Bpp = fmt.BytesPerPixel;
3548-
3549- /* log
3550- ("SurfaceOpenGL::SurfaceOpenGL(SDL_Surface) Size: (%d, %d) %db(%dB) ",
3551- m_tex_w, m_tex_h,
3552- fmt.BitsPerPixel, Bpp);
3553- log("R:%X, G:%X, B:%X, A:%X", fmt.Rmask, fmt.Gmask, fmt.Bmask, fmt.Amask); */
3554-
3555- glPushAttrib(GL_PIXEL_MODE_BIT);
3556- bool pushed = not (handle_glerror() == GL_STACK_OVERFLOW);
3557-
3558- if (Bpp == 4)
3559- {
3560- if
3561- (fmt.Rmask == 0x000000ff and fmt.Gmask == 0x0000ff00 and
3562- fmt.Bmask == 0x00ff0000)
3563- {
3564- if (fmt.Amask == 0xff000000)
3565- {
3566- pixels_format = GL_RGBA; //log(" RGBA 8888 ");
3567- } else {
3568- pixels_format = GL_RGBA; //log(" RGB 8880 ");
3569- // Read four bytes per pixel but ignore the alpha value
3570- glPixelTransferi(GL_ALPHA_SCALE, 0.0f);
3571- glPixelTransferi(GL_ALPHA_BIAS, 1.0f);
3572- }
3573- } else if
3574- (fmt.Bmask == 0x000000ff and fmt.Gmask == 0x0000ff00 and
3575- fmt.Rmask == 0x00ff0000)
3576- {
3577- if (fmt.Amask == 0xff000000)
3578- {
3579- pixels_format = GL_BGRA; //log(" BGRA 8888 ");
3580- } else {
3581- pixels_format = GL_BGRA; //log(" BGR 8880 ");
3582- // Read four bytes per pixel but ignore the alpha value
3583- glPixelTransferi(GL_ALPHA_SCALE, 0.0f);
3584- glPixelTransferi(GL_ALPHA_BIAS, 1.0f);
3585- }
3586- } else
3587- throw wexception("OpenGL: Unknown pixel format");
3588- pixels_type = GL_UNSIGNED_BYTE;
3589- } else if (Bpp == 3)
3590- {
3591- if
3592- (fmt.Rmask == 0x000000ff and fmt.Gmask == 0x0000ff00 and
3593- fmt.Bmask == 0x00ff0000)
3594- {
3595- pixels_format = GL_RGB; //log(" RGB 888 ");
3596- } else if
3597- (fmt.Bmask == 0x000000ff and fmt.Gmask == 0x0000ff00 and
3598- fmt.Rmask == 0x00ff0000)
3599- {
3600- pixels_format = GL_BGR; //log(" BGR 888 ");
3601- } else
3602- throw wexception("OpenGL: Unknown pixel format");
3603- pixels_type = GL_UNSIGNED_BYTE;
3604- } else if (Bpp == 2)
3605- {
3606- if (fmt.Rmask == 0xF800 and fmt.Gmask == 0x7E0 and fmt.Bmask == 0x1F)
3607- {
3608- pixels_format = GL_RGB; //log(" RGB 565");
3609- } else if
3610- (fmt.Bmask == 0xF800 and fmt.Gmask == 0x7E0 and fmt.Rmask == 0x1F)
3611- {
3612- pixels_format = GL_BGR; //log(" BGR 565");
3613- } else
3614- assert(false);
3615- pixels_type = GL_UNSIGNED_SHORT_5_6_5;
3616- } else
3617- throw wexception("OpenGL: Unknown pixel format");
3618- //log("\n");
3619-
3620- // Let OpenGL create a texture object
3621- glGenTextures(1, &texture);
3622- handle_glerror();
3623-
3624- // select the texture object
3625- glBindTexture(GL_TEXTURE_2D, texture);
3626- handle_glerror();
3627-
3628- // set texture filter to use linear filtering. This looks nicer for resized
3629- // texture. Most textures and images are not resized so the filtering
3630- // makes no difference
3631- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
3632- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
3633- handle_glerror();
3634-
3635- SDL_LockSurface(surface);
3636-
3637- // glTexImage2D creates the texture of size (m_tex_w x m_tex_h) and copies
3638- // the pixels for surface->pixels to it.
3639- // The third parameter (internal format) specifies how opengl should store
3640- // the pixels. This has nothing to do with the read pixels
3641- // 7th and 8th parameter (format and type) specify the format of the read
3642- // pixels (9th parameter)
3643- glTexImage2D
3644- (GL_TEXTURE_2D, 0, WL_GLINTERNALFORMAT, m_tex_w, m_tex_h, 0,
3645- pixels_format, pixels_type, surface->pixels);
3646- handle_glerror();
3647-
3648- if (pushed)
3649- glPopAttrib();
3650-
3651- SDL_UnlockSurface(surface);
3652- SDL_FreeSurface(surface);
3653-
3654- pix_used += m_w * m_h;
3655- pix_aloc += m_tex_w * m_tex_h;
3656- num_tex++;
3657- /*
3658- log
3659- ("texture stats: num: %lu, used: %lu (%luM), "
3660- "alocated: %lu (%luM) ++\n",
3661- num_tex, pix_used * 4, pix_used * 4 / (1024 * 1024),
3662- pix_aloc * 4, pix_aloc * 4/ (1024 * 1024));
3663- */
3664- assert(glIsTexture(texture));
3665-
3666- m_texture = new oglTexture(texture);
3667- m_glTexUpdate = false;
3668-}
3669-
3670-
3671-SurfaceOpenGL::~SurfaceOpenGL() {
3672- if (m_texture) {
3673- pix_used -= m_w * m_h;
3674- pix_aloc -= m_tex_w * m_tex_h;
3675- num_tex--;
3676- delete m_texture;
3677- }
3678- /* log
3679- ("~SurfaceOpenGL(): texture stats: num: %lu, "
3680- "used: %lu (%luM), alocated: %lu (%luM) --\n",
3681- num_tex, pix_used * 4, pix_used * 4 / (1024 * 1024),
3682- pix_aloc * 4, pix_aloc * 4/ (1024 * 1024)); */
3683-
3684- delete[] m_pixels;
3685-}
3686-
3687-
3688-SurfaceOpenGL::SurfaceOpenGL(int const w, int const h):
3689- Surface(w, h, SURFACE_SOURCE),
3690- m_texture(0),
3691- m_glTexUpdate(false),
3692- m_pixels (0),
3693- m_locked(false)
3694-{
3695- if (g_gr and g_gr->caps().gl.tex_power_of_two) {
3696- // Some old graphics cards support only opengl textures which have a
3697- // size of 2^n. To get it working on these cards we take the next equal
3698- // or greater power of two. This is a waste of graphics memory and
3699- // causes some problem with borders of textures and repeated textures
3700- // but at least it works.
3701- int wexp = log(static_cast<float>(w)) / log(2.0f);
3702- int hexp = log(static_cast<float>(h)) / log(2.0f);
3703- if (pow(2.0f, wexp) < w)
3704- wexp++;
3705- if (pow(2.0f, hexp) < h)
3706- hexp++;
3707-
3708- m_tex_w = pow(2.0f, wexp);
3709- m_tex_h = pow(2.0f, hexp);
3710- } else {
3711- m_tex_w = w;
3712- m_tex_h = h;
3713- }
3714-}
3715-
3716-/* This returns a SDL_Pixel format for the returned pixels. lock() copies the
3717- * pixels always as 32Bit RGBA. So we create and return a RGBA SDL_PixelFormat
3718- */
3719-const SDL_PixelFormat * SurfaceOpenGL::get_format() const
3720-{
3721- if (rgbafmt)
3722- return rgbafmt;
3723- rgbafmt = new SDL_PixelFormat;
3724- rgbafmt->BitsPerPixel = 32;
3725- rgbafmt->BytesPerPixel = 4;
3726- rgbafmt->Rmask = 0x000000ff; rgbafmt->Gmask = 0x0000ff00;
3727- rgbafmt->Bmask = 0x00ff0000; rgbafmt->Amask = 0xff000000;
3728- rgbafmt->Ashift = 24; rgbafmt->Bshift = 16; rgbafmt->Gshift = 8;
3729- rgbafmt->Rshift = 0; rgbafmt->palette = 0;
3730- return rgbafmt;
3731-}
3732-
3733-/* lock the surface for pixel access. This allocates memory and copies the
3734- * pixles from opengl texture to it. This copies the whole texture even if
3735- * only one pixel is read. So use this as rare as possible.
3736- */
3737-void SurfaceOpenGL::lock() {
3738- if (m_locked)
3739- return;
3740- try {
3741- if (m_surf_type == SURFACE_SCREEN)
3742- m_pixels = new uint8_t[m_w * m_h * 4];
3743- else
3744- m_pixels = new uint8_t[m_tex_w * m_tex_h * 4];
3745- } catch (std::bad_alloc) {
3746- return;
3747- }
3748- if (m_surf_type == SURFACE_SCREEN)
3749- glReadPixels
3750- (0, 0, m_w, m_h, GL_RGBA, GL_UNSIGNED_BYTE, m_pixels);
3751- else if (m_texture) {
3752- assert(glIsTexture(m_texture->id()));
3753- glBindTexture(GL_TEXTURE_2D, m_texture->id());
3754- glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_pixels);
3755- m_glTexUpdate = false;
3756- } else
3757- m_glTexUpdate = true;
3758- //log("locked opengl surface(%d, %d)\n", m_tex_w, m_tex_h);
3759- m_locked = true;
3760-}
3761-
3762-/* Unlock the surface after pixel access. This loads the pixels to the texture
3763- * if pixels were changed and free the alocated memory.
3764- */
3765-void SurfaceOpenGL::unlock() {
3766- if (not m_locked)
3767- return;
3768- assert(m_pixels);
3769-
3770- if (m_glTexUpdate) {
3771- assert(m_surf_type != SURFACE_SCREEN);
3772- if (!m_texture)
3773- {
3774- GLuint texture;
3775- glGenTextures(1, &texture);
3776-
3777- // selcet the texture object
3778- glBindTexture(GL_TEXTURE_2D, texture);
3779-
3780- // set texture filter to siply take the nearest pixel.
3781- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3782- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3783-
3784- pix_used += m_w * m_h;
3785- pix_aloc += m_tex_w * m_tex_h;
3786- num_tex++;
3787-
3788- m_texture = new oglTexture(texture);
3789- }
3790- glBindTexture(GL_TEXTURE_2D, m_texture->id());;
3791- glTexImage2D
3792- (GL_TEXTURE_2D, 0, WL_GLINTERNALFORMAT, m_tex_w, m_tex_h, 0, GL_RGBA,
3793- GL_UNSIGNED_BYTE, m_pixels);
3794- }
3795-
3796- delete [] m_pixels;
3797- m_pixels = 0;
3798- m_locked = false;
3799-}
3800-
3801-#endif //USE_OPENGL
3802
3803=== removed file 'src/graphic/render/surface_opengl.h'
3804--- src/graphic/render/surface_opengl.h 2010-11-01 22:37:46 +0000
3805+++ src/graphic/render/surface_opengl.h 1970-01-01 00:00:00 +0000
3806@@ -1,170 +0,0 @@
3807-/*
3808- * Copyright 2010 by the Widelands Development Team
3809- *
3810- * This program is free software; you can redistribute it and/or
3811- * modify it under the terms of the GNU General Public License
3812- * as published by the Free Software Foundation; either version 2
3813- * of the License, or (at your option) any later version.
3814- *
3815- * This program is distributed in the hope that it will be useful,
3816- * but WITHOUT ANY WARRANTY; without even the implied warranty of
3817- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3818- * GNU General Public License for more details.
3819- *
3820- * You should have received a copy of the GNU General Public License
3821- * along with this program; if not, write to the Free Software
3822- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
3823- */
3824-
3825-#if !defined(SURFACE_OPENGL_H) and defined(USE_OPENGL)
3826-#define SURFACE_OPENGL_H
3827-
3828-#include "rgbcolor.h"
3829-#include "rect.h"
3830-#include "graphic/surface.h"
3831-
3832-#include <SDL_opengl.h>
3833-
3834-#include <cassert>
3835-
3836-#define WL_GLINTERNALFORMAT GL_RGBA
3837-
3838-namespace Widelands {
3839-struct Editor_Game_Base;
3840-struct Field;
3841-struct Player;
3842-}
3843-
3844-namespace UI {
3845-struct Font_Handler;
3846-}
3847-
3848-struct Vertex;
3849-
3850-/**
3851- * This implements OpenGL rendering. Do not use this class directly. The right
3852- * way is to use the base class Surface wherever possible. Everything which
3853- * needs to know about the underlying renderer should go to the graphics
3854- * subdirectory.
3855- * Surfaces are created through Graphic::create_surface() functions.
3856-*/
3857-class SurfaceOpenGL : public Surface {
3858-public:
3859- /**
3860- * Manages a single OpenGL texture. This makes sure the texture is
3861- * freed when the object is destroyed.
3862- */
3863- struct oglTexture {
3864- oglTexture() {}
3865- oglTexture(GLuint id): m_textureID(id) {}
3866- ~oglTexture() {glDeleteTextures(1, &m_textureID);}
3867- GLuint id() const {return m_textureID;}
3868- private:
3869- GLuint m_textureID;
3870- };
3871-
3872- SurfaceOpenGL(SDL_Surface & surface);
3873- explicit SurfaceOpenGL(int w = 0, int h = 0);
3874- ~SurfaceOpenGL();
3875-
3876- //@{
3877- /// Get width and height
3878- uint32_t get_w() const {return m_w;}
3879- uint32_t get_h() const {return m_h;}
3880- uint32_t get_tex_w() const {return m_tex_w;}
3881- uint32_t get_tex_h() const {return m_tex_h;}
3882- //@}
3883-
3884- void update();
3885-
3886- GLuint get_texture() const
3887- {
3888-#if defined(DEBUG)
3889- if (m_surf_type != SURFACE_SOURCE)
3890- throw wexception
3891- ("Try to get opengl texture id but not a source surface");
3892- if (not m_texture)
3893- throw wexception("no texture");
3894-#endif
3895- return m_texture->id();
3896- }
3897-
3898- const SDL_PixelFormat * get_format() const;
3899- SDL_PixelFormat const & format() const {return *get_format();}
3900-
3901- /// Directly access the pixels. This is only valid if the surface is locked
3902- inline uint16_t get_pitch() const {return m_tex_w * 4;}
3903- uint8_t * get_pixels() const
3904- {
3905- assert(m_locked);
3906- assert(m_pixels);
3907- return m_pixels;
3908- }
3909-
3910- /// Lock: The Surface need to be locked before get or set pixel
3911- void lock();
3912- void unlock();
3913-
3914- /// For the slowest: Indirect pixel access
3915- inline uint32_t get_pixel(uint32_t x, uint32_t y) {
3916- x += m_offsx;
3917- y += m_offsy;
3918-
3919- assert(x < get_w());
3920- assert(y < get_h());
3921- assert(m_locked);
3922-
3923- return *reinterpret_cast<uint32_t *>(m_pixels + y * get_pitch() + x * 4);
3924- }
3925- inline void set_pixel(uint32_t x, uint32_t y, Uint32 clr) {
3926- x += m_offsx;
3927- y += m_offsy;
3928-
3929- assert(x < get_w());
3930- assert(y < get_h());
3931- assert(m_locked);
3932- m_glTexUpdate = true;
3933-
3934- *reinterpret_cast<uint32_t *>(m_pixels + y * get_pitch() + x * 4) = clr;
3935- }
3936-
3937- void clear();
3938- void draw_rect(Rect, RGBColor);
3939- void fill_rect(Rect, RGBAColor);
3940- void brighten_rect(Rect, int32_t factor);
3941-
3942- void draw_line
3943- (int32_t x1, int32_t y1,
3944- int32_t x2, int32_t y2,
3945- RGBColor, Rect const * clip = 0);
3946-
3947- void blit(Point, Surface *, Rect srcrc, bool enable_alpha = true);
3948- void blit(Rect dst, Surface *, Rect srcrc, bool enable_alpha = true);
3949- //void fast_blit(Surface *);
3950-
3951- oglTexture & getTexture() {return *m_texture;}
3952-
3953-private:
3954- SurfaceOpenGL & operator= (SurfaceOpenGL const &);
3955- explicit SurfaceOpenGL (SurfaceOpenGL const &);
3956-
3957- /// stores the opengl texture id and frees if destroyed
3958- oglTexture * m_texture;
3959- /// Indicates that the texture needs to be updated after pixel access
3960- bool m_glTexUpdate;
3961-
3962- //@{
3963- /// set/unset a clipping rectangle
3964- void set_subwin(Rect r);
3965- void unset_subwin();
3966- //@}
3967-
3968- uint8_t * m_pixels;
3969- bool m_locked;
3970-
3971- /// Keep the size of the opengl texture. This is necessary because some
3972- /// systems support only a power of two for texture sizes.
3973- uint32_t m_tex_w, m_tex_h;
3974-};
3975-
3976-#endif
3977
3978=== modified file 'src/graphic/render/surface_sdl.cc'
3979--- src/graphic/render/surface_sdl.cc 2010-05-18 13:21:05 +0000
3980+++ src/graphic/render/surface_sdl.cc 2010-11-29 19:01:16 +0000
3981@@ -25,7 +25,7 @@
3982
3983 SurfaceSDL::~SurfaceSDL() {
3984 //log("SurfaceSDL::~SurfaceSDL()\n");
3985- if (m_surface and m_surf_type != SURFACE_SCREEN)
3986+ if (m_surface and !m_isscreen)
3987 SDL_FreeSurface(m_surface);
3988 }
3989
3990@@ -58,12 +58,12 @@
3991 m_offsx * m_surface->format->BytesPerPixel;
3992 }
3993
3994-void SurfaceSDL::lock() {
3995+void SurfaceSDL::lock(LockMode) {
3996 if (SDL_MUSTLOCK(m_surface))
3997 SDL_LockSurface(m_surface);
3998 }
3999
4000-void SurfaceSDL::unlock() {
4001+void SurfaceSDL::unlock(UnlockMode) {
4002 if (SDL_MUSTLOCK(m_surface))
4003 SDL_UnlockSurface(m_surface);
4004 }
4005@@ -147,3 +147,8 @@
4006 m_w = m_surface->w;
4007 m_h = m_surface->h;
4008 }
4009+
4010+void SurfaceSDL::set_isscreen(bool screen)
4011+{
4012+ m_isscreen = screen;
4013+}
4014
4015=== modified file 'src/graphic/render/surface_sdl.h'
4016--- src/graphic/render/surface_sdl.h 2010-11-01 22:37:46 +0000
4017+++ src/graphic/render/surface_sdl.h 2010-11-29 19:01:16 +0000
4018@@ -23,7 +23,7 @@
4019 #include "rgbcolor.h"
4020 #include "rect.h"
4021
4022-#include "graphic/surface.h"
4023+#include "graphic/offscreensurface.h"
4024
4025 /**
4026 * This implements SDL rendering. Do not use this class directly. The right
4027@@ -32,17 +32,24 @@
4028 * subdirectory.
4029 * Surfaces are created through Graphic::create_surface() functions.
4030 */
4031-struct SurfaceSDL : public Surface {
4032+struct SurfaceSDL : IOffscreenSurface {
4033 SurfaceSDL(SDL_Surface & surface) :
4034- Surface(surface.w, surface.h, SURFACE_OFFSCREEN),
4035- m_surface(&surface)
4036+ m_surface(&surface),
4037+ m_offsx(0), m_offsy(0),
4038+ m_w(surface.w), m_h(surface.h),
4039+ m_isscreen(false)
4040 {}
4041 SurfaceSDL():
4042- Surface(),
4043- m_surface(0)
4044+ m_surface(0),
4045+ m_offsx(0), m_offsy(0),
4046+ m_w(0), m_h(0),
4047+ m_isscreen(false)
4048 {}
4049 ~SurfaceSDL();
4050
4051+ virtual uint32_t get_w() {return m_w;}
4052+ virtual uint32_t get_h() {return m_h;}
4053+
4054 /// Set surface, only call once
4055 void set_sdl_surface(SDL_Surface & surface);
4056 SDL_Surface * get_sdl_surface() {return m_surface;}
4057@@ -53,21 +60,13 @@
4058 /// Save a bitmap of this to a file
4059 void save_bmp(const char & fname) const;
4060
4061-/*
4062- // For the bravest: Direct Pixel access. Use carefully
4063- /// Needed if you want to blit directly to the screen by memcpy
4064- void force_disable_alpha();
4065- const SDL_PixelFormat * get_format() const;
4066- uint16_t get_pitch() const {return m_surface->pitch;}
4067-*/
4068-
4069 SDL_PixelFormat const & format() const;
4070 uint8_t * get_pixels() const;
4071 uint16_t get_pitch() const {return m_surface->pitch;}
4072
4073 /// Lock
4074- void lock();
4075- void unlock();
4076+ void lock(LockMode);
4077+ void unlock(UnlockMode);
4078
4079 /// For the slowest: Indirect pixel access
4080 uint32_t get_pixel(uint32_t x, uint32_t y);
4081@@ -83,17 +82,27 @@
4082 int32_t x2, int32_t y2,
4083 RGBColor, Rect const * clip = 0);
4084
4085- void blit(Point, Surface *, Rect srcrc, bool enable_alpha = true);
4086- void fast_blit(Surface *);
4087+ void blit(Point, PictureID, Rect srcrc, Composite cm);
4088+ void fast_blit(PictureID);
4089
4090 void set_subwin(Rect r);
4091 void unset_subwin();
4092
4093+ void set_isscreen(bool screen);
4094+
4095+ bool valid() {return m_surface;}
4096+
4097+ virtual IPixelAccess & pixelaccess() {return *this;}
4098+
4099 private:
4100 SurfaceSDL & operator= (SurfaceSDL const &);
4101 explicit SurfaceSDL (SurfaceSDL const &);
4102
4103 SDL_Surface * m_surface;
4104+ int32_t m_offsx;
4105+ int32_t m_offsy;
4106+ uint32_t m_w, m_h;
4107+ bool m_isscreen;
4108 };
4109
4110 #endif
4111
4112=== modified file 'src/graphic/render/terrain_opengl.h'
4113--- src/graphic/render/terrain_opengl.h 2010-11-05 19:36:57 +0000
4114+++ src/graphic/render/terrain_opengl.h 2010-11-29 19:01:16 +0000
4115@@ -19,13 +19,12 @@
4116
4117 #ifdef USE_OPENGL
4118
4119-#include "surface_opengl.h"
4120+#include "gl_picture_texture.h"
4121 #include "vertex.h"
4122
4123
4124 void draw_field_opengl
4125- (Surface & surf,
4126- Rect const & subwin,
4127+ (Rect const & subwin,
4128 Vertex const & p1,
4129 Vertex const & p2,
4130 Vertex const & p3,
4131@@ -122,11 +121,11 @@
4132 uint8_t road;
4133
4134 GLuint rt_normal =
4135- dynamic_cast<SurfaceOpenGL const &>
4136- (*g_gr->get_road_texture(Widelands::Road_Normal)).get_texture();
4137+ dynamic_cast<GLPictureTexture const &>
4138+ (*g_gr->get_road_texture(Widelands::Road_Normal)).get_gl_texture();
4139 GLuint rt_busy =
4140- dynamic_cast<SurfaceOpenGL const &>
4141- (*g_gr->get_road_texture(Widelands::Road_Busy)).get_texture();
4142+ dynamic_cast<GLPictureTexture const &>
4143+ (*g_gr->get_road_texture(Widelands::Road_Busy)).get_gl_texture();
4144
4145 glDisable(GL_BLEND);
4146 glColor4f(1.0f, 1.0f, 1.0f, 0.6f);
4147
4148=== modified file 'src/graphic/render/terrain_sdl.h'
4149--- src/graphic/render/terrain_sdl.h 2010-11-05 19:36:57 +0000
4150+++ src/graphic/render/terrain_sdl.h 2010-11-29 19:01:16 +0000
4151@@ -23,6 +23,7 @@
4152 #include "constants.h"
4153 #include "log.h"
4154 #include "random.h"
4155+#include "upcast.h"
4156 #include "vertex.h"
4157
4158 #include "wui/mapviewpixelconstants.h"
4159@@ -532,7 +533,7 @@
4160 }
4161
4162 template<typename T> static void render_road_horiz
4163- (SurfaceSDL & dst, Point const start, Point const end, Surface const & src)
4164+ (SurfaceSDL & dst, Point const start, Point const end, SurfaceSDL const & src)
4165 {
4166 int32_t const dstw = dst.get_w();
4167 int32_t const dsth = dst.get_h();
4168@@ -559,7 +560,7 @@
4169 }
4170
4171 template<typename T> static void render_road_vert
4172- (SurfaceSDL & dst, Point const start, Point const end, Surface const & src)
4173+ (SurfaceSDL & dst, Point const start, Point const end, SurfaceSDL const & src)
4174 {
4175 int32_t const dstw = dst.get_w();
4176 int32_t const dsth = dst.get_h();
4177@@ -597,10 +598,10 @@
4178 Texture const & f_d_texture,
4179 Texture const & f_r_texture)
4180 {
4181- Surface const & rt_normal = *g_gr->get_road_texture(Widelands::Road_Normal);
4182- Surface const & rt_busy = *g_gr->get_road_texture(Widelands::Road_Busy);
4183+ upcast(SurfaceSDL, rt_normal, g_gr->get_road_texture(Widelands::Road_Normal).get());
4184+ upcast(SurfaceSDL, rt_busy, g_gr->get_road_texture(Widelands::Road_Busy).get());
4185
4186- dst.lock();
4187+ dst.lock(IPixelAccess::Lock_Normal);
4188
4189 render_triangle<T> (dst, f_vert, br_vert, r_vert, f_r_texture);
4190 render_triangle<T> (dst, f_vert, bl_vert, br_vert, f_d_texture);
4191@@ -613,10 +614,10 @@
4192 if (road) {
4193 switch (road) {
4194 case Widelands::Road_Normal:
4195- render_road_horiz<T> (dst, f_vert, r_vert, rt_normal);
4196+ render_road_horiz<T> (dst, f_vert, r_vert, *rt_normal);
4197 break;
4198 case Widelands::Road_Busy:
4199- render_road_horiz<T> (dst, f_vert, r_vert, rt_busy);
4200+ render_road_horiz<T> (dst, f_vert, r_vert, *rt_busy);
4201 break;
4202 default:
4203 assert(false);
4204@@ -631,10 +632,10 @@
4205 if (road) {
4206 switch (road) {
4207 case Widelands::Road_Normal:
4208- render_road_vert<T> (dst, f_vert, br_vert, rt_normal);
4209+ render_road_vert<T> (dst, f_vert, br_vert, *rt_normal);
4210 break;
4211 case Widelands::Road_Busy:
4212- render_road_vert<T> (dst, f_vert, br_vert, rt_busy);
4213+ render_road_vert<T> (dst, f_vert, br_vert, *rt_busy);
4214 break;
4215 default:
4216 assert(false);
4217@@ -649,10 +650,10 @@
4218 if (road) {
4219 switch (road) {
4220 case Widelands::Road_Normal:
4221- render_road_vert<T> (dst, f_vert, bl_vert, rt_normal);
4222+ render_road_vert<T> (dst, f_vert, bl_vert, *rt_normal);
4223 break;
4224 case Widelands::Road_Busy:
4225- render_road_vert<T> (dst, f_vert, bl_vert, rt_busy);
4226+ render_road_vert<T> (dst, f_vert, bl_vert, *rt_busy);
4227 break;
4228 default:
4229 assert(false);
4230@@ -662,7 +663,7 @@
4231 }
4232 }
4233
4234- dst.unlock();
4235+ dst.unlock(IPixelAccess::Unlock_Update);
4236
4237 // FIXME: similar textures may not need dithering
4238 }
4239
4240=== modified file 'src/graphic/rendertarget.cc'
4241--- src/graphic/rendertarget.cc 2010-06-14 19:31:37 +0000
4242+++ src/graphic/rendertarget.cc 2010-11-29 19:01:16 +0000
4243@@ -27,9 +27,7 @@
4244 #include "logic/tribe.h"
4245 #include "vertex.h"
4246
4247-#include "surface.h"
4248-#include "graphic/render/surface_opengl.h"
4249-#include "graphic/render/surface_sdl.h"
4250+#include "offscreensurface.h"
4251
4252 #include "log.h"
4253 #include "upcast.h"
4254@@ -43,16 +41,23 @@
4255 using Widelands::TCoords;
4256
4257 /**
4258- * Build a render target for the given bitmap.
4259- * \note The bitmap will not be owned by the renderer, i.e. it won't be
4260- * deleted by the destructor.
4261+ * Build a render target for the given surface.
4262 */
4263-RenderTarget::RenderTarget(Surface * const bmp)
4264+RenderTarget::RenderTarget(SurfacePtr bmp)
4265 {
4266 m_surface = bmp;
4267 reset();
4268 }
4269
4270+/**
4271+ * Build a render target for the given surface.
4272+ */
4273+RenderTarget::RenderTarget(OffscreenSurfacePtr surf)
4274+{
4275+ m_surface = surf;
4276+ reset();
4277+}
4278+
4279
4280 /**
4281 * Sets an arbitrary drawing window.
4282@@ -178,108 +183,33 @@
4283 }
4284
4285 /**
4286- * Blits a Surface on the screen or (if possible) on another Surface
4287- * Check g_gr->caps().offscreen_rendering to see if it is possible to blit
4288- * to a non screen surface.
4289- *
4290- * This blit function copies the pixels to the destination surface.
4291- * I the source surface contains a alpha channel this is used during
4292- * the blit.
4293- */
4294-void RenderTarget::blit(const Point dst, const PictureID picture)
4295-{
4296- if (Surface * const src = g_gr->get_picture_surface(picture))
4297- doblit
4298- (Rect(dst, 0, 0),
4299- src, Rect(Point(0, 0), src->get_w(), src->get_h()));
4300-}
4301-
4302-/**
4303- * Blits a Surface on the screen or (if possible) on another Surface
4304- * Check g_gr->caps().offscreen_rendering to see if it is possible to blit
4305- * to a non screen surface.
4306- *
4307- * This blit function copies the pixels to the destination surface.
4308- * I the source surface contains a alpha channel this is used during
4309- * the blit.
4310- */
4311-void RenderTarget::blit(const Rect dst, const PictureID picture)
4312-{
4313- if (Surface * const src = g_gr->get_picture_surface(picture))
4314- doblit(dst, src, Rect(Point(0, 0), src->get_w(), src->get_h()));
4315-}
4316-
4317-/**
4318- * Blits a Surface on the screen or (if possible) on another Surface
4319- * Check g_gr->caps().offscreen_rendering to see if it is possible to blit
4320- * to a non screen surface.
4321- *
4322- * This blit function copies the pixels values without alpha channel to the
4323- * destination surface.
4324- */
4325-void RenderTarget::blit_solid(const Point dst, const PictureID picture)
4326-{
4327- Surface * const src = g_gr->get_picture_surface(picture);
4328- if (not src)
4329- return;
4330-
4331- upcast(SurfaceSDL, sdlsurf, src);
4332- upcast(SurfaceOpenGL, oglsurf, src);
4333-
4334- if (sdlsurf) {
4335- bool alpha;
4336- uint8_t alphaval;
4337- alpha = sdlsurf->get_sdl_surface()->flags & SDL_SRCALPHA;
4338- alphaval = sdlsurf->get_sdl_surface()->format->alpha;
4339- SDL_SetAlpha(sdlsurf->get_sdl_surface(), 0, 0);
4340- doblit
4341- (Rect(dst, 0, 0),
4342- src, Rect(Point(0, 0), src->get_w(), src->get_h()), false);
4343- SDL_SetAlpha(sdlsurf->get_sdl_surface(), alpha?SDL_SRCALPHA:0, alphaval);
4344- } else if (oglsurf) {
4345- doblit
4346- (Rect(dst, 0, 0),
4347- src, Rect(Point(0, 0), src->get_w(), src->get_h()), false);
4348- }
4349-}
4350-
4351-/**
4352- * Blits a Surface on the screen or (if possible) on another Surface
4353- * Check g_gr->caps().offscreen_rendering to see if it is possible to blit
4354- * to a non screen surface.
4355- *
4356- * This blit function copies the pixels (including alpha channel)
4357- * to the destination surface.
4358- * The destination pixels will be exactly like the source pixels.
4359- */
4360-void RenderTarget::blit_copy(Point dst, PictureID picture)
4361-{
4362- Surface * const src = g_gr->get_picture_surface(picture);
4363- upcast(SurfaceSDL, sdlsurf, src);
4364- bool alpha;
4365- uint8_t alphaval;
4366- if (sdlsurf) {
4367- alpha = sdlsurf->get_sdl_surface()->flags & SDL_SRCALPHA;
4368- alphaval = sdlsurf->get_sdl_surface()->format->alpha;
4369- SDL_SetAlpha(sdlsurf->get_sdl_surface(), 0, 0);
4370- }
4371- if (src)
4372- doblit
4373- (Rect(dst, 0, 0),
4374- src, Rect(Point(0, 0), src->get_w(), src->get_h()), false);
4375- if (sdlsurf) {
4376- SDL_SetAlpha(sdlsurf->get_sdl_surface(), alpha?SDL_SRCALPHA:0, alphaval);
4377- }
4378-}
4379-
4380+ * Blits a Picture on the screen or (if possible) on another Surface
4381+ * Check g_gr->caps().offscreen_rendering to see if it is possible to blit
4382+ * to a non screen surface.
4383+ *
4384+ * This blit function copies the pixels to the destination surface.
4385+ * I the source surface contains a alpha channel this is used during
4386+ * the blit.
4387+ */
4388+void RenderTarget::blit(const Point dst, const PictureID picture, Composite cm)
4389+{
4390+ if (picture->valid())
4391+ doblit
4392+ (Rect(dst, 0, 0),
4393+ picture, Rect(Point(0, 0), picture->get_w(), picture->get_h()), cm);
4394+}
4395+
4396+/**
4397+ * Like \ref blit, but use only a sub-rectangle of the source picture.
4398+ */
4399 void RenderTarget::blitrect
4400- (Point const dst, PictureID const picture, Rect const srcrc)
4401+ (Point const dst, PictureID const picture, Rect const srcrc, Composite cm)
4402 {
4403 assert(0 <= srcrc.x);
4404 assert(0 <= srcrc.y);
4405
4406- if (Surface * const src = g_gr->get_picture_surface(picture))
4407- doblit(Rect(dst, 0, 0), src, srcrc);
4408+ if (picture->valid())
4409+ doblit(Rect(dst, 0, 0), picture, srcrc, cm);
4410 }
4411
4412 /**
4413@@ -288,24 +218,25 @@
4414 * The pixel from ofs inside picture is placed at the top-left corner of
4415 * the filled rectangle.
4416 */
4417-void RenderTarget::tile(Rect r, PictureID const picture, Point ofs)
4418+void RenderTarget::tile(Rect r, PictureID const picture, Point ofs, Composite cm)
4419 {
4420- Surface * const src = g_gr->get_picture_surface(picture);
4421-
4422- if (!src)
4423+ if (!picture->valid())
4424 return;
4425
4426+ int32_t srcw = picture->get_w();
4427+ int32_t srch = picture->get_h();
4428+
4429 if (clip(r)) {
4430 // Make sure the offset is within bounds
4431- ofs.x = ofs.x % src->get_w();
4432+ ofs.x = ofs.x % srcw;
4433
4434 if (ofs.x < 0)
4435- ofs.x += src->get_w();
4436+ ofs.x += srcw;
4437
4438- ofs.y = ofs.y % src->get_h();
4439+ ofs.y = ofs.y % srch;
4440
4441 if (ofs.y < 0)
4442- ofs.y += src->get_h();
4443+ ofs.y += srch;
4444
4445 // Blit the picture into the rectangle
4446 uint32_t ty = 0;
4447@@ -316,19 +247,19 @@
4448 Rect srcrc;
4449
4450 srcrc.y = ofs.y;
4451- srcrc.h = src->get_h() - ofs.y;
4452+ srcrc.h = srch - ofs.y;
4453
4454 if (ty + srcrc.h > r.h)
4455 srcrc.h = r.h - ty;
4456
4457 while (tx < r.w) {
4458 srcrc.x = tofsx;
4459- srcrc.w = src->get_w() - tofsx;
4460+ srcrc.w = srcw - tofsx;
4461
4462 if (tx + srcrc.w > r.w)
4463 srcrc.w = r.w - tx;
4464
4465- m_surface->blit(r + Point(tx, ty), src, srcrc);
4466+ m_surface->blit(r + Point(tx, ty), picture, srcrc, cm);
4467
4468 tx += srcrc.w;
4469
4470@@ -372,7 +303,7 @@
4471
4472 // Get the frame and its data
4473 uint32_t const framenumber = time / data->frametime % gfx->nr_frames();
4474- Surface * const frame =
4475+ const PictureID & frame =
4476 player ?
4477 gfx->get_frame
4478 (framenumber, player->player_number(), player->get_playercolor())
4479@@ -411,7 +342,7 @@
4480
4481 // Get the frame and its data
4482 uint32_t const framenumber = time / data->frametime % gfx->nr_frames();
4483- Surface * const frame =
4484+ const PictureID & frame =
4485 player ?
4486 gfx->get_frame
4487 (framenumber, player->player_number(), player->get_playercolor())
4488@@ -486,14 +417,13 @@
4489 * Clip against window and source bitmap, then call the Bitmap blit routine.
4490 */
4491 void RenderTarget::doblit
4492- (Rect dst, Surface * const src, Rect srcrc, bool enable_alpha)
4493+ (Point dst, PictureID src, Rect srcrc, Composite cm)
4494 {
4495 assert(0 <= srcrc.x);
4496 assert(0 <= srcrc.y);
4497 dst += m_offset;
4498
4499 // Clipping
4500-
4501 if (dst.x < 0) {
4502 if (srcrc.w <= static_cast<uint32_t>(-dst.x))
4503 return;
4504@@ -527,10 +457,5 @@
4505
4506 dst += m_rect;
4507
4508- // Draw it
4509- upcast(SurfaceOpenGL, oglsurf, m_surface);
4510- if (oglsurf and dst.w and dst.h)
4511- oglsurf->blit(dst, src, srcrc, enable_alpha);
4512- else
4513- m_surface->blit(Point(dst.x, dst.y), src, srcrc, enable_alpha);
4514+ m_surface->blit(dst, src, srcrc, cm);
4515 }
4516
4517=== modified file 'src/graphic/rendertarget.h'
4518--- src/graphic/rendertarget.h 2010-11-10 20:05:21 +0000
4519+++ src/graphic/rendertarget.h 2010-11-29 19:01:16 +0000
4520@@ -20,7 +20,9 @@
4521 #ifndef RENDERTARGET_H
4522 #define RENDERTARGET_H
4523
4524+#include "compositemode.h"
4525 #include "picture_id.h"
4526+#include "surfaceptr.h"
4527 #include "rect.h"
4528 #include "rgbcolor.h"
4529
4530@@ -29,7 +31,6 @@
4531 namespace Widelands {
4532 struct Player;
4533 };
4534-struct Surface;
4535
4536 /**
4537 * This abstract class represents anything that can be rendered to.
4538@@ -47,7 +48,8 @@
4539 * false and doesn't change the window state at all.
4540 */
4541 struct RenderTarget {
4542- RenderTarget(Surface *);
4543+ RenderTarget(SurfacePtr);
4544+ RenderTarget(OffscreenSurfacePtr);
4545 RenderTarget(RenderTarget & rt):
4546 m_surface(rt.m_surface),
4547 m_rect(rt.m_rect),
4548@@ -70,12 +72,9 @@
4549 void brighten_rect(Rect, int32_t factor);
4550 void clear();
4551
4552- void blit(Point dst, PictureID picture);
4553- void blit(Rect dst, PictureID picture);
4554- void blit_solid(Point dst, PictureID picture);
4555- void blit_copy(Point dst, PictureID picture);
4556- void blitrect(Point dst, PictureID picture, Rect src);
4557- void tile(Rect, PictureID picture, Point ofs);
4558+ void blit(Point dst, PictureID picture, Composite cm = CM_Normal);
4559+ void blitrect(Point dst, PictureID picture, Rect src, Composite cm = CM_Normal);
4560+ void tile(Rect, PictureID picture, Point ofs, Composite cm = CM_Normal);
4561
4562 void drawanim
4563 (Point dst,
4564@@ -92,15 +91,15 @@
4565
4566 void reset();
4567
4568- Surface & get_surface() {return *m_surface;}
4569+ SurfacePtr get_surface() {return m_surface;}
4570
4571 protected:
4572 bool clip(Rect & r) const throw ();
4573
4574- void doblit(Rect dst, Surface * src, Rect srcrc, bool enable_alpha = true);
4575+ void doblit(Point dst, PictureID src, Rect srcrc, Composite cm = CM_Normal);
4576
4577 ///The target surface
4578- Surface * m_surface;
4579+ SurfacePtr m_surface;
4580 ///The current clip rectangle
4581 Rect m_rect;
4582 ///Drawing offset
4583
4584=== modified file 'src/graphic/surface.h'
4585--- src/graphic/surface.h 2010-11-01 22:37:46 +0000
4586+++ src/graphic/surface.h 2010-11-29 19:01:16 +0000
4587@@ -20,80 +20,28 @@
4588 #ifndef SURFACE_H
4589 #define SURFACE_H
4590
4591+#include "compositemode.h"
4592 #include "rgbcolor.h"
4593 #include "rect.h"
4594+#include "surfaceptr.h"
4595 #include "wexception.h"
4596
4597 /**
4598- * The type of a surface. This make it possible to check a bit before drawing.
4599+ * Interface to a basic surfaces that can be used as destination for drawing.
4600 */
4601-enum SurfaceType {
4602- SURFACE_INVALID,
4603- SURFACE_SOURCE, ///< This sourface is used as source only
4604- SURFACE_OFFSCREEN, ///< Use surface as source and destinantion
4605- SURFACE_SCREEN ///< This draws to screen directly
4606-};
4607-
4608-/// A virtual base for rendering. Objects of Surface are used as Source or
4609-/// destination for drawing. Surfaces are created with the
4610-/// Graphic::create_surface() functions.
4611 struct Surface {
4612+ Surface() {}
4613 virtual ~Surface() {}
4614
4615 //@{
4616 /// Get width and height
4617- virtual uint32_t get_w() const {return m_w;}
4618- virtual uint32_t get_h() const {return m_h;}
4619+ virtual uint32_t get_w() = 0;
4620+ virtual uint32_t get_h() = 0;
4621 //@}
4622
4623 /// Update the screen. This is only useful for the screen surface.
4624 virtual void update() = 0;
4625
4626- //@{
4627- /// For the slowest: Indirect pixel access.
4628- /// A safe function to get and set single pixels. lock() must be called
4629- /// before pixel access can be used. get_pixel() and set_pixel() are easier
4630- /// and safer to use but also much slower than direct pixel access.
4631- virtual uint32_t get_pixel(uint32_t x, uint32_t y) {
4632- // FIXME make abstract or move body out of declaration
4633- throw wexception("get_pixel() not implemented");
4634- }
4635- virtual void set_pixel(uint32_t x, uint32_t y, Uint32 clr) {
4636- // FIXME make abstract or move body out of declaration
4637- throw wexception("set_pixel() not implemented");
4638- }
4639- //@}
4640-
4641- //@{
4642- /**
4643- * Locking and unlocking the surface for pixel access. This may be slow. So
4644- * use it with care.
4645- */
4646-
4647- virtual void lock() {};
4648- virtual void unlock() {};
4649- //@}
4650-
4651- /// This returns the pixel format for direct pixel access.
4652- virtual SDL_PixelFormat const & format() const {
4653- throw wexception("format() not implemented");
4654- }
4655-
4656- //@{
4657- /**
4658- * Direct pixel access. lock() must be called before pixles may be access.
4659- * This is faster than indirect pixel access but also more dangerous.
4660- * get_pixels() gives a pointer to the pixel data. get_pitch() returns an
4661- * integer where the next row begins.
4662- */
4663- virtual uint16_t get_pitch() const {
4664- throw wexception("get_pitch() not implemented");
4665- }
4666- virtual uint8_t * get_pixels() const {
4667- throw wexception("get_pixels() not implemented");
4668- }
4669- //@}
4670-
4671 /// Clears the complete surface to black.
4672 virtual void clear() {
4673 fill_rect
4674@@ -123,36 +71,16 @@
4675 virtual void brighten_rect(Rect, int32_t factor) = 0;
4676
4677 /// This draws a part aother surface to this surface
4678- virtual void blit(Point, Surface *, Rect srcrc, bool enable_alpha = false) = 0;
4679+ virtual void blit(Point, PictureID, Rect srcrc, Composite cm = CM_Normal) = 0;
4680 /// This draws another surface completely in the left
4681 /// upper corner of this surface
4682- virtual void fast_blit(Surface * surface) {
4683- blit
4684- (Point(0, 0),
4685- surface,
4686- Rect(Point(0, 0), surface->get_w(), surface->get_h()));
4687- }
4688-
4689- /// set the type of the surface
4690- virtual void set_type(SurfaceType const type) {m_surf_type = type;}
4691-
4692-protected:
4693- int32_t m_offsx;
4694- int32_t m_offsy;
4695- uint32_t m_w, m_h;
4696-
4697- Surface():
4698- m_offsx(0), m_offsy(0),
4699- m_w(0), m_h(0),
4700- m_surf_type(SURFACE_INVALID)
4701- {}
4702- Surface(int w, int h, SurfaceType t):
4703- m_offsx(0), m_offsy(0),
4704- m_w(w), m_h(h),
4705- m_surf_type(t)
4706- {}
4707- SurfaceType m_surf_type;
4708+ virtual void fast_blit(PictureID surface) = 0;
4709+
4710+ virtual IPixelAccess & pixelaccess() = 0;
4711+
4712 private:
4713+ // surfaces cannot be copied
4714+ Surface(const Surface &);
4715 Surface & operator= (Surface const &);
4716 };
4717
4718
4719=== added file 'src/graphic/surfaceptr.h'
4720--- src/graphic/surfaceptr.h 1970-01-01 00:00:00 +0000
4721+++ src/graphic/surfaceptr.h 2010-11-29 19:01:16 +0000
4722@@ -0,0 +1,31 @@
4723+/*
4724+ * Copyright (C) 2010 by the Widelands Development Team
4725+ *
4726+ * This program is free software; you can redistribute it and/or
4727+ * modify it under the terms of the GNU General Public License
4728+ * as published by the Free Software Foundation; either version 2
4729+ * of the License, or (at your option) any later version.
4730+ *
4731+ * This program is distributed in the hope that it will be useful,
4732+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4733+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4734+ * GNU General Public License for more details.
4735+ *
4736+ * You should have received a copy of the GNU General Public License
4737+ * along with this program; if not, write to the Free Software
4738+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
4739+ *
4740+ */
4741+
4742+#ifndef SURFACEPTR_H
4743+#define SURFACEPTR_H
4744+
4745+#include <boost/shared_ptr.hpp>
4746+
4747+struct IOffscreenSurface;
4748+struct Surface;
4749+
4750+typedef boost::shared_ptr<IOffscreenSurface> OffscreenSurfacePtr;
4751+typedef boost::shared_ptr<Surface> SurfacePtr;
4752+
4753+#endif // SURFACEPTR_H
4754
4755=== modified file 'src/graphic/texture.cc'
4756--- src/graphic/texture.cc 2010-11-21 11:44:22 +0000
4757+++ src/graphic/texture.cc 2010-11-29 19:01:16 +0000
4758@@ -102,14 +102,14 @@
4759
4760 #ifdef USE_OPENGL
4761 if (g_opengl) {
4762- SurfaceOpenGL * tsurface =
4763- &dynamic_cast<SurfaceOpenGL &>
4764- (g_gr->load_image(fname));
4765- // SDL_ConvertSurface(surf, &fmt, 0);
4766- m_glFrames.push_back(tsurface);
4767- tsurface->lock();
4768- m_mmap_color = tsurface->get_pixel(0, 0);
4769- tsurface->unlock();
4770+ // Note: we except the constructor to free the SDL surface
4771+ boost::shared_ptr<GLPictureTexture> surface(new GLPictureTexture(surf));
4772+ m_glFrames.push_back(surface);
4773+
4774+ surface->lock(IPixelAccess::Lock_Normal);
4775+ m_mmap_color = surface->get_pixel(0, 0);
4776+ surface->unlock(IPixelAccess::Unlock_NoChange);
4777+
4778 ++m_nrframes;
4779 continue;
4780 }
4781@@ -181,11 +181,6 @@
4782 delete m_colormap;
4783 free(m_pixels);
4784 free(m_texture_picture);
4785-
4786-#ifdef USE_OPENGL
4787- container_iterate(std::vector<SurfaceOpenGL *>, m_glFrames, it)
4788- delete *it.current;
4789-#endif
4790 }
4791
4792 /**
4793
4794=== modified file 'src/graphic/texture.h'
4795--- src/graphic/texture.h 2010-11-01 22:37:46 +0000
4796+++ src/graphic/texture.h 2010-11-29 19:01:16 +0000
4797@@ -23,7 +23,7 @@
4798 #include "colormap.h"
4799 #include "picture_id.h"
4800
4801-#include "graphic/render/surface_opengl.h"
4802+#include "graphic/render/gl_picture_texture.h"
4803
4804 #include <boost/shared_ptr.hpp>
4805 #include <stdint.h>
4806@@ -65,7 +65,7 @@
4807 bool was_animated() const throw () {return m_was_animated;}
4808 #ifdef USE_OPENGL
4809 uint32_t getTexture() const
4810- {return m_glFrames.at(m_frame_num)->get_texture();}
4811+ {return m_glFrames.at(m_frame_num)->get_gl_texture();}
4812 #endif
4813
4814 private:
4815@@ -80,7 +80,7 @@
4816 bool is_32bit;
4817 bool m_was_animated;
4818 #ifdef USE_OPENGL
4819- std::vector<SurfaceOpenGL *> m_glFrames;
4820+ std::vector<boost::shared_ptr<GLPictureTexture> > m_glFrames;
4821 #endif
4822 };
4823
4824
4825=== modified file 'src/map_io/widelands_map_extradata_data_packet.cc'
4826--- src/map_io/widelands_map_extradata_data_packet.cc 2010-05-12 10:16:44 +0000
4827+++ src/map_io/widelands_map_extradata_data_packet.cc 2010-11-29 19:01:16 +0000
4828@@ -75,20 +75,19 @@
4829 if (!surf)
4830 continue; // Illegal pic. Skip it.
4831
4832- Surface & picsurf = g_gr->create_surface(*surf);
4833+ PictureID const picture = g_gr->convert_sdl_surface_to_picture(surf);
4834
4835 std::string picname = FileSystem::FS_Filename(pname->c_str());
4836 picname = "map:" + picname;
4837
4838- PictureID const data =
4839- g_gr->get_picture(PicMod_Game, picsurf, picname.c_str());
4840+ g_gr->add_picture_to_cache(PicMod_Game, picname, picture);
4841
4842 // OK, the pic is now known to the game. But when the game is
4843 // saved, this data has to be regenerated.
4844 Map::Extradata_Info info;
4845 info.type = Map::Extradata_Info::PIC;
4846 info.filename = *pname;
4847- info.data = data;
4848+ info.data = picture;
4849 map.m_extradatainfos.push_back(info);
4850 }
4851 }
4852
4853=== modified file 'src/ui_basic/button.cc'
4854--- src/ui_basic/button.cc 2010-11-01 23:32:46 +0000
4855+++ src/ui_basic/button.cc 2010-11-29 19:01:16 +0000
4856@@ -22,6 +22,7 @@
4857 #include "mouse_constants.h"
4858
4859 #include "graphic/font_handler.h"
4860+#include "graphic/offscreensurface.h"
4861 #include "graphic/rendertarget.h"
4862 #include "wlapplication.h"
4863 #include "log.h"
4864@@ -48,7 +49,6 @@
4865 m_repeating (false),
4866 m_flat (flat),
4867 m_needredraw (true),
4868- m_cache_pic (g_gr->get_no_picture()),
4869 m_title (title_text),
4870 m_pic_background(background_picture_id),
4871 m_pic_custom (g_gr->get_no_picture()),
4872@@ -81,7 +81,6 @@
4873 m_repeating (false),
4874 m_flat (flat),
4875 m_needredraw (true),
4876- m_cache_pic (g_gr->get_no_picture()),
4877 m_pic_background(background_picture_id),
4878 m_pic_custom (foreground_picture_id),
4879 m_pic_custom_disabled(g_gr->create_grayed_out_pic(foreground_picture_id)),
4880@@ -94,9 +93,8 @@
4881 }
4882
4883
4884-Button::~Button() {
4885- if (m_pic_custom_disabled != g_gr->get_no_picture())
4886- g_gr->free_picture_surface(m_pic_custom_disabled);
4887+Button::~Button()
4888+{
4889 }
4890
4891
4892@@ -113,8 +111,6 @@
4893 m_needredraw = true;
4894
4895 m_pic_custom = picid;
4896- if (m_pic_custom_disabled != g_gr->get_no_picture())
4897- g_gr->free_picture_surface(m_pic_custom_disabled);
4898 m_pic_custom_disabled = g_gr->create_grayed_out_pic(picid);
4899
4900 update();
4901@@ -168,7 +164,7 @@
4902 */
4903 void Button::draw(RenderTarget & odst)
4904 {
4905- RenderTarget * dst = &odst;
4906+ RenderTarget dst = odst;
4907
4908 if (g_gr->caps().offscreen_rendering) {
4909 if (!m_needredraw)
4910@@ -176,18 +172,15 @@
4911 odst.blit(Point(0, 0), m_cache_pic);
4912 return;
4913 } else {
4914- if (m_cache_pic == g_gr->get_no_picture())
4915- m_cache_pic =
4916- g_gr->create_picture_surface(get_w(), get_h(), m_flat);
4917- else if
4918- (m_cache_pic->rendertarget->get_w() != get_w() or
4919- m_cache_pic->rendertarget->get_h() != get_h())
4920+ if
4921+ (!m_cache_pic ||
4922+ (static_cast<IPicture *>(m_cache_pic.get())->get_w() != static_cast<uint32_t>(get_w()) or
4923+ static_cast<IPicture *>(m_cache_pic.get())->get_h() != static_cast<uint32_t>(get_h())))
4924 {
4925- g_gr->free_picture_surface(m_cache_pic);
4926 m_cache_pic =
4927- g_gr->create_picture_surface(get_w(), get_h(), m_flat);
4928+ g_gr->create_offscreen_surface(get_w(), get_h(), m_flat);
4929 }
4930- dst = (g_gr->get_surface_renderer(m_cache_pic));
4931+ dst = RenderTarget(m_cache_pic);
4932 }
4933 }
4934
4935@@ -195,18 +188,18 @@
4936 // Draw the background
4937 if (not m_flat) {
4938 assert(m_pic_background != g_gr->get_no_picture());
4939- dst->fill_rect
4940+ dst.fill_rect
4941 (Rect(Point(0, 0), get_w(), get_h()), RGBAColor(0, 0, 0, 255));
4942- dst->tile
4943+ dst.tile
4944 (Rect(Point(0, 0), get_w(), get_h()),
4945 m_pic_background,
4946 Point(get_x(), get_y()));
4947 } else if (g_gr->caps().offscreen_rendering)
4948- dst->fill_rect
4949+ dst.fill_rect
4950 (Rect(Point(0, 0), get_w(), get_h()), RGBAColor(0, 0, 0, 0));
4951
4952 if (m_enabled and m_highlighted and not m_flat)
4953- dst->brighten_rect
4954+ dst.brighten_rect
4955 (Rect(Point(0, 0), get_w(), get_h()), MOUSE_OVER_BRIGHT_FACTOR);
4956
4957 // if we got a picture, draw it centered
4958@@ -217,13 +210,14 @@
4959 // ">> 1" is almost like "/ 2", but simpler for signed types (difference
4960 // is that -1 >> 1 is -1 but -1 / 2 is 0).
4961 if (g_gr->caps().offscreen_rendering and m_flat)
4962- dst->blit_copy
4963+ dst.blit
4964 (Point
4965 ((get_w() - static_cast<int32_t>(cpw)) >> 1,
4966 (get_h() - static_cast<int32_t>(cph)) >> 1),
4967- m_enabled ? m_pic_custom : m_pic_custom_disabled);
4968+ m_enabled ? m_pic_custom : m_pic_custom_disabled,
4969+ CM_Copy);
4970 else
4971- dst->blit
4972+ dst.blit
4973 (Point
4974 ((get_w() - static_cast<int32_t>(cpw)) >> 1,
4975 (get_h() - static_cast<int32_t>(cph)) >> 1),
4976@@ -231,7 +225,7 @@
4977
4978 } else if (m_title.length()) // otherwise draw title string centered
4979 UI::g_fh->draw_string
4980- (*dst,
4981+ (dst,
4982 m_fontname,
4983 m_fontsize,
4984 m_enabled ? UI_FONT_CLR_FG : UI_FONT_CLR_DISABLED, UI_FONT_CLR_BG,
4985@@ -240,7 +234,7 @@
4986 Align_Center,
4987 std::numeric_limits<uint32_t>::max(),
4988 Widget_Cache_None,
4989- g_gr->get_no_picture(),
4990+ 0,
4991 m_draw_caret ? m_title.length() :
4992 std::numeric_limits<uint32_t>::max());
4993
4994@@ -260,32 +254,32 @@
4995 // button is a normal one, not flat
4996 if (not draw_pressed) {
4997 // top edge
4998- dst->brighten_rect
4999+ dst.brighten_rect
5000 (Rect(Point(0, 0), get_w(), 2), BUTTON_EDGE_BRIGHT_FACTOR);
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches

to status/vote changes: