Hi!
I have problem initializing standalone mesa (linux-solo) WITHOUT using
the MiniGLX API for my GPLed 3D desktop attempt.
I am able to create screen, drawable and context, then bind these three
elements, but when calling gl* functions screen is always black, i put
fprintf's in r200 driver and the right functions are called but no drawing
occur, i am calling `(*dri->drawable->swapBuffers)(dri->drawable);` to
swap the buffers.
ldd report libGL.so in right location, and dlopen works nicely with
r200_dri.so
Demos in progs/miniglx works correctly so i am pretty sure i am the faulty
one :)
Here is the last part of my DRI initialization routine, everything
before this is fbdev setup and works perfectly, do i am missing
some obvious things?
Attached is my complete DRI initialization routines in case you need the
full picture.
Thanks in advance!
-solca
----------- CUT&PASTE -----------
/* post validate DRI driver context */
if(!dri->driver->postValidateMode(&dri->driverContext)) {
ee_error_num(0, "[dri] unable to post validate driver context",
fbdev->path);
return -1;
}
/* restore hardware state */
dri->driver->restoreHardware(&dri->driverContext);
/* unlock DRM */
DRM_UNLOCK(dri->driverContext.drmFD, dri->driverContext.pSAREA,
dri->driverContext.serverContext);
/* create DRI screen */
dri->screen = (*dri->screenCreate)(dri->driver, &dri->driverContext);
if(!dri->screen) {
ee_error_num(0, "[dri] function '%s' in '%s' failed",
"__driCreateScreen", dri->path);
return -1;
} else
ee_error_num(0, "[dri] create DRI screen (@ %p) successfully",
dri->screen);
/* create DRI drawable */
dri->drawable = (*dri->screen->createDrawable)
(dri->screen,
dri->driverContext.shared.virtualWidth,
dri->driverContext.shared.virtualHeight,
0, dri->driverMode);
if(!dri->drawable) {
ee_error_num(0, "[dri] function '%s' in '%s' failed",
"__driCreateDrawable", dri->path);
return -1;
} else
ee_error_num(0, "[dri] create DRI drawable (@ %p) successfully",
dri->drawable);
/* create DRI context */
dri->context = (*dri->screen->createContext)
(dri->screen,
dri->driverMode,
NULL);
if(!dri->context) {
ee_error_num(0, "[dri] function '%s' in '%s' failed",
"__driCreateContext", dri->path);
return -1;
} else
ee_error_num(0, "[dri] create DRI context (@ %p) successfully",
dri->context);
/* bind screen, drawable and context so we can began issuing GL commands */
(*dri->context->bindContext)(dri->screen, dri->drawable, dri->context);
ee_error_num(0, "[dri] screen, drawable and context bound");
/* set the drawable flag */
dri->driverContext.pSAREA->drawableTable[0].stamp++;
dri->driverContext.pSAREA->drawableTable[0].flags = flag;
/* setup finish here */
ee_error_num(0, "[dri] setup finished");
/* return successfully */
return 0;
--------- END CUT&PASTE ---------
static int ee_server_graphic_dri_init(struct ee_server_graphic_dri *dri) {
/* no dri, is worthless */
if(!dri)
return -1;
/* if no path is provided use r200_dri.so as default */
if(!dri->path)
dri->path = "r200_dri.so";
/* try to load the dri driver */
dri->dl = dlopen(dri->path, RTLD_NOW | RTLD_GLOBAL);
if(!dri->dl) {
ee_error("[dri] could not load %s", dlerror());
if(dri->dl)
ee_error_num(0, "[dri] '%s' must match same version than libGL", dri->path);
return -1;
} else
ee_error_num(0, "[dri] Standalone MESA DRI driver '%s' loaded", dri->path);
/* pull DRI driver hooks */
dri->driver = (struct DRIDriverRec *) dlsym(dri->dl, "__driDriver");
if(!dri->driver) {
ee_error("[dri] could not find '%s' in '%s'", "__driDriver", dri->path);
return -1;
}
dri->screenCreate = (driCreateScreenFunc*) dlsym(dri->dl, "__driCreateScreen");
if(!dri->screenCreate) {
ee_error("[dri] could not find '%s' in '%s'", "__driCreateScreen", dri->path);
return -1;
}
/* return successfully */
return 0;
} /* ee_server_graphic_dri_init */
static void ee_server_graphic_dri_drawable(struct ee_server_graphic_dri *dri, int flag) {
/* no dri, is worthless */
if(!dri)
return;
/* lock DRM */
if(*dri->active)
DRM_LIGHT_LOCK(dri->driverContext.drmFD, dri->driverContext.pSAREA, dri->driverContext.serverContext);
/* set the flag */
dri->driverContext.pSAREA->drawableTable[0].stamp++;
dri->driverContext.pSAREA->drawableTable[0].flags = flag;
/* unlock DRM */
if(*dri->active)
DRM_UNLOCK(dri->driverContext.drmFD, dri->driverContext.pSAREA, dri->driverContext.serverContext);
} /* ee_server_graphic_dri_drawable */
static void ee_server_graphic_dri_fini(struct ee_server_graphic_dri *dri) {
/* no dri, is worthless */
if(!dri)
return;
/* unbind and destroy the DRI context */
if(dri->context) {
/* mark as no drawable */
ee_server_graphic_dri_drawable(dri, 0);
(*dri->context-> unbindContext)(dri->drawable, dri->context);
(*dri->context->destroyContext)(dri->context);
dri->context = NULL;
}
/* destroy the DRI drawable */
if(dri->drawable) {
(*dri->drawable->destroyDrawable)(dri->drawable);
dri->drawable = NULL;
}
/* destroy the DRI screen */
if(dri->screen) {
(*dri->screen->destroyScreen)(dri->screen);
(*dri->driver->haltFBDev)(&dri->driverContext);
dri->screen = NULL;
}
/* close the DRI dl handle */
if(dri->dl)
dlclose(dri->dl);
/* invalidate pointers */
dri->driver = NULL;
dri->screenCreate = NULL;
/* avoid surprises, make the dl handle invalid */
dri->dl = 0;
/* inform user that dri have been properly shutdown */
ee_error_num(0, "[dri] finished");
} /* ee_server_graphic_dri_fini */
static int ee_server_graphic_dri_setup(struct ee_server_graphic_fbdev *fbdev, struct ee_server_graphic_dri *dri) {
int numValidModes;
/* no dri nor fbdev, is worthless */
if(!dri || !fbdev)
return -1;
/* destroy DRI key structures so we can create it again */
/* destroy and unbind the DRI context */
if(dri->context) {
(*dri->context-> unbindContext)(dri->drawable, dri->context);
(*dri->context->destroyContext)(dri->context);
dri->context = NULL;
}
/* destroy the DRI drawable */
if(dri->drawable) {
(*dri->drawable->destroyDrawable)(dri->drawable);
dri->drawable = NULL;
}
/* destroy the DRI screen */
if(dri->screen) {
(*dri->screen->destroyScreen)(dri->screen);
(*dri->driver->haltFBDev)(&dri->driverContext);
dri->screen = NULL;
}
/* hopefully someday we'll be independent of fbdev for DRI setup */
/* setup DRI to a usable state */
dri->driverContext.cpp = dri->driverContext.bpp / 8;
dri->driverContext.shared.fbSize = fbdev->info_fixed.smem_len;
dri->driverContext.shared.fbStride = dri->driverContext.shared.virtualWidth * (dri->driverContext.bpp / 8);
/* fbdev context info */
dri->driverContext.FBStart = fbdev->info_fixed.smem_start;
dri->driverContext.FBSize = fbdev->info_fixed.smem_len;
dri->driverContext.shared.fbSize = fbdev->info_fixed.smem_len;
dri->driverContext.FBAddress = fbdev->mmap_fb;
/* fbdev MMIO region context info */
dri->driverContext.MMIOStart = fbdev->info_fixed.mmio_start;
dri->driverContext.MMIOSize = fbdev->info_fixed.mmio_len;
dri->driverContext.MMIOAddress = fbdev->mmap_mmio;
/* inform user about configuration */
ee_error_num(0, "[dri] setup");
ee_error_num(0, "[dri] Bus ID %s", dri->driverContext.pciBusID);
ee_error_num(0, "[dri] Chipset %04X", dri->driverContext.chipset);
ee_error_num(0, "[dri] Visual Geometry %dx%d-%dbpp",
dri->driverContext.shared.virtualWidth,
dri->driverContext.shared.virtualHeight,
dri->driverContext.bpp);
ee_error_num(0, "[dri] FB Address %p mapped at %p", dri->driverContext.FBStart, dri->driverContext.FBAddress);
ee_error_num(0, "[dri] FB Size %d bytes", dri->driverContext.FBSize);
ee_error_num(0, "[dri] FB MMIO Address %p mapped at %p", dri->driverContext.MMIOStart, dri->driverContext.MMIOAddress);
ee_error_num(0, "[dri] FB MMIO Size %d bytes", dri->driverContext.MMIOSize);
/* ask DRI driver for list of supported configs */
dri->driver->initContextModes(&dri->driverContext, &dri->driverNumModes, &dri->driverModes);
/* report supported dri hardware visual modes */
numValidModes = 0;
ee_error_num(0, "[dri] Number of reported visuals: %d", dri->driverNumModes);
for(int i = 0; i < dri->driverNumModes; i++) {
const __GLcontextModes *mode = dri->driverModes + i;
/* no RGBA mode nor Index mode, is an invalid mode */
if(mode->rgbMode != GL_TRUE && mode->colorIndexMode != GL_TRUE)
continue;
ee_error_num(0, "[dri]\tVisual ID %02d", i);
if(mode->rgbMode == GL_TRUE)
ee_error_num(0, "[dri]\t\tColor RGBA %d/%d/%d/%d",
mode->redBits, mode->greenBits, mode->blueBits, mode->alphaBits);
if(mode->colorIndexMode == GL_TRUE)
ee_error_num(0, "[dri]\t\tColor Index %d bits", mode->indexBits);
if(mode->doubleBufferMode == GL_TRUE)
ee_error_num(0, "[dri]\t\tDouble Buffer Mode");
if(mode->stereoMode == GL_TRUE)
ee_error_num(0, "[dri]\t\tStereo Buffer Mode");
if(mode->haveAccumBuffer == GL_TRUE)
ee_error_num(0, "[dri]\t\tAccumulation Buffer RGBA %d/%d/%d/%d",
mode->accumRedBits, mode->accumGreenBits, mode->accumBlueBits, mode->accumAlphaBits);
if(mode->haveDepthBuffer == GL_TRUE)
ee_error_num(0, "[dri]\t\tDepth Buffer %d bits", mode->depthBits);
if(mode->haveStencilBuffer == GL_TRUE)
ee_error_num(0, "[dri]\t\tStencil Buffer %d bits", mode->stencilBits);
ee_error_num(0, "[dri]\t\tAuxiliary Buffers %d", mode->numAuxBuffers);
ee_error_num(0, "[dri]\t\tLevel %d - Pixel Map Mode %d", mode->level, mode->pixmapMode);
/* increment valid count */
numValidModes++;
/* check if this visual is what we need */
if(mode-> rgbMode == GL_TRUE &&
mode-> redBits == 8 &&
mode-> greenBits == 8 &&
mode-> blueBits == 8 &&
mode-> alphaBits == 8 &&
mode-> doubleBufferMode == GL_TRUE &&
mode-> stereoMode != GL_TRUE &&
mode-> haveAccumBuffer != GL_TRUE &&
mode-> haveDepthBuffer == GL_TRUE &&
mode-> depthBits == 24 &&
mode->haveStencilBuffer == GL_TRUE &&
mode-> stencilBits == 8 &&
mode-> numAuxBuffers == 0 &&
mode-> level == 0 &&
mode-> pixmapMode == 0) {
dri->driverMode = mode;
ee_error_num(0, "[dri]\tChoosen visual: %02d", i);
}
}
ee_error_num(0, "[dri] Number of valid visuals: %d", numValidModes);
/* check if we choose a visual */
if(!dri->driverMode) {
ee_error_num(0, "[dri] Could not find a useful visual");
return -1;
}
/* perform fbdev DRI driver initialization */
if(!dri->driver->initFBDev(&dri->driverContext)) {
ee_error("[dri] function '%s' in '%s' have failed", "__driInitFBDev", dri->path);
return -1;
}
/* set fbdev geometry */
fbdev->info_var_current.bits_per_pixel = dri->driverContext.bpp;
fbdev->info_var_current.xres_virtual = dri->driverContext.shared.virtualWidth;
fbdev->info_var_current.yres_virtual = dri->driverContext.shared.virtualHeight;
fbdev->info_var_current.xres = dri->driverContext.shared.virtualWidth;
fbdev->info_var_current.yres = dri->driverContext.shared.virtualHeight;
fbdev->info_var_current.xoffset = 0;
fbdev->info_var_current.yoffset = 0;
fbdev->info_var_current.nonstd = 0;
fbdev->info_var_current.vmode = ~FB_VMODE_YWRAP;
if(fbdev->info_var_current.bits_per_pixel == 32) {
fbdev->info_var_current.transp.offset = 24;
fbdev->info_var_current.transp.length = 8;
fbdev->info_var_current.red.offset = 16;
fbdev->info_var_current.red.length = 8;
fbdev->info_var_current.green.offset = 8;
fbdev->info_var_current.green.length = 8;
fbdev->info_var_current.blue.offset = 0;
fbdev->info_var_current.blue.length = 8;
/* } else if(fbdev->info_var_current.bits_per_pixel == 16) {
fbdev->info_var_current.transp.offset = 24;
fbdev->info_var_current.transp.length = 8;
fbdev->info_var_current.red.offset = 16;
fbdev->info_var_current.red.length = 8;
fbdev->info_var_current.green.offset = 8;
fbdev->info_var_current.green.length = 8;
fbdev->info_var_current.blue.offset = 0;
fbdev->info_var_current.blue.length = 8; */
} else {
ee_error_num(0, "[dri] Visual depth of 32bpp required, depth requested: %d bpp",
fbdev->info_var_current.bits_per_pixel);
return -1;
}
/* inform about color space setup */
ee_error_num(0, "[dri] fbdev '%s' RGBA configuration: %d/%d,%d/%d,%d/%d,%d/%d", fbdev->path,
fbdev->info_var_current. red.length, fbdev->info_var_current. red.offset,
fbdev->info_var_current. green.length, fbdev->info_var_current. green.offset,
fbdev->info_var_current. blue.length, fbdev->info_var_current. blue.offset,
fbdev->info_var_current.transp.length, fbdev->info_var_current.transp.offset);
/* DRI driver context validation */
if(!dri->driver->validateMode(&dri->driverContext)) {
ee_error("[dri] context validation failed");
return -1;
}
/* set the fbdev timings (from fb.modes) for our requested mode */
if(fbdev->info_var_current.xres == 1280 && /* 1280x1024-75 */
fbdev->info_var_current.yres == 1024) {
fbdev->info_var_current.pixclock = 7408;
fbdev->info_var_current. left_margin = 248;
fbdev->info_var_current.right_margin = 16;
fbdev->info_var_current.upper_margin = 38;
fbdev->info_var_current.lower_margin = 1;
fbdev->info_var_current.hsync_len = 144;
fbdev->info_var_current.hsync_len = 3;
} else if(fbdev->info_var_current.xres == 1024 && /* 1024x768-75 */
fbdev->info_var_current.yres == 768) {
fbdev->info_var_current.pixclock = 12699;
fbdev->info_var_current. left_margin = 176;
fbdev->info_var_current.right_margin = 16;
fbdev->info_var_current.upper_margin = 28;
fbdev->info_var_current.lower_margin = 1;
fbdev->info_var_current.hsync_len = 96;
fbdev->info_var_current.hsync_len = 3;
} else if(fbdev->info_var_current.xres == 768 && /* 768x1024-75 */
fbdev->info_var_current.yres == 1024) {
fbdev->info_var_current.pixclock = 11993;
fbdev->info_var_current. left_margin = 136;
fbdev->info_var_current.right_margin = 32;
fbdev->info_var_current.upper_margin = 41;
fbdev->info_var_current.lower_margin = 1;
fbdev->info_var_current.hsync_len = 80;
fbdev->info_var_current.hsync_len = 3;
} else if(fbdev->info_var_current.xres == 800 && /* 800x600-75 */
fbdev->info_var_current.yres == 600) {
fbdev->info_var_current.pixclock = 20203;
fbdev->info_var_current. left_margin = 160;
fbdev->info_var_current.right_margin = 16;
fbdev->info_var_current.upper_margin = 21;
fbdev->info_var_current.lower_margin = 1;
fbdev->info_var_current.hsync_len = 80;
fbdev->info_var_current.hsync_len = 3;
} else if(fbdev->info_var_current.xres == 640 && /* 640x480-60 */
fbdev->info_var_current.yres == 480) {
fbdev->info_var_current.pixclock = 20203;
fbdev->info_var_current. left_margin = 160;
fbdev->info_var_current.right_margin = 16;
fbdev->info_var_current.upper_margin = 21;
fbdev->info_var_current.lower_margin = 1;
fbdev->info_var_current.hsync_len = 80;
fbdev->info_var_current.hsync_len = 3;
} else {
ee_error_num(0, "[dri] Visual mode not supported: %dx%d-%d",
fbdev->info_var_current.xres,
fbdev->info_var_current.yres,
fbdev->info_var_current.bits_per_pixel);
return -1;
}
/* set the fbdev variable screen information */
if(ioctl(fbdev->fd, FBIOPUT_VSCREENINFO, &fbdev->info_var_current) != 0) {
ee_error("[dri] could not set screen info for fbdev '%s'", fbdev->path);
return -1;
}
/* read back variable screen information in case kernel change it */
if(ioctl(fbdev->fd, FBIOGET_VSCREENINFO, &fbdev->info_var_current) != 0) {
ee_error("[dri] could not get screen info from fbdev '%s'", fbdev->path);
return -1;
}
/* read fixed screen information */
if(ioctl(fbdev->fd, FBIOGET_FSCREENINFO, &fbdev->info_fixed) != 0) {
ee_error("[dri] could not get screen fixed info from fbdev '%s'", fbdev->path);
return -1;
}
/* we just support true-color or direct-color (with a palette) visuals */
if(fbdev->info_fixed.visual != FB_VISUAL_TRUECOLOR &&
fbdev->info_fixed.visual != FB_VISUAL_DIRECTCOLOR) {
ee_error_num(0, "[dri] fbdev '%s' does not support a true-color visual", fbdev->path);
return -1;
}
/* if visual is direct-color we need to setup a color palette */
if(fbdev->info_fixed.visual == FB_VISUAL_DIRECTCOLOR) {
struct fb_cmap map;
unsigned short red[256], green[256], blue[256];
int rcols = 1 << fbdev->info_var_current. red.length;
int gcols = 1 << fbdev->info_var_current.green.length;
int bcols = 1 << fbdev->info_var_current. blue.length;
int i;
map.start = 0;
map.len = gcols;
map.red = red;
map.green = green;
map.blue = blue;
map.transp = NULL;
for(i = 0; i < rcols; i++)
red[i] = (65536 / (rcols - 1)) * i;
for(i = 0; i < gcols; i++)
green[i] = (65536 / (gcols - 1)) * i;
for(i = 0; i < rcols; i++)
blue[i] = (65536 / (bcols - 1)) * i;
if(ioctl(fbdev->fd, FBIOPUTCMAP, (void *) &map) != 0) {
ee_error("[dri] could not set color palette for direct-color visual on fbdev '%s'", fbdev->path);
return -1;
} else
ee_error("[dri] color palette installed for direct-color visual on fbdev '%s'", fbdev->path);
}
/* post validate DRI driver context */
if(!dri->driver->postValidateMode(&dri->driverContext)) {
ee_error_num(0, "[dri] unable to post validate driver context", fbdev->path);
return -1;
}
/* restore hardware state */
dri->driver->restoreHardware(&dri->driverContext);
/* unlock DRM */
DRM_UNLOCK(dri->driverContext.drmFD, dri->driverContext.pSAREA, dri->driverContext.serverContext);
/* create DRI screen */
dri->screen = (*dri->screenCreate)(dri->driver, &dri->driverContext);
if(!dri->screen) {
ee_error_num(0, "[dri] function '%s' in '%s' failed", "__driCreateScreen", dri->path);
return -1;
} else
ee_error_num(0, "[dri] create DRI screen (@ %p) successfully", dri->screen);
/* create DRI drawable */
dri->drawable = (*dri->screen->createDrawable)
(dri->screen,
dri->driverContext.shared.virtualWidth,
dri->driverContext.shared.virtualHeight,
0, dri->driverMode);
if(!dri->drawable) {
ee_error_num(0, "[dri] function '%s' in '%s' failed", "__driCreateDrawable", dri->path);
return -1;
} else
ee_error_num(0, "[dri] create DRI drawable (@ %p) successfully", dri->drawable);
/* create DRI context */
dri->context = (*dri->screen->createContext)
(dri->screen,
dri->driverMode,
NULL);
if(!dri->context) {
ee_error_num(0, "[dri] function '%s' in '%s' failed", "__driCreateContext", dri->path);
return -1;
} else
ee_error_num(0, "[dri] create DRI context (@ %p) successfully", dri->context);
/* bind screen, drawable and context so we can began issuing GL commands */
(*dri->context->bindContext)(dri->screen, dri->drawable, dri->context);
ee_error_num(0, "[dri] screen, drawable and context bound");
/* setup finish here */
ee_error_num(0, "[dri] setup finished");
/* return successfully */
return 0;
} /* ee_server_graphic_dri_setup */
static void ee_server_graphic_dri_swapbuffers(struct ee_server_graphic_dri *dri) {
/* if no dri nor drawable, is worthless */
if(!dri || !dri->drawable)
return;
/* swap the front & back buffers */
(*dri->drawable->swapBuffers)(dri->drawable);
} /* ee_server_graphic_dri_swapbuffers */
static int ee_server_graphic_setup(struct ee_server_graphic *graphic) {
struct ee_server_graphic_dri *dri = &graphic->dri;
int ret;
if(graphic->was_setup)
ee_server_graphic_dri_drawable(&graphic->dri, 0);
/* physical card topology context info */
dri->driverContext.pciBusID = "PCI:1:5:0";
dri->driverContext.pciBus = 1;
dri->driverContext.pciDevice = 5;
dri->driverContext.pciFunc = 0;
dri->driverContext.chipset = 0x5961;
/* geometry context info */
dri->driverContext.shared.virtualWidth = graphic->width;
dri->driverContext.shared.virtualHeight = graphic->height;
dri->driverContext.bpp = graphic->bpp;
ret = ee_server_graphic_dri_setup(&graphic->fbdev, &graphic->dri);
if(ret == 0) {
ee_server_graphic_dri_drawable(&graphic->dri, 1);
graphic->was_setup = 1;
ee_server_scene_setup(graphic->width, graphic->height);
}
return ret;
} /* ee_server_graphic_setup */