1
2 /*
3 * Diverse Bristol audio routines.
4 * Copyright (c) by Nick Copeland <nickycopeland@hotmail.com> 1996,2012
5 *
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see <http://www.gnu.org/licenses/>.
19 *
20 */
21
22 #include "brightonX11internals.h"
23
24 /*
25 * At the moment (14/3/02) this code uses XDrawPoint directly onto the screen.
26 * It could be accelerated by using an XImage structure. In the mean time this
27 * will be accelerated using XDrawPoints() rather than the singular version.
28 */
29 int
BCopyArea(brightonDisplay * display,int x,int y,int w,int h,int dx,int dy)30 BCopyArea(brightonDisplay *display, int x, int y, int w, int h, int dx, int dy)
31 {
32 bdisplay *bd = display->display;
33
34 /*printf("BCopyArea(%x %x, (%i/%i/%i/%i) (%i/%i/%i,%i) %x\n",*/
35 /*bd, display->image, x, y, w, h, dx, dy, bd->width, bd->height, bd->gc);*/
36
37 if ((display->image == NULL) || (display->flags & _BRIGHTON_WINDOW))
38 return(0);
39
40 #ifdef BRIGHTON_XIMAGE
41 /* 0.10.7 code for XImage accelerators */
42 if (display->flags & BRIGHTON_BIMAGE)
43 {
44 //printf("image copy code %i %i, %i %i, %i %i\n", x, y, dx, dy, w, h);
45 #ifdef BRIGHTON_SHMIMAGE
46 XShmPutImage(bd->display,
47 (Window) ((brightonWindow *) display->bwin)->win,
48 (GC) ((brightonWindow *) display->bwin)->gc,
49 (XImage *) display->image,
50 x, y, dx, dy, w, h, False);
51 #else
52 XPutImage(bd->display, (Window) ((brightonWindow *) display->bwin)->win,
53 (GC) ((brightonWindow *) display->bwin)->gc,
54 (XImage *) display->image,
55 x, y, dx, dy, w, h);
56 #endif
57 } else
58 #endif
59 XCopyArea(bd->display, (Pixmap) display->image,
60 (Window) ((brightonWindow *) display->bwin)->win,
61 (GC) ((brightonWindow *) display->bwin)->gc,
62 x, y, w, h, dx, dy);
63
64 return(0);
65 }
66
67 int
BResizeWindow(brightonDisplay * display,brightonWindow * bwin,int width,int height)68 BResizeWindow(brightonDisplay *display, brightonWindow *bwin,
69 int width, int height)
70 {
71 bdisplay *bd = display->display;
72
73 /*printf("BResizeWindow(%x, %x, %i, %i)\n", display, bwin, width, height);*/
74
75 if (~display->flags & _BRIGHTON_WINDOW)
76 XResizeWindow(bd->display, (Window) bwin->win, width, height);
77
78 return(0);
79 }
80
81 #ifdef BRIGHTON_XIMAGE
82 #ifdef BRIGHTON_SHMIMAGE
83 static int
BDrawImage(brightonDisplay * display,brightonBitmap * bitmap,int sx,int sy,int sw,int sh,int destx,int desty)84 BDrawImage(brightonDisplay *display, brightonBitmap *bitmap,
85 int sx, int sy, int sw, int sh,
86 int destx, int desty)
87 {
88 register bdisplay *bd = display->display;
89 /* register brightonWindow *bwin = (brightonWindow *) display->bwin; */
90 register brightonPalette *palette = display->palette;
91 register int *pixels = bitmap->pixels;
92 register int x, y, pindex;
93 register int dx, dy = desty;
94 XImage *image;
95 struct shmid_ds myshmid;
96
97 //printf("BDrawImage(%p, (%i/%i/%i/%i) (%i/%i) (%i/%i) %i\n",
98 //bitmap, sx, sy, sw, sh, destx, desty, bd->width, bd->height, bd->depth);
99
100 if (display->flags & _BRIGHTON_WINDOW)
101 return(0);
102
103 /*
104 * See if we need an image or to resize the image
105 */
106 if (display->image == 0)
107 {
108 char *iData;
109 Visual *visual = DefaultVisual(bd->display, bd->screen_num);
110
111 bd->width = ((brightonWindow *) display->bwin)->width;
112 bd->height = ((brightonWindow *) display->bwin)->height;
113
114 iData = brightonX11malloc(bd->width * bd->height * sizeof(unsigned));
115
116 /*
117 * The bitmap pad has several interpretations and none of them seem
118 * consistent, however if the last two parameters are not correctly
119 * given then the call fails (seen on 64bit systems). We did have:
120 *
121 * 8 * sizeof(long) - bd->depth, sizeof(long) * bd->width))
122 *
123 * This had been changed to
124 *
125 * bd->depth >= 24? 32: bd->depth, 0
126 *
127 * However correctly speaking we might prefer
128 *
129 * bd->depth > 16? 32: bd->depth > 8? 16:8, 0
130 */
131 if ((image = (void *)
132 XShmCreateImage(
133 bd->display,
134 visual,
135 bd->depth,
136 ZPixmap,
137 0,
138 &bd->shminfo,
139 bd->width, bd->height))
140 == NULL)
141 {
142 printf("failed to allocate image: try using option -pixmap\n");
143 brightonX11free(iData);
144 return(0);
145 }
146 /* Get the shared memory and check for errors */
147 bd->shminfo.shmid = shmget(IPC_PRIVATE,
148 image->bytes_per_line * image->height,
149 IPC_CREAT | 0777 );
150
151 if(bd->shminfo.shmid < 0)
152 return(0);
153 /* attach, and check for errrors */
154 bd->shminfo.shmaddr = image->data =
155 (char *) shmat(bd->shminfo.shmid, 0, 0);
156 if (bd->shminfo.shmaddr == (char *) -1)
157 return 1;
158 /* set as read/write, and attach to the display */
159 bd->shminfo.readOnly = False;
160 XShmAttach(bd->display, &bd->shminfo);
161
162 /*
163 * This looks odd but now that we have attached it, mark it for
164 * deletion. This will clear up the mess after all the detaches
165 * have occured.
166 */
167 shmctl(bd->shminfo.shmid, IPC_STAT, &myshmid);
168 shmctl(bd->shminfo.shmid, IPC_RMID, &myshmid);
169
170 display->image = (void *) image;
171 } else if ((bd->width != ((brightonWindow *) display->bwin)->width)
172 || (bd->height != ((brightonWindow *) display->bwin)->height))
173 {
174 char *iData;
175 Visual *visual = DefaultVisual(bd->display, bd->screen_num);
176
177 XShmDetach(bd->display, &bd->shminfo);
178 XDestroyImage((XImage *) display->image);
179 shmdt(bd->shminfo.shmaddr);
180
181 bd->width = ((brightonWindow *) display->bwin)->width;
182 bd->height = ((brightonWindow *) display->bwin)->height;
183
184 iData = brightonX11malloc(bd->width * bd->height * sizeof(unsigned));
185
186 if ((image = (void *)
187 XShmCreateImage(
188 bd->display,
189 visual,
190 bd->depth,
191 ZPixmap,
192 0,
193 &bd->shminfo,
194 bd->width, bd->height))
195 == NULL)
196 {
197 printf("failed to reallocate image\n");
198 brightonX11free(iData);
199 return(0);
200 }
201 /* Get the shared memory and check for errors */
202 bd->shminfo.shmid = shmget(IPC_PRIVATE,
203 image->bytes_per_line * image->height,
204 IPC_CREAT | 0777 );
205 if(bd->shminfo.shmid < 0)
206 return(0);
207 /* attach, and check for errrors */
208 bd->shminfo.shmaddr = image->data =
209 (char *) shmat(bd->shminfo.shmid, 0, 0);
210 if (bd->shminfo.shmaddr == (char *) -1)
211 return 1;
212 /* set as read/write, and attach to the display */
213 bd->shminfo.readOnly = False;
214 XShmAttach(bd->display, &bd->shminfo);
215
216 /*
217 * This looks odd but now that we have attached it, mark it for
218 * deletion. This will clear up the mess after all the detaches
219 * have occured.
220 */
221 shmctl(bd->shminfo.shmid, IPC_STAT, &myshmid);
222 shmctl(bd->shminfo.shmid, IPC_RMID, &myshmid);
223
224 display->image = (void *) image;
225 }
226
227 /*
228 * We now go through each pixel in the bitmap, check we have its color, and
229 * then render it onto the pixmap. After that we copy the relevant area
230 * of the pixmap over to the screen.
231 *
232 * This is currently the main performance hog since the color cache was
233 * implemented in the libbrighton color management code. The only real
234 * resolution that I can see is to use on screen bitmap management.
235 */
236 for (y = sy; y < (sy + sh); y++)
237 {
238 if (y >= bitmap->height)
239 break;
240
241 dx = destx;
242
243 for (x = sx; x < (sx + sw); x++)
244 {
245 if (x >= bitmap->width)
246 break;
247
248 pindex = y * bitmap->width + x;
249
250 /*
251 * Do not render blue
252 */
253 if ((palette[pixels[pindex]].red == 0)
254 && (palette[pixels[pindex]].green == 0)
255 && (palette[pixels[pindex]].blue == 65535))
256 {
257 ++dx;
258 continue;
259 }
260
261 if (palette[pixels[pindex]].pixel < 0)
262 {
263 /*
264 * Allocate a color so we can start painting with them.
265 */
266 BAllocColor(display, &palette[pixels[pindex]],
267 palette[pixels[pindex]].red,
268 palette[pixels[pindex]].green,
269 palette[pixels[pindex]].blue);
270 }
271
272 XPutPixel((XImage *) display->image,
273 dx, dy, palette[pixels[pindex]].pixel);
274
275 ++dx;
276 }
277
278 ++dy;
279 }
280
281 BCopyArea(display, destx, desty, sw, sh, destx, desty);
282
283 return(0);
284 }
285 #else /* ShmImage code */
286 static int
BDrawImage(brightonDisplay * display,brightonBitmap * bitmap,int sx,int sy,int sw,int sh,int destx,int desty)287 BDrawImage(brightonDisplay *display, brightonBitmap *bitmap,
288 int sx, int sy, int sw, int sh,
289 int destx, int desty)
290 {
291 register bdisplay *bd = display->display;
292 /* register brightonWindow *bwin = (brightonWindow *) display->bwin; */
293 register brightonPalette *palette = display->palette;
294 register int *pixels = bitmap->pixels;
295 register int x, y, pindex;
296 register int dx, dy = desty;
297
298 //printf("BDrawImage(%x %x, (%i/%i/%i/%i) (%i/%i) (%i/%i) %i\n",
299 //bwin, bitmap, sx, sy, sw, sh, destx, desty, bd->width, bd->height, bd->depth);
300 if (display->flags & _BRIGHTON_WINDOW)
301 return(0);
302
303 /*
304 * See if we need an image or to resize the image
305 */
306 if (display->image == 0)
307 {
308 char *iData;
309 Visual *visual = DefaultVisual(bd->display, bd->screen_num);
310
311 bd->width = ((brightonWindow *) display->bwin)->width;
312 bd->height = ((brightonWindow *) display->bwin)->height;
313
314 iData = brightonX11malloc(bd->width * bd->height * sizeof(unsigned));
315
316 /*
317 * The bitmap pad has several interpretations and none of them seem
318 * consistent, however if the last two parameters are not correctly
319 * given then the call fails (seen on 64bit systems). We did have:
320 *
321 * 8 * sizeof(long) - bd->depth, sizeof(long) * bd->width))
322 *
323 * This had been changed to
324 *
325 * bd->depth >= 24? 32: bd->depth, 0
326 *
327 * However correctly speaking we might prefer
328 *
329 * bd->depth > 16? 32: bd->depth > 8? 16:8, 0
330 */
331 if ((display->image = (void *)
332 XCreateImage(
333 bd->display,
334 visual,
335 bd->depth,
336 ZPixmap,
337 0,
338 iData,
339 bd->width, bd->height,
340 bd->depth > 16? 32:bd->depth > 8? 16:8,
341 0))
342 == NULL)
343 {
344 printf("failed to allocate image: try using option -pixmap\n");
345 brightonX11free(iData);
346 return(0);
347 }
348 } else if ((bd->width != ((brightonWindow *) display->bwin)->width)
349 || (bd->height != ((brightonWindow *) display->bwin)->height))
350 {
351 char *iData;
352 Visual *visual = DefaultVisual(bd->display, bd->screen_num);
353
354 XDestroyImage((XImage *) display->image);
355
356 bd->width = ((brightonWindow *) display->bwin)->width;
357 bd->height = ((brightonWindow *) display->bwin)->height;
358
359 iData = brightonX11malloc(bd->width * bd->height * sizeof(unsigned));
360
361 if ((display->image = (void *)
362 XCreateImage(
363 bd->display,
364 visual,
365 bd->depth,
366 ZPixmap,
367 0,
368 iData,
369 bd->width, bd->height,
370 bd->depth > 16? 32:bd->depth > 8? 16:8,
371 0))
372 == NULL)
373 {
374 printf("failed to reallocate image\n");
375 brightonX11free(iData);
376 return(0);
377 }
378 }
379
380 /*
381 * We now go through each pixel in the bitmap, check we have its color, and
382 * then render it onto the pixmap. After that we copy the relevant area
383 * of the pixmap over to the screen.
384 *
385 * This is currently the main performance hog since the color cache was
386 * implemented in the libbrighton color management code. The only real
387 * resolution that I can see is to use on screen bitmap management.
388 */
389 for (y = sy; y < (sy + sh); y++)
390 {
391 if (y >= bitmap->height)
392 break;
393
394 dx = destx;
395
396 for (x = sx; x < (sx + sw); x++)
397 {
398 if (x >= bitmap->width)
399 break;
400
401 pindex = y * bitmap->width + x;
402
403 /*
404 * Do not render blue
405 */
406 if ((palette[pixels[pindex]].red == 0)
407 && (palette[pixels[pindex]].green == 0)
408 && (palette[pixels[pindex]].blue == 65535))
409 {
410 ++dx;
411 continue;
412 }
413
414 if (palette[pixels[pindex]].pixel < 0)
415 {
416 /*
417 * Allocate a color so we can start painting with them.
418 */
419 BAllocColor(display, &palette[pixels[pindex]],
420 palette[pixels[pindex]].red,
421 palette[pixels[pindex]].green,
422 palette[pixels[pindex]].blue);
423 }
424
425 XPutPixel((XImage *) display->image,
426 dx, dy, palette[pixels[pindex]].pixel);
427
428 ++dx;
429 }
430
431 ++dy;
432 }
433
434 BCopyArea(display, destx, desty, sw, sh, destx, desty);
435
436 return(0);
437 }
438 #endif /* note shmImage code */
439 #endif /* Image code */
440
441 static int
BDrawPixmap(brightonDisplay * display,brightonBitmap * bitmap,int sx,int sy,int sw,int sh,int destx,int desty)442 BDrawPixmap(brightonDisplay *display, brightonBitmap *bitmap,
443 int sx, int sy, int sw, int sh,
444 int destx, int desty)
445 {
446 bdisplay *bd = display->display;
447 brightonWindow *bwin = (brightonWindow *) display->bwin;
448 brightonQRender *qrender = bd->qrender;
449 brightonPalette *palette = display->palette;
450 int *pixels = bitmap->pixels, ncolors = bd->ocount, cindex;
451 int missed = 0;
452 GC tgc;
453 int x, y, pindex;
454 int dx, dy = desty;
455
456 /*printf("BDrawArea(%x %x, (%i/%i/%i/%i) (%i/%i) (%i/%i) %i\n",*/
457 /*bwin, bitmap, sx, sy, sw, sh, destx, desty, bd->width, bd->height, bd->depth);*/
458
459 if (display->flags & _BRIGHTON_WINDOW)
460 return(0);
461
462 if (qrender == 0)
463 {
464 qrender = (brightonQRender *)
465 brightonX11malloc(BRIGHTON_QR_COLORS * sizeof(brightonQRender));
466 bd->qrender = qrender;
467 ncolors = bd->ocount = BRIGHTON_QR_COLORS;
468 }
469
470 /*
471 * See if we need an image or to resize the image
472 */
473 if (display->image == 0)
474 {
475 bd->width = ((brightonWindow *) display->bwin)->width;
476 bd->height = ((brightonWindow *) display->bwin)->height;
477
478 display->image = (void *) XCreatePixmap(bd->display, (Window) bwin->win,
479 bd->width, bd->height, bd->depth);
480 } else {
481 if ((bd->width != ((brightonWindow *) display->bwin)->width)
482 || (bd->height != ((brightonWindow *) display->bwin)->height))
483 {
484 XFreePixmap(bd->display, (Pixmap) display->image);
485
486 bd->width = ((brightonWindow *) display->bwin)->width;
487 bd->height = ((brightonWindow *) display->bwin)->height;
488
489 display->image = (void *) XCreatePixmap(bd->display,
490 (Window) bwin->win, bd->width, bd->height, bd->depth);
491 }
492 }
493
494 /*
495 * We now go through each pixel in the bitmap, check we have its color, and
496 * then render it onto the pixmap. After that we copy the relevant area
497 * of the pixmap over to the screen.
498 *
499 * This is currently the main performance hog since the color cache was
500 * implemented in the libbrighton color management code. The only real
501 * resolution that I can see is to use on screen bitmap management.
502 */
503 for (y = sy; y < (sy + sh); y++)
504 {
505 if (y >= bitmap->height)
506 break;
507
508 dx = destx;
509
510 for (x = sx; x < (sx + sw); x++)
511 {
512 if (x >= bitmap->width)
513 break;
514
515 pindex = y * bitmap->width + x;
516
517 /*
518 * Do not render blue
519 */
520 if ((palette[pixels[pindex]].red == 0)
521 && (palette[pixels[pindex]].green == 0)
522 && (palette[pixels[pindex]].blue == 65535))
523 {
524 ++dx;
525 continue;
526 }
527
528 if (palette[pixels[pindex]].gc == 0)
529 {
530 /*
531 * Get a GC
532 */
533 BAllocGC(display, &palette[pixels[pindex]],
534 palette[pixels[pindex]].red,
535 palette[pixels[pindex]].green,
536 palette[pixels[pindex]].blue);
537 }
538
539 tgc = palette[pixels[pindex]].gc;
540 for (cindex = 0; cindex < ncolors; cindex++)
541 {
542 if (qrender[cindex].gc == tgc)
543 break;
544
545 if (qrender[cindex].gc == 0)
546 {
547 /*
548 * We have not filled this queue yet.
549 */
550 qrender[cindex].gc = tgc;
551 qrender[cindex].index = cindex;
552 break;
553 }
554 }
555
556 if (cindex == ncolors) {
557 missed++;
558 XDrawPoint(bd->display, (Pixmap) display->image,
559 (GC) palette[pixels[pindex]].gc, dx, dy);
560 } else {
561 qrender[cindex].queue[qrender[cindex].count].x = dx;
562 qrender[cindex].queue[qrender[cindex].count].y = dy;
563 if (++qrender[cindex].count == BRIGHTON_QR_QSIZE)
564 {
565 XDrawPoints(bd->display, (Pixmap) display->image,
566 tgc, qrender[cindex].queue, BRIGHTON_QR_QSIZE,
567 CoordModeOrigin);
568 qrender[cindex].count = 0;
569 }
570 }
571
572 ++dx;
573 }
574
575 ++dy;
576 }
577
578 for (cindex = 0; cindex < ncolors; cindex++)
579 {
580 if (qrender[cindex].count == 0)
581 continue;
582
583 XDrawPoints(bd->display, (Pixmap) display->image,
584 qrender[cindex].gc, qrender[cindex].queue,
585 qrender[cindex].count, CoordModeOrigin);
586
587 qrender[cindex].count = 0;
588 }
589
590 if (missed)
591 {
592 brightonX11free(bd->qrender);
593 bd->ocount += BRIGHTON_QR_COLORS;
594
595 bd->qrender = (brightonQRender *)
596 brightonX11malloc(bd->ocount * sizeof(brightonQRender));
597 /*printf("Allocated %i colors (%i)\n", ncolors, bd->ocount);*/
598 }
599 BCopyArea(display, destx, desty, sw, sh, destx, desty);
600
601 return(0);
602 }
603
604 int
BDrawArea(brightonDisplay * display,brightonBitmap * bitmap,int sx,int sy,int sw,int sh,int destx,int desty)605 BDrawArea(brightonDisplay *display, brightonBitmap *bitmap,
606 int sx, int sy, int sw, int sh, int destx, int desty)
607 {
608 if (display->flags & _BRIGHTON_WINDOW)
609 return(0);
610
611 #ifdef BRIGHTON_XIMAGE
612 /* 0.10.7 code for XImage accelerators */
613 if (display->flags & BRIGHTON_BIMAGE)
614 return(BDrawImage(display, bitmap, sx, sy, sw, sh, destx, desty));
615 #endif
616
617 return(BDrawPixmap(display, bitmap, sx, sy, sw, sh, destx, desty));
618 }
619