ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/DC/Texture.pm
Revision: 1.10
Committed: Tue Jul 4 23:23:32 2006 UTC (17 years, 11 months ago) by root
Branch: MAIN
Changes since 1.9: +15 -15 lines
Log Message:
Get rid of cairo completely (yay!) and of ft2 factually (still need the
library as it included pangofc), by introducing a custom pango opengl
renderer.

Text rendering now no longer requires the distinction between rgba and
grayscale modes, requires much less texture space and memory, and is
faster on accelerated hardware (and possibly with software rendering, too).

All at the cost of only 1200 lines or so.

File Contents

# Content
1 =head1 NAME
2
3 CFClient::Texture - tetxure class for CFClient
4
5 =head1 SYNOPSIS
6
7 use CFClient::Texture;
8
9 =head1 DESCRIPTION
10
11 =over 4
12
13 =cut
14
15 package CFClient::Texture;
16
17 use strict;
18
19 use Scalar::Util;
20
21 use CFClient::OpenGL;
22
23 my %TEXTURES;
24
25 sub new {
26 my ($class, %data) = @_;
27
28 my $self = bless {
29 internalformat => GL_RGBA,
30 format => GL_RGBA,
31 type => GL_UNSIGNED_BYTE,
32 %data,
33 }, $class;
34
35 Scalar::Util::weaken ($TEXTURES{$self+0} = $self);
36
37 $self->upload;
38
39 $self
40 }
41
42 sub new_from_image {
43 my ($class, $image, %arg) = @_;
44
45 $class->new (image => $image, internalformat => undef, %arg)
46 }
47
48 sub new_from_file {
49 my ($class, $path, %arg) = @_;
50
51 open my $fh, "<:raw", $path
52 or die "$path: $!";
53
54 local $/;
55 $class->new_from_image (<$fh>, %arg)
56 }
57
58 #sub new_from_surface {
59 # my ($class, $surface) = @_;
60 #
61 # $surface->rgba;
62 #
63 # $class->new (
64 # data => $surface->pixels,
65 # w => $surface->width,
66 # h => $surface->height,
67 # )
68 #}
69
70 #sub new_from_layout {
71 # my ($class, $layout, %arg) = @_;
72 #
73 # my ($w, $h, $data, $format, $internalformat) = $layout->render;
74 #
75 # $class->new (
76 # w => $w,
77 # h => $h,
78 # data => $data,
79 # format => $format,
80 # internalformat => $format,
81 # type => GL_UNSIGNED_BYTE,
82 # %arg,
83 # )
84 #}
85
86 sub new_from_opengl {
87 my ($class, $w, $h, $cb) = @_;
88
89 $class->new (w => $w || 1, h => $h || 1, render_cb => $cb)
90 }
91
92 sub upload {
93 my ($self) = @_;
94
95 return unless $GL_VERSION;
96
97 my $data;
98
99 if (exists $self->{data}) {
100 $data = $self->{data};
101
102 } elsif (exists $self->{render_cb}) {
103 glViewport 0, 0, $self->{w}, $self->{h};
104 glMatrixMode GL_PROJECTION;
105 glLoadIdentity;
106 glOrtho 0, $self->{w}, 0, $self->{h}, -10000, 10000;
107 glMatrixMode GL_MODELVIEW;
108 glLoadIdentity;
109 $self->{render_cb}->($self, $self->{w}, $self->{h});
110
111 } else {
112 ($self->{w}, $self->{h}, $data, my $internalformat, $self->{format}, $self->{type})
113 = CFClient::load_image_inline $self->{image};
114
115 $self->{internalformat} ||= $internalformat;
116 }
117
118 my ($tw, $th) = @$self{qw(w h)};
119
120 $self->{minified} ||= [CFClient::average $tw, $th, $data]
121 if $self->{minify};
122
123 pad2pot $data, $tw, $th unless $GL_NPOT;
124
125 $self->{s} = $self->{w} / $tw;
126 $self->{t} = $self->{h} / $th;
127
128 $self->{name} ||= glGenTexture;
129
130 glBindTexture GL_TEXTURE_2D, $self->{name};
131
132 if ($self->{wrap}) {
133 glTexParameter GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT;
134 glTexParameter GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT;
135 } else {
136 glTexParameter GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, $GL_VERSION >= 1.2 ? GL_CLAMP_TO_EDGE : GL_CLAMP;
137 glTexParameter GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, $GL_VERSION >= 1.2 ? GL_CLAMP_TO_EDGE : GL_CLAMP;
138 }
139
140 if ($::FAST) {
141 glTexParameter GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST;
142 glTexParameter GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST;
143 } elsif ($self->{mipmap} && $GL_VERSION >= 1.4) {
144 glTexParameter GL_TEXTURE_2D, GL_GENERATE_MIPMAP, 1;
145 glTexParameter GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR;
146 glTexParameter GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR;
147 } else {
148 glTexParameter GL_TEXTURE_2D, GL_GENERATE_MIPMAP, $self->{mipmap};
149 glTexParameter GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR;
150 glTexParameter GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR;
151 }
152
153 glGetError;
154
155 if (defined $data) {
156 glTexImage2D GL_TEXTURE_2D, 0,
157 $self->{internalformat},
158 $tw, $th,
159 0,
160 $self->{format},
161 $self->{type},
162 $data;
163 gl_check "uploading texture %dx%d if=%x f=%x t=%x",
164 $tw, $th, $self->{internalformat}, $self->{format}, $self->{type};
165 } else {
166 exists $self->{render_cb} or die;
167 glCopyTexImage2D GL_TEXTURE_2D, 0,
168 $self->{internalformat},
169 0, 0,
170 $tw, $th,
171 0;
172 gl_check "copying to texture %dx%d if=%x",
173 $tw, $th, $self->{internalformat};
174 }
175 }
176
177 sub shutdown {
178 my ($self) = @_;
179
180 glDeleteTexture $self->{name}
181 if $self->{name};
182 }
183
184 sub DESTROY {
185 my ($self) = @_;
186
187 delete $TEXTURES{$self+0};
188
189 $self->shutdown;
190 }
191
192 $CFClient::OpenGL::INIT_HOOK{"CFClient::Texture"} = sub {
193 # first mark all existing texture names as in-use, in case the context lost textures
194 glBindTexture GL_TEXTURE_2D, $_->{name}
195 for values %TEXTURES;
196 $_->upload
197 for values %TEXTURES;
198 };
199
200 $CFClient::OpenGL::SHUTDOWN_HOOK{"CFClient::Texture"} = sub {
201 $_->shutdown
202 for values %TEXTURES;
203 };
204
205 1;
206
207 =back
208
209 =head1 AUTHOR
210
211 Marc Lehmann <schmorp@schmorp.de>
212 http://home.schmorp.de/
213
214 =cut
215