16 #include "kernel/openbox.h"
23 XVisualInfo render_visual_info;
25 Visual *render_visual;
26 Colormap render_colormap;
28 int render_red_offset = 0, render_green_offset = 0, render_blue_offset = 0;
29 int render_red_shift, render_green_shift, render_blue_shift;
30 int render_red_mask, render_green_mask, render_blue_mask;
35 GLXContext render_glx_context;
37 int render_glx_rating(XVisualInfo *v)
42 printf("evaluating visual %d\n", v->visualid);
43 glXGetConfig(ob_display, v, GLX_BUFFER_SIZE, &val);
44 printf("buffer size %d\n", val);
58 glXGetConfig(ob_display, v, GLX_LEVEL, &val);
59 printf("level %d\n", val);
63 glXGetConfig(ob_display, v, GLX_DEPTH_SIZE, &val);
64 printf("depth size %d\n", val);
79 glXGetConfig(ob_display, v, GLX_DOUBLEBUFFER, &val);
80 printf("double buffer %d\n", val);
87 void render_startup(void)
89 int count, i = 0, val, best = 0, rate = 0, temp;
90 XVisualInfo vimatch, *vilist;
93 render_depth = DefaultDepth(ob_display, ob_screen);
94 render_visual = DefaultVisual(ob_display, ob_screen);
95 render_colormap = DefaultColormap(ob_display, ob_screen);
98 vimatch.screen = ob_screen;
99 vimatch.class = TrueColor;
100 vilist = XGetVisualInfo(ob_display, VisualScreenMask | VisualClassMask,
104 printf("looking for a GL visualin %d visuals\n", count);
105 for (i = 0; i < count; i++) {
106 glXGetConfig(ob_display, &vilist[i], GLX_USE_GL, &val);
108 temp = render_glx_rating(&vilist[i]);
117 printf("picked visual %d with rating %d\n", best, rate);
118 render_depth = vilist[best].depth;
119 render_visual = vilist[best].visual;
120 render_colormap = XCreateColormap(ob_display, ob_root,
121 render_visual, AllocNone);
122 render_visual_info = vilist[best];
123 render_glx_context = glXCreateContext(ob_display, &render_visual_info,
125 if (render_glx_context == NULL)
134 switch (render_visual->class) {
142 pseudocolor_startup();
145 g_critical("unsupported visual class.\n");
151 void truecolor_startup(void)
153 unsigned long red_mask, green_mask, blue_mask;
154 XImage *timage = NULL;
156 timage = XCreateImage(ob_display, render_visual, render_depth,
157 ZPixmap, 0, NULL, 1, 1, 32, 0);
158 g_assert(timage != NULL);
159 /* find the offsets for each color in the visual's masks */
160 render_red_mask = red_mask = timage->red_mask;
161 render_green_mask = green_mask = timage->green_mask;
162 render_blue_mask = blue_mask = timage->blue_mask;
164 render_red_offset = 0;
165 render_green_offset = 0;
166 render_blue_offset = 0;
168 while (! (red_mask & 1)) { render_red_offset++; red_mask >>= 1; }
169 while (! (green_mask & 1)) { render_green_offset++; green_mask >>= 1; }
170 while (! (blue_mask & 1)) { render_blue_offset++; blue_mask >>= 1; }
172 render_red_shift = render_green_shift = render_blue_shift = 8;
173 while (red_mask) { red_mask >>= 1; render_red_shift--; }
174 while (green_mask) { green_mask >>= 1; render_green_shift--; }
175 while (blue_mask) { blue_mask >>= 1; render_blue_shift--; }
179 void pseudocolor_startup(void)
182 int tr, tg, tb, n, r, g, b, i, incolors, ii;
185 g_message("Initializing PseudoColor RenderControl\n");
187 /* determine the number of colors and the bits-per-color */
188 pseudo_bpc = 2; /* XXX THIS SHOULD BE A USER OPTION */
189 g_assert(pseudo_bpc >= 1);
190 _ncolors = pseudo_ncolors();
192 if (_ncolors > 1 << render_depth) {
193 g_warning("PseudoRenderControl: Invalid colormap size. Resizing.\n");
194 pseudo_bpc = 1 << (render_depth/3) >> 3;
195 _ncolors = 1 << (pseudo_bpc * 3);
198 /* build a color cube */
199 pseudo_colors = malloc(_ncolors * sizeof(XColor));
200 cpc = 1 << pseudo_bpc; /* colors per channel */
202 for (n = 0, r = 0; r < cpc; r++)
203 for (g = 0; g < cpc; g++)
204 for (b = 0; b < cpc; b++, n++) {
205 tr = (int)(((float)(r)/(float)(cpc-1)) * 0xFF);
206 tg = (int)(((float)(g)/(float)(cpc-1)) * 0xFF);
207 tb = (int)(((float)(b)/(float)(cpc-1)) * 0xFF);
208 pseudo_colors[n].red = tr | tr << 8;
209 pseudo_colors[n].green = tg | tg << 8;
210 pseudo_colors[n].blue = tb | tb << 8;
211 pseudo_colors[n].flags = DoRed|DoGreen|DoBlue; /* used to track
215 /* allocate the colors */
216 for (i = 0; i < _ncolors; i++)
217 if (!XAllocColor(ob_display, render_colormap, &pseudo_colors[i]))
218 pseudo_colors[i].flags = 0; /* mark it as unallocated */
220 /* try allocate any colors that failed allocation above */
222 /* get the allocated values from the X server (only the first 256 XXX why!?)
224 incolors = (((1 << render_depth) > 256) ? 256 : (1 << render_depth));
225 for (i = 0; i < incolors; i++)
226 icolors[i].pixel = i;
227 XQueryColors(ob_display, render_colormap, icolors, incolors);
229 /* try match unallocated ones */
230 for (i = 0; i < _ncolors; i++) {
231 if (!pseudo_colors[i].flags) { /* if it wasn't allocated... */
232 unsigned long closest = 0xffffffff, close = 0;
233 for (ii = 0; ii < incolors; ii++) {
234 /* find deviations */
235 r = (pseudo_colors[i].red - icolors[ii].red) & 0xff;
236 g = (pseudo_colors[i].green - icolors[ii].green) & 0xff;
237 b = (pseudo_colors[i].blue - icolors[ii].blue) & 0xff;
238 /* find a weighted absolute deviation */
239 dev = (r * r) + (g * g) + (b * b);
247 pseudo_colors[i].red = icolors[close].red;
248 pseudo_colors[i].green = icolors[close].green;
249 pseudo_colors[i].blue = icolors[close].blue;
250 pseudo_colors[i].pixel = icolors[close].pixel;
252 /* try alloc this closest color, it had better succeed! */
253 if (XAllocColor(ob_display, render_colormap, &pseudo_colors[i]))
254 pseudo_colors[i].flags = DoRed|DoGreen|DoBlue; /* mark as alloced */
256 g_assert(FALSE); /* wtf has gone wrong, its already alloced for
262 void x_paint(Window win, Appearance *l)
264 int i, transferred = 0, sw;
265 pixel32 *source, *dest;
269 int w = l->area.width;
270 int h = l->area.height;
271 Rect tarea; /* area in which to draw textures */
273 if (w <= 0 || h <= 0 || x+w <= 0 || y+h <= 0) return;
275 oldp = l->pixmap; /* save to free after changing the visible pixmap */
276 l->pixmap = XCreatePixmap(ob_display, ob_root, x+w, y+h, render_depth);
277 g_assert(l->pixmap != None);
279 if (l->xftdraw != NULL)
280 XftDrawDestroy(l->xftdraw);
281 l->xftdraw = XftDrawCreate(ob_display, l->pixmap, render_visual,
283 g_assert(l->xftdraw != NULL);
285 g_free(l->surface.pixel_data);
286 l->surface.pixel_data = g_new(pixel32, w * h);
289 if (l->surface.grad == Background_ParentRelative) {
290 sw = l->surface.parent->area.width;
291 source = l->surface.parent->surface.pixel_data
293 + sw * l->surface.parenty;
294 dest = l->surface.pixel_data;
295 for (i = 0; i < h; i++, source += sw, dest += w) {
296 memcpy(dest, source, w * sizeof(pixel32));
299 else if (l->surface.grad == Background_Solid)
300 gradient_solid(l, x, y, w, h);
301 else gradient_render(&l->surface, w, h);
303 for (i = 0; i < l->textures; i++) {
304 tarea = l->texture[i].position;
305 if (l->surface.grad != Background_ParentRelative) {
306 if (l->surface.relief != Flat) {
307 switch (l->surface.bevel) {
309 tarea.x += 1; tarea.y += 1;
310 tarea.width -= 2; tarea.height -= 2;
313 tarea.x += 2; tarea.y += 2;
314 tarea.width -= 4; tarea.height -= 4;
317 } else if (l->surface.border) {
318 tarea.x += 1; tarea.y += 1;
319 tarea.width -= 2; tarea.height -= 2;
323 switch (l->texture[i].type) {
327 if (l->surface.grad != Background_Solid)
328 pixel32_to_pixmap(l->surface.pixel_data,
331 if (l->xftdraw == NULL) {
332 l->xftdraw = XftDrawCreate(ob_display, l->pixmap,
333 render_visual, render_colormap);
335 font_draw(l->xftdraw, &l->texture[i].data.text,
341 if (l->surface.grad != Background_Solid)
342 pixel32_to_pixmap(l->surface.pixel_data,
345 if (l->texture[i].data.mask.color->gc == None)
346 color_allocate_gc(l->texture[i].data.mask.color);
347 mask_draw(l->pixmap, &l->texture[i].data.mask,
351 image_draw(l->surface.pixel_data,
352 &l->texture[i].data.rgba,
360 if (l->surface.grad != Background_Solid)
361 pixel32_to_pixmap(l->surface.pixel_data, l->pixmap
366 XSetWindowBackgroundPixmap(ob_display, win, l->pixmap);
367 XClearWindow(ob_display, win);
368 if (oldp != None) XFreePixmap(ob_display, oldp);
371 void render_shutdown(void)
375 Appearance *appearance_new(int numtex)
380 out = g_new(Appearance, 1);
381 out->textures = numtex;
383 if (numtex) out->texture = g_new0(Texture, numtex);
384 else out->texture = NULL;
390 p->border_color = NULL;
391 p->bevel_dark = NULL;
392 p->bevel_light = NULL;
393 p->pixel_data = NULL;
397 Appearance *appearance_copy(Appearance *orig)
400 Appearance *copy = g_new(Appearance, 1);
402 spo = &(orig->surface);
403 spc = &(copy->surface);
404 spc->grad = spo->grad;
405 spc->relief = spo->relief;
406 spc->bevel = spo->bevel;
407 if (spo->primary != NULL)
408 spc->primary = color_new(spo->primary->r,
411 else spc->primary = NULL;
413 if (spo->secondary != NULL)
414 spc->secondary = color_new(spo->secondary->r,
417 else spc->secondary = NULL;
419 if (spo->border_color != NULL)
420 spc->border_color = color_new(spo->border_color->r,
421 spo->border_color->g,
422 spo->border_color->b);
423 else spc->border_color = NULL;
425 if (spo->bevel_dark != NULL)
426 spc->bevel_dark = color_new(spo->bevel_dark->r,
429 else spc->bevel_dark = NULL;
431 if (spo->bevel_light != NULL)
432 spc->bevel_light = color_new(spo->bevel_light->r,
434 spo->bevel_light->b);
435 else spc->bevel_light = NULL;
437 spc->interlaced = spo->interlaced;
438 spc->border = spo->border;
439 spc->pixel_data = NULL;
441 copy->textures = orig->textures;
442 copy->texture = g_memdup(orig->texture, orig->textures * sizeof(Texture));
444 copy->xftdraw = NULL;
448 void appearance_free(Appearance *a)
452 if (a->pixmap != None) XFreePixmap(ob_display, a->pixmap);
453 if (a->xftdraw != NULL) XftDrawDestroy(a->xftdraw);
457 color_free(p->primary);
458 color_free(p->secondary);
459 color_free(p->border_color);
460 color_free(p->bevel_dark);
461 color_free(p->bevel_light);
462 g_free(p->pixel_data);
469 void pixel32_to_pixmap(pixel32 *in, Pixmap out, int x, int y, int w, int h)
473 im = XCreateImage(ob_display, render_visual, render_depth,
474 ZPixmap, 0, NULL, w, h, 32, 0);
475 g_assert(im != NULL);
476 im->byte_order = render_endian;
477 /* this malloc is a complete waste of time on normal 32bpp
478 as reduce_depth just sets im->data = data and returns
480 scratch = g_new(pixel32, im->width * im->height);
481 im->data = (char*) scratch;
482 reduce_depth(in, im);
483 XPutImage(ob_display, out, DefaultGC(ob_display, ob_screen),
484 im, 0, 0, x, y, w, h);
490 void appearance_minsize(Appearance *l, int *w, int *h)
496 if (l->surface.relief != Flat) {
497 switch (l->surface.bevel) {
505 } else if (l->surface.border)
508 for (i = 0; i < l->textures; ++i) {
509 switch (l->texture[i].type) {
511 *w += l->texture[i].data.mask.mask->w;
512 *h += l->texture[i].data.mask.mask->h;
515 m = font_measure_string(l->texture[i].data.text.font,
516 l->texture[i].data.text.string,
517 l->texture[i].data.text.shadow,
518 l->texture[i].data.text.offset);
520 m = font_height(l->texture[i].data.text.font,
521 l->texture[i].data.text.shadow,
522 l->texture[i].data.text.offset);
526 *w += l->texture[i].data.rgba.width;
527 *h += l->texture[i].data.rgba.height;
535 gboolean render_pixmap_to_rgba(Pixmap pmap, Pixmap mask,
536 int *w, int *h, pixel32 **data)
540 guint pw, ph, mw, mh, xb, xd, i, x, y, di;
541 XImage *xi, *xm = NULL;
543 if (!XGetGeometry(ob_display, pmap, &xr, &xx, &xy, &pw, &ph, &xb, &xd))
546 if (!XGetGeometry(ob_display, mask, &xr, &xx, &xy, &mw, &mh, &xb, &xd))
548 if (pw != mw || ph != mh || xd != 1)
552 xi = XGetImage(ob_display, pmap, 0, 0, pw, ph, 0xffffffff, ZPixmap);
557 xm = XGetImage(ob_display, mask, 0, 0, mw, mh, 0xffffffff, ZPixmap);
562 *data = g_new(pixel32, pw * ph);
563 increase_depth(*data, xi);
566 /* apply transparency from the mask */
568 for (i = 0, y = 0; y < ph; ++y) {
569 for (x = 0; x < pw; ++x, ++i) {
570 if (!((((unsigned)xm->data[di + x / 8]) >> (x % 8)) & 0x1))
571 (*data)[i] &= ~(0xff << default_alpha_offset);
573 di += xm->bytes_per_line;
584 void gl_paint(Window win, Appearance *l)
588 int i, transferred = 0, sw, b, d;
589 pixel32 *source, *dest;
591 int tempx, tempy, absx, absy, absw, absh;
594 int w = l->area.width;
595 int h = l->area.height;
596 Rect tarea; /* area in which to draw textures */
597 if (w <= 0 || h <= 0 || x+w <= 0 || y+h <= 0) return;
599 g_assert(l->surface.type == Surface_Planar);
601 printf("making %p, %p, %p current\n", ob_display, win, render_glx_context);
602 err = glXMakeCurrent(ob_display, win, render_glx_context);
605 glMatrixMode(GL_MODELVIEW);
607 glMatrixMode(GL_PROJECTION);
609 glOrtho(0, 1376, 1032, 0, 0, 10);
610 if (XGetGeometry(ob_display, win, &root, &tempx, &tempy,
611 &absw, &absh, &b, &d) &&
612 XTranslateCoordinates(ob_display, win, root, tempx, tempy,
613 &absx, &absy, &child))
614 printf("window at %d, %d (%d,%d)\n", absx, absy, absw, absh);
618 glViewport(0, 0, 1376, 1032);
619 glMatrixMode(GL_MODELVIEW);
620 glTranslatef(-absx, 1032-absh-absy, 0);
621 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
624 if (l->surface.grad == Background_ParentRelative) {
627 render_gl_gradient(&l->surface, absx+x, absy+y, absw, absh);
629 glXSwapBuffers(ob_display, win);