mirror of
https://github.com/X11Libre/xf86-video-nested.git
synced 2026-03-24 01:24:18 +00:00
257 lines
7.1 KiB
C
257 lines
7.1 KiB
C
/*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
* to deal in the Software without restriction, including without limitation
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice (including the next
|
|
* paragraph) shall be included in all copies or substantial portions of the
|
|
* Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
* DEALINGS IN THE SOFTWARE.
|
|
*
|
|
* Author: Paulo Zanoni <pzanoni@mandriva.com>
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <sys/ipc.h>
|
|
#include <sys/shm.h>
|
|
|
|
#include <X11/Xlib.h>
|
|
#include <X11/Xutil.h>
|
|
#include <X11/extensions/XShm.h>
|
|
|
|
#include <xorg/xf86.h>
|
|
|
|
#include "client.h"
|
|
|
|
struct NestedvClientPrivate {
|
|
Display *display;
|
|
int screenNumber;
|
|
Screen *screen;
|
|
Window rootWindow;
|
|
Window window;
|
|
XImage *img;
|
|
GC gc;
|
|
Bool usingShm;
|
|
XShmSegmentInfo shminfo;
|
|
int scrnIndex; /* stored only for xf86DrvMsg usage */
|
|
};
|
|
|
|
/* Checks if a display is open */
|
|
Bool
|
|
NestedvClientCheckDisplay(char *displayName)
|
|
{
|
|
Display *d;
|
|
|
|
d = XOpenDisplay(displayName);
|
|
if (!d) {
|
|
return FALSE;
|
|
} else {
|
|
XCloseDisplay(d);
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
Bool
|
|
NestedvClientValidDepth(int depth)
|
|
{
|
|
/* XXX: implement! */
|
|
return TRUE;
|
|
}
|
|
|
|
NestedvClientPrivatePtr
|
|
NestedvClientCreateScreen(int scrnIndex,
|
|
char *displayName,
|
|
int width,
|
|
int height,
|
|
int originX,
|
|
int originY,
|
|
int depth,
|
|
int bitsPerPixel,
|
|
Pixel *retRedMask,
|
|
Pixel *retGreenMask,
|
|
Pixel *retBlueMask)
|
|
{
|
|
NestedvClientPrivatePtr pPriv;
|
|
XSizeHints sizeHints;
|
|
|
|
int shmMajor, shmMinor;
|
|
Bool hasSharedPixmaps;
|
|
|
|
pPriv = malloc(sizeof(struct NestedvClientPrivate));
|
|
pPriv->scrnIndex = scrnIndex;
|
|
|
|
pPriv->display = XOpenDisplay(displayName);
|
|
if (!pPriv->display)
|
|
return NULL;
|
|
|
|
pPriv->screenNumber = DefaultScreen(pPriv->display);
|
|
pPriv->screen = ScreenOfDisplay(pPriv->display, pPriv->screenNumber);
|
|
pPriv->rootWindow = RootWindow(pPriv->display, pPriv->screenNumber);
|
|
pPriv->gc = DefaultGC(pPriv->display, pPriv->screenNumber);
|
|
|
|
pPriv->window = XCreateSimpleWindow(pPriv->display, pPriv->rootWindow,
|
|
originX, originY, width, height,
|
|
0, 0, 0);
|
|
|
|
sizeHints.flags = PPosition | PSize | PMinSize | PMaxSize;
|
|
sizeHints.min_width = width;
|
|
sizeHints.max_width = width;
|
|
sizeHints.min_height = height;
|
|
sizeHints.max_height = height;
|
|
XSetWMNormalHints(pPriv->display, pPriv->window, &sizeHints);
|
|
|
|
XStoreName(pPriv->display, pPriv->window, "nested");
|
|
|
|
XMapWindow(pPriv->display, pPriv->window);
|
|
|
|
XSelectInput(pPriv->display, pPriv->window, ExposureMask);
|
|
|
|
if (XShmQueryExtension(pPriv->display)) {
|
|
if (XShmQueryVersion(pPriv->display, &shmMajor, &shmMinor,
|
|
&hasSharedPixmaps)) {
|
|
xf86DrvMsg(scrnIndex, X_INFO,
|
|
"XShm extension version %d.%d %s shared pixmaps\n",
|
|
shmMajor, shmMinor,
|
|
(hasSharedPixmaps) ? "with" : "without");
|
|
}
|
|
pPriv->img = XShmCreateImage(pPriv->display,
|
|
DefaultVisualOfScreen(pPriv->screen),
|
|
depth,
|
|
ZPixmap,
|
|
NULL, /* data */
|
|
&pPriv->shminfo,
|
|
width,
|
|
height);
|
|
if (!pPriv->img)
|
|
return NULL;
|
|
|
|
/* XXX: change the 0777 mask? */
|
|
pPriv->shminfo.shmid = shmget(IPC_PRIVATE,
|
|
pPriv->img->bytes_per_line *
|
|
pPriv->img->height,
|
|
IPC_CREAT | 0777);
|
|
if (pPriv->shminfo.shmid == -1) {
|
|
XDestroyImage(pPriv->img);
|
|
return NULL;
|
|
}
|
|
|
|
pPriv->shminfo.shmaddr = (char *)shmat(pPriv->shminfo.shmid, NULL, 0);
|
|
if (pPriv->shminfo.shmaddr == (char *) -1) {
|
|
XDestroyImage(pPriv->img);
|
|
return NULL;
|
|
}
|
|
|
|
pPriv->img->data = pPriv->shminfo.shmaddr;
|
|
pPriv->shminfo.readOnly = FALSE;
|
|
XShmAttach(pPriv->display, &pPriv->shminfo);
|
|
|
|
pPriv->usingShm = TRUE;
|
|
|
|
} else {
|
|
xf86DrvMsg(scrnIndex, X_INFO, "XShm not supported\n");
|
|
pPriv->img = XCreateImage(pPriv->display,
|
|
DefaultVisualOfScreen(pPriv->screen),
|
|
depth,
|
|
ZPixmap,
|
|
0, /* offset */
|
|
NULL, /* data */
|
|
width,
|
|
height,
|
|
32, /* XXX: bitmap_pad */
|
|
0 /* XXX: bytes_per_line */);
|
|
if (!pPriv->img)
|
|
return NULL;
|
|
pPriv->img->data = malloc(pPriv->img->bytes_per_line *
|
|
pPriv->img->height);
|
|
|
|
pPriv->usingShm = FALSE;
|
|
}
|
|
if (!pPriv->img->data)
|
|
return NULL;
|
|
|
|
#if 0
|
|
xf86DrvMsg(scrnIndex, X_INFO, "width: %d\n", pPriv->img->width);
|
|
xf86DrvMsg(scrnIndex, X_INFO, "height: %d\n", pPriv->img->height);
|
|
xf86DrvMsg(scrnIndex, X_INFO, "xoffset: %d\n", pPriv->img->xoffset);
|
|
xf86DrvMsg(scrnIndex, X_INFO, "depth: %d\n", pPriv->img->depth);
|
|
xf86DrvMsg(scrnIndex, X_INFO, "bpp: %d\n", pPriv->img->bits_per_pixel);
|
|
xf86DrvMsg(scrnIndex, X_INFO, "red_mask: 0x%lx\n", pPriv->img->red_mask);
|
|
xf86DrvMsg(scrnIndex, X_INFO, "gre_mask: 0x%lx\n", pPriv->img->green_mask);
|
|
xf86DrvMsg(scrnIndex, X_INFO, "blu_mask: 0x%lx\n", pPriv->img->blue_mask);
|
|
#endif
|
|
*retRedMask = pPriv->img->red_mask;
|
|
*retGreenMask = pPriv->img->green_mask;
|
|
*retBlueMask = pPriv->img->blue_mask;
|
|
|
|
XEvent ev;
|
|
while (1) {
|
|
XNextEvent(pPriv->display, &ev);
|
|
if (ev.type == Expose) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
return pPriv;
|
|
}
|
|
|
|
char *
|
|
NestedvClientGetFrameBuffer(NestedvClientPrivatePtr pPriv)
|
|
{
|
|
return pPriv->img->data;
|
|
}
|
|
|
|
void
|
|
NestedvClientUpdateScreen(NestedvClientPrivatePtr pPriv, int16_t x1, int16_t y1,
|
|
int16_t x2, int16_t y2)
|
|
{
|
|
if (pPriv->usingShm) {
|
|
XShmPutImage(pPriv->display, pPriv->window, pPriv->gc, pPriv->img,
|
|
x1, y1, x1, y1, x2 - x1, y2 - y1, FALSE);
|
|
/* Without this sync we get some freezes, probably due to some lock in
|
|
* the shm usage */
|
|
XSync(pPriv->display, FALSE);
|
|
} else {
|
|
XPutImage(pPriv->display, pPriv->window, pPriv->gc, pPriv->img,
|
|
x1, y1, x1, y1, x2 - x1, y2 - y1);
|
|
}
|
|
}
|
|
|
|
void
|
|
NestedvClientTimerCallback(NestedvClientPrivatePtr pPriv)
|
|
{
|
|
XEvent ev;
|
|
while(XCheckMaskEvent(pPriv->display, ~0, &ev)) {
|
|
if (ev.type == Expose) {
|
|
NestedvClientUpdateScreen(pPriv,
|
|
((XExposeEvent*)&ev)->x,
|
|
((XExposeEvent*)&ev)->y,
|
|
((XExposeEvent*)&ev)->x + ((XExposeEvent*)&ev)->width,
|
|
((XExposeEvent*)&ev)->y + ((XExposeEvent*)&ev)->height);
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
NestedvClientCloseScreen(NestedvClientPrivatePtr pPriv)
|
|
{
|
|
if (pPriv->usingShm) {
|
|
XShmDetach(pPriv->display, &pPriv->shminfo);
|
|
shmdt(pPriv->shminfo.shmaddr);
|
|
} else {
|
|
free(pPriv->img->data);
|
|
}
|
|
XDestroyImage(pPriv->img);
|
|
XCloseDisplay(pPriv->display);
|
|
}
|