2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License
4 * as published by the Free Software Foundation; either version 2
5 * of the License, or (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16 * See the COPYING file for license information.
18 * Guillaume Chazarain <gfc@altern.org>
21 /************************
22 * Rendering functions. *
23 ************************/
27 #include <gtk/gtkgl.h>
31 extern options_struct
*options
;
32 extern gliv_image
*current_image
;
33 extern GtkWidget
*gl_widget
;
35 static guint idle_id
= 0;
37 static void set_filter(gint filter
)
42 /* All textures have the same parameters. */
44 for (level
= 0; level
< current_image
->nb_maps
; level
++) {
45 map
= current_image
->maps
+ level
;
47 for (id
= 0; id
< map
->nb_tiles
; id
++) {
48 glBindTexture(GL_TEXTURE_2D
, map
->tex_ids
[id
]);
49 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, filter
);
50 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, filter
);
55 static void call_lists(gboolean smooth
, gint level
)
60 if (rt
->filtering_enabled
!= smooth
) {
61 rt
->filtering_enabled
= smooth
;
62 set_filter(smooth
? GL_LINEAR
: GL_NEAREST
);
65 map
= current_image
->maps
+ level
;
67 for (id
= 0; id
< map
->nb_tiles
; id
++)
68 if (matrix_tile_visible(map
->tiles
+ id
))
69 glCallList(map
->list
+ id
);
72 static void draw_checker(void)
74 static guint tex_id
= 0;
76 gfloat half_w
, half_h
;
77 gboolean matrix_changed
;
79 matrix_changed
= get_matrix_has_changed();
81 if (rt
->alpha_checks_changed
) {
85 glGenTextures(1, &tex_id
);
87 for (i
= 0; i
< 3; i
++) {
88 texture
[i
] = texture
[9 + i
] = options
->alpha1
[i
];
89 texture
[3 + i
] = texture
[6 + i
] = options
->alpha2
[i
];
92 glBindTexture(GL_TEXTURE_2D
, tex_id
);
94 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
95 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
97 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_REPEAT
);
98 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_REPEAT
);
100 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGB
, 2, 2, 0, GL_RGB
,
101 GL_UNSIGNED_SHORT
, texture
);
103 rt
->alpha_checks_changed
= FALSE
;
105 glBindTexture(GL_TEXTURE_2D
, tex_id
);
107 if (matrix_changed
== FALSE
)
108 /* glMatrixMode(GL_MODELVIEW); */
109 /* Save the matrix only if we will not replace it when redrawing. */
114 half_w
= rt
->wid_size
->width
/ 2.0;
115 half_h
= rt
->wid_size
->height
/ 2.0;
119 glTexCoord2f(0.0, 0.0);
120 glVertex2f(-half_w
, -half_h
);
122 glTexCoord2f(half_w
/ 16.0, 0.0);
123 glVertex2f(half_w
, -half_h
);
125 glTexCoord2f(half_w
/ 16.0, half_h
/ 16.0);
126 glVertex2f(half_w
, half_h
);
128 glTexCoord2f(0.0, half_h
/ 16.0);
129 glVertex2f(-half_w
, half_h
);
133 if (matrix_changed
== FALSE
)
134 /* glMatrixMode(GL_MODELVIEW); */
138 static gint
choose_mipmap_level(void)
140 gfloat zoom
, mipmap_ratio
= MIPMAP_RATIO
;
143 if (options
->mipmap
) {
144 zoom
= get_matrix_zoom();
146 while (mipmap_ratio
> zoom
&& level
< current_image
->nb_maps
) {
147 mipmap_ratio
*= MIPMAP_RATIO
;
152 /* Mipmaps should only be scaled down. */
156 static gboolean
redraw(void)
158 GdkGLDrawable
*gldrawable
;
162 gldrawable
= gtk_widget_get_gl_drawable(gl_widget
);
163 gdk_gl_drawable_wait_gdk(gldrawable
);
165 glDisable(GL_DITHER
);
167 if (current_image
!= NULL
&& current_image
->has_alpha
&&
168 options
->alpha_checks
)
172 glClear(GL_COLOR_BUFFER_BIT
);
178 if (current_image
!= NULL
)
179 call_lists(is_filtering_needed(), choose_mipmap_level());
181 gdk_gl_drawable_swap_buffers(gldrawable
);
183 if (current_image
!= NULL
&& options
->scrollbars
)
184 update_scrollbars(TRUE
);
186 gdk_gl_drawable_wait_gl(gldrawable
);
188 /* To remove the idle func. */
195 prioritize_textures(current_image
, TRUE
);
198 delete_selected_image();
199 fill_ident(current_image
);
201 rt
->filtering_enabled
= FALSE
;
203 if (options
->fullscreen
== FALSE
)
206 if (options
->maximize
|| options
->scaledown
)
207 matrix_set_max_zoom(-1, -1, TRUE
);
209 refresh(REFRESH_NOW
| REFRESH_STATUS
| APPEND_HISTORY
);
211 /* A bit dumb, but needed on some cards. */
212 refresh(REFRESH_NOW
);
214 g_free(current_image
->ident
);
215 current_image
->ident
= NULL
;
217 update_window_title();
221 void zoom_in(gfloat ratio
)
223 gint pointer_x
, pointer_y
;
226 if (options
->zoom_pointer
) {
227 /* The pointer is the zoom center. */
228 gdk_window_get_pointer(gl_widget
->window
, &pointer_x
, &pointer_y
, NULL
);
229 x
= (gfloat
) pointer_x
;
230 y
= (gfloat
) pointer_y
;
232 /* The zoom center is the midle of the window. */
233 x
= rt
->wid_size
->width
/ 2.0;
234 y
= rt
->wid_size
->height
/ 2.0;
237 matrix_zoom(ratio
, x
, y
);
238 refresh(REFRESH_IMAGE
| REFRESH_STATUS
| APPEND_HISTORY
);
241 void refresh(gint what
)
243 /* GTK does that automatically but with more overhead. */
244 if (what
& REFRESH_IMAGE
) {
247 idle_id
= gtk_idle_add_priority(GDK_PRIORITY_REDRAW
,
248 (GtkFunction
) redraw
, NULL
);
250 } else if (what
& REFRESH_NOW
) {
253 gtk_idle_remove(idle_id
);
258 if (what
& REFRESH_STATUS
)
261 if (what
& APPEND_HISTORY
)