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

# User Rev Content
1 root 1.1 =head1 NAME
2    
3 root 1.11 CFPlus::Texture - tetxure class for CFPlus
4 root 1.1
5     =head1 SYNOPSIS
6    
7 root 1.11 use CFPlus::Texture;
8 root 1.1
9     =head1 DESCRIPTION
10    
11     =over 4
12    
13     =cut
14    
15 root 1.11 package CFPlus::Texture;
16 root 1.1
17     use strict;
18    
19 root 1.11 use CFPlus::OpenGL;
20 root 1.1
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 root 1.13 CFPlus::weaken ($TEXTURES{$self+0} = $self);
34 root 1.1
35     $self->upload;
36    
37     $self
38     }
39    
40     sub new_from_image {
41     my ($class, $image, %arg) = @_;
42    
43 root 1.7 $class->new (image => $image, internalformat => undef, %arg)
44 root 1.1 }
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 root 1.10 #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 root 1.1
84     sub new_from_opengl {
85     my ($class, $w, $h, $cb) = @_;
86    
87 root 1.12 $class->new (w => $w || 1, h => $h || 1, render_cb => $cb, nearest => 1)
88 root 1.1 }
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 root 1.7 ($self->{w}, $self->{h}, $data, my $internalformat, $self->{format}, $self->{type})
111 root 1.11 = CFPlus::load_image_inline $self->{image};
112 root 1.7
113     $self->{internalformat} ||= $internalformat;
114 root 1.1 }
115    
116     my ($tw, $th) = @$self{qw(w h)};
117    
118 root 1.11 $self->{minified} ||= [CFPlus::average $tw, $th, $data]
119 root 1.1 if $self->{minify};
120    
121 root 1.5 pad2pot $data, $tw, $th unless $GL_NPOT;
122 root 1.1
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 root 1.2 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 root 1.1
138 root 1.12 if ($::FAST || $self->{nearest}) {
139 root 1.1 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 root 1.9 exists $self->{render_cb} or die;
165 root 1.1 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 root 1.8 sub shutdown {
176     my ($self) = @_;
177    
178 root 1.9 glDeleteTexture $self->{name}
179 root 1.8 if $self->{name};
180     }
181    
182 root 1.1 sub DESTROY {
183     my ($self) = @_;
184    
185     delete $TEXTURES{$self+0};
186    
187 root 1.8 $self->shutdown;
188 root 1.1 }
189    
190 root 1.11 $CFPlus::OpenGL::INIT_HOOK{"CFPlus::Texture"} = sub {
191 root 1.9 # 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 root 1.1 $_->upload
195     for values %TEXTURES;
196     };
197    
198 root 1.11 $CFPlus::OpenGL::SHUTDOWN_HOOK{"CFPlus::Texture"} = sub {
199 root 1.8 $_->shutdown
200     for values %TEXTURES;
201     };
202    
203 root 1.1 1;
204    
205     =back
206    
207     =head1 AUTHOR
208    
209     Marc Lehmann <schmorp@schmorp.de>
210     http://home.schmorp.de/
211    
212     =cut
213