1 /*******************************************************************************
2 * Goggles Music Manager *
3 ********************************************************************************
4 * Copyright (C) 2009-2021 by Sander Jansen. All Rights Reserved *
5 * --- *
6 * This program is free software: you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation, either version 3 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program. If not, see http://www.gnu.org/licenses. *
18 ********************************************************************************/
19 #include "gmdefs.h"
20 #ifdef HAVE_OPENGL
21 #include "GMImageView.h"
22 #include <GL/glu.h>
23
GMImageTexture()24 GMImageTexture::GMImageTexture() :
25 id(0),
26 cw(1.0f),
27 ch(1.0f),
28 aspect(1.0f) {}
29
~GMImageTexture()30 GMImageTexture::~GMImageTexture() {
31 FXASSERT(id==0);
32 }
33
setImage(FXImage * image)34 FXbool GMImageTexture::setImage(FXImage* image) {
35 if (image) {
36 FXint image_width = image->getWidth();
37 FXint image_height = image->getHeight();
38 FXint texture_width,texture_height;
39 FXint texture_max;
40
41
42 /// Query Maximum Texture Size
43 glGetIntegerv(GL_MAX_TEXTURE_SIZE,&texture_max);
44
45 /// Prescale to maximum texture size if necessary
46 if((image_width>texture_max) || (image_height>texture_max)){
47
48 if(image_width>image_height)
49 image->scale(texture_max,(texture_max*image_height)/image_width,FOX_SCALE_BEST);
50 else
51 image->scale((texture_max*image_width)/image_height,texture_max,FOX_SCALE_BEST);
52
53 image_width=image->getWidth();
54 image_height=image->getHeight();
55 }
56
57 // aspect ratio
58 aspect = image->getWidth() / (FXfloat) image->getHeight();
59
60
61 /// Get a nice texture size
62 if (epoxy_has_gl_extension("GL_ARB_texture_non_power_of_two")) {
63 texture_width=image_width;
64 texture_height=image_height;
65 }
66 else {
67 texture_width=1;
68 texture_height=1;
69 while(image_width>texture_width) texture_width<<=1;
70 while(image_height>texture_height) texture_height<<=1;
71 }
72
73 FXASSERT(texture_width<=texture_max);
74 FXASSERT(texture_height<=texture_max);
75
76 /// Generate a new texture if required.
77 if (id==0) {
78 glGenTextures(1,&id);
79 }
80
81 glBindTexture(GL_TEXTURE_2D,id);
82 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
83 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
84
85 FXbool use_mipmap = (epoxy_gl_version()>=30);
86
87 if (use_mipmap) {
88 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
89 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
90 }
91 else {
92 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
93 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
94 }
95
96 if (texture_width==image_width && texture_height==image_height) {
97 glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8,texture_width,texture_height,0,GL_BGRA,GL_UNSIGNED_INT_8_8_8_8_REV,image->getData());
98 cw=ch=1.0f;
99 }
100 else {
101 glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8,texture_width,texture_height,0,GL_BGRA,GL_UNSIGNED_INT_8_8_8_8_REV,nullptr);
102 glTexSubImage2D(GL_TEXTURE_2D,0,0,0,image_width,image_height,GL_BGRA,GL_UNSIGNED_INT_8_8_8_8_REV,image->getData());
103 cw = (1.0f / (FXfloat)(texture_width)) * image_width;
104 ch = (1.0f / (FXfloat)(texture_height)) * image_height;
105 }
106 if (use_mipmap)
107 glGenerateMipmap(GL_TEXTURE_2D);
108 }
109 else {
110 if (id) {
111 glDeleteTextures(1,&id);
112 id=0;
113 }
114 }
115 return true;
116 }
117
118
drawQuad(FXfloat x,FXfloat y,FXfloat width,FXfloat height,FXColor background)119 void GMImageTexture::drawQuad(FXfloat x,FXfloat y,FXfloat width,FXfloat height,FXColor background) {
120 const FXfloat coordinates[8] = { x,y,
121 x,y+height,
122 x+width,y,
123 x+width,y+height
124 };
125
126 const FXfloat tex[8] = { 0.0f,ch,
127 0.0f,0.0f,
128 cw,ch,
129 cw,0.0f
130 };
131
132 const FXuchar colors[16] = { FXREDVAL(background),FXBLUEVAL(background),FXGREENVAL(background),
133 FXREDVAL(background),FXBLUEVAL(background),FXGREENVAL(background),
134 FXREDVAL(background),FXBLUEVAL(background),FXGREENVAL(background),
135 FXREDVAL(background),FXBLUEVAL(background),FXGREENVAL(background) };
136
137
138 glEnable(GL_TEXTURE_2D);
139 glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL);
140 glBindTexture(GL_TEXTURE_2D,id);
141 glEnableClientState(GL_VERTEX_ARRAY);
142 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
143 glEnableClientState(GL_COLOR_ARRAY);
144 glColorPointer(3,GL_UNSIGNED_BYTE,0,colors);
145 glVertexPointer(2,GL_FLOAT,0,coordinates);
146 glTexCoordPointer(2,GL_FLOAT,0,tex);
147 glDrawArrays(GL_TRIANGLE_STRIP,0,4);
148 glDisableClientState(GL_COLOR_ARRAY);
149 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
150 glDisableClientState(GL_VERTEX_ARRAY);
151 }
152
153
154
155 FXDEFMAP(GMImageView) GMImageViewMap[]={
156 FXMAPFUNC(SEL_PAINT,0,GMImageView::onPaint)
157 };
158
159 FXIMPLEMENT(GMImageView,FXGLCanvas,GMImageViewMap,ARRAYNUMBER(GMImageViewMap));
160
161
GMImageView()162 GMImageView::GMImageView(){
163 texture=nullptr;
164 }
165
GMImageView(FXComposite * p,FXGLContext * ctx,FXuint opts,FXint x,FXint y,FXint w,FXint h)166 GMImageView::GMImageView(FXComposite* p,FXGLContext *ctx,FXuint opts,FXint x,FXint y,FXint w,FXint h) : FXGLCanvas(p,ctx,nullptr,0,opts,x,y,w,h){
167 texture=nullptr;
168 }
169
~GMImageView()170 GMImageView::~GMImageView(){
171 delete texture;
172 }
173
setImage(FXImage * image)174 void GMImageView::setImage(FXImage * image) {
175 if (makeCurrent()) {
176 if (texture==nullptr && image) {
177 texture = new GMImageTexture();
178 }
179 if (texture) texture->setImage(image);
180 makeNonCurrent();
181 }
182 recalc();
183 update();
184 }
185
186
getDefaultWidth()187 FXint GMImageView::getDefaultWidth() {
188 return 256;
189 }
190
getDefaultHeight()191 FXint GMImageView::getDefaultHeight() {
192 return 256;
193 }
194
195 // Repaint the GL window
onPaint(FXObject *,FXSelector,void *)196 long GMImageView::onPaint(FXObject*,FXSelector,void*){
197 FXGLVisual *vis=(FXGLVisual*)getVisual();
198 FXfloat aspect = getWidth() / (float)getHeight();
199 FXfloat xwidth = 1.0f*aspect;
200 FXfloat size;
201
202 FXVec4f background=colorToVec4f(backColor);
203 FXASSERT(xid);
204 if(makeCurrent()){
205 glViewport(0,0,getWidth(),getHeight());
206 glClearColor(background.x,background.y,background.z,background.w);
207 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
208
209 if (texture && texture->id) {
210 glMatrixMode(GL_MODELVIEW);
211 glLoadIdentity();
212 gluOrtho2D(0,xwidth,0.0f,1.0f);
213
214 if (aspect>=texture->aspect) {
215 size = 1.0f*texture->aspect;
216 texture->drawQuad(0.5f*(xwidth-size),0.0f,size,1.0f,backColor);
217 }
218 else {
219 size = xwidth / texture->aspect;
220 texture->drawQuad(0.0f,0.5f * (1.0f-size),xwidth,size,backColor);
221 }
222 }
223 if(vis->isDoubleBuffer()) swapBuffers();
224 makeNonCurrent();
225 }
226 return 1;
227 }
228 #endif
229