Merge lp:~nha/widelands/graphics-refactor into lp:widelands
- graphics-refactor
- Merge into trunk
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 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Widelands Developers | Pending | ||
Review via email: mp+42016@code.launchpad.net |
Commit message
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.