ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/DC/Texture.pm
Revision: 1.13
Committed: Sat Dec 9 21:26:46 2006 UTC (17 years, 5 months ago) by root
Branch: MAIN
CVS Tags: rel-0_97, rel-0_98
Changes since 1.12: +1 -3 lines
Log Message:
- do no longer depend on Scalar::Util for weaken
- use a different, cleaner, more correct and less efficient event propagation mechanism
- this fixes the segfault bug in map $_.

File Contents

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