tahoma2d/toonz/sources/common/tvectorrenderer.cpp
Toshihiro Shimizu 890dddabbd first commit
2016-03-19 02:57:51 +09:00

459 lines
12 KiB
C++

#ifdef USE_MESA
#include <GL/osmesa.h>
#endif
#include "tvectorrenderdata.h"
#include "tvectorimage.h"
#include "tstrokeutil.h"
#include "tmathutil.h"
#include "tgl.h"
#include "tcurves.h"
#ifndef __sgi
#include <cstdio>
#include <cstdlib>
#include <cstring>
#else
#include <math.h>
#include <string.h>
#include <stdlib.h>
#endif
#if defined(LINUX) || defined(__sgi)
#include <GL/glx.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#endif
#ifdef USE_MESA
extern "C" int GLAPIENTRY wglChoosePixelFormat(HDC, const PIXELFORMATDESCRIPTOR *);
extern "C" int GLAPIENTRY wglDescribePixelFormat(HDC, int, unsigned int, LPPIXELFORMATDESCRIPTOR);
extern "C" int GLAPIENTRY wglSetPixelFormat(HDC, int, const PIXELFORMATDESCRIPTOR *);
extern "C" int GLAPIENTRY wglSwapBuffers(HDC);
#define ChoosePixelFormat wglChoosePixelFormat
#define SetPixelFormat wglSetPixelFormat
#define SwapBuffers wglSwapBuffers
#endif
//=============================================================================
#ifdef WIN32
// init a BITMAPINFO structure
void initBITMAPINFO(BITMAPINFO &info, const TRasterP img)
{
memset(&info, 0, sizeof(BITMAPINFOHEADER));
info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
info.bmiHeader.biWidth = img->getLx();
info.bmiHeader.biHeight = img->getLy();
info.bmiHeader.biPlanes = 1;
info.bmiHeader.biBitCount = 32;
info.bmiHeader.biCompression = BI_RGB;
info.bmiHeader.biSizeImage = 0;
info.bmiHeader.biXPelsPerMeter = 1000;
info.bmiHeader.biYPelsPerMeter = 1000;
info.bmiHeader.biClrUsed = 0;
info.bmiHeader.biClrImportant = 0;
}
//-----------------------------------------------------------------------------
#ifdef BUBU
void hardRenderVectorImage_MESA(const TVectorRenderData &rd, TRaster32P &ras, const TVectorImageP &vimg)
{
int rasterWidth = ras->getLx();
int rasterHeight = ras->getLy();
//--- begin mesa stuff
/* Create an RGBA-mode context */
#if OSMESA_MAJOR_VERSION * 100 + OSMESA_MINOR_VERSION >= 305
/* specify Z, stencil, accum sizes */
OSMesaContext ctx = OSMesaCreateContextExt(OSMESA_RGBA, 16, 0, 0, NULL);
#else
OSMesaContext ctx = OSMesaCreateContext(OSMESA_RGBA, NULL);
#endif
if (!ctx) {
throw TException("OSMesaCreateContext failed!\n");
}
ras->lock();
/* Bind the buffer to the context and make it current */
if (!OSMesaMakeCurrent(ctx, ras->getRawData(), GL_UNSIGNED_BYTE, ras->getLx(), ras->getLy())) {
{
ras->unlock();
throw TException("OSMesaMakeCurrent failed!\n");
}
}
//---end mesa stuff
// cfr. help: OpenGL/Programming tip/OpenGL Correctness Tips
glViewport(0, 0, rasterWidth, rasterHeight);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, rasterWidth, 0, rasterHeight);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.375, 0.375, 0.0);
/*
glClearColor(0.0f,0.0f,0.0f,0.0f);
glClear(GL_COLOR_BUFFER_BIT);
// draw background
glRasterPos2d(0, 0);
glDrawPixels( ras->getLx(),ras->getLy(), GL_BGRA_EXT, GL_UNSIGNED_BYTE, ras->getRawData());
*/
// do OpenGL draw
assert(vimg);
tglDraw(rd, vimg.getPointer());
// force to finish
glFlush();
glFinish();
/*
// set info in out raster
TDimension size = ras->getSize();
if( ras->getWrap() == rasterWidth )
memcpy( ras->getRawData(), offData, ras->getPixelSize()*size.lx*size.ly );
else
{
TRaster32P temp( ras->getLx(), ras->getLy());
memcpy( temp->getRawData(), offData, ras->getPixelSize()*size.lx*size.ly );
ras->copy(temp);
}
*/
OSMesaDestroyContext(ctx);
ras->unlock();
}
#endif //BUBU
void hardRenderVectorImage(const TVectorRenderData &rd, TRaster32P &ras, const TVectorImageP &vimg)
{
int rasterWidth = ras->getLx();
int rasterHeight = ras->getLy();
ras->lock();
#ifdef USE_MESA
/* Create an RGBA-mode context */
#if OSMESA_MAJOR_VERSION * 100 + OSMESA_MINOR_VERSION >= 305
/* specify Z, stencil, accum sizes */
OSMesaContext ctx = OSMesaCreateContextExt(OSMESA_RGBA, 16, 0, 0, NULL);
#else
OSMesaContext ctx = OSMesaCreateContext(OSMESA_RGBA, NULL);
#endif
if (!ctx) {
ras->unlock();
throw TException("OSMesaCreateContext failed!\n");
}
/* Bind the buffer to the context and make it current */
if (!OSMesaMakeCurrent(ctx, ras->getRawData(), GL_UNSIGNED_BYTE, ras->getLx(), ras->getLy())) {
{
ras->unlock();
throw TException("OSMesaMakeCurrent failed!\n");
}
}
#else
BITMAPINFO info;
initBITMAPINFO(info, ras);
void *offData = 0; // a pointer to buffer
// open an offscreen device
HDC offDC = CreateCompatibleDC(NULL);
HBITMAP offDIB = // and a bitmap image
CreateDIBSection(offDC, &info, DIB_RGB_COLORS, &offData, NULL, 0);
assert(offDIB);
assert(offData);
int dataSize = // number of byte of raster
rasterWidth * rasterHeight * 4;
memset(offData, 0, dataSize);
HGDIOBJ oldobj = // select BIB to write
SelectObject(offDC, offDIB);
static PIXELFORMATDESCRIPTOR pfd =
{
sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd
1, // version number
0 | (false ? (PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER) : (PFD_DRAW_TO_BITMAP | PFD_SUPPORT_GDI)) | PFD_SUPPORT_OPENGL, // support OpenGL
PFD_TYPE_RGBA, // RGBA type
32, // 32-bit color depth
0, 0, 0, 0, 0, 0, // color bits ignored
0, // no alpha buffer
0, // shift bit ignored
0, // no accumulation buffer
0, 0, 0, 0, // accum bits ignored
32, // 32-bit z-buffer
0, // no stencil buffer
0, // no auxiliary buffer
PFD_MAIN_PLANE, // main layer
0, // reserved
0, 0, 0 // layer masks ignored
};
// get the best available match of pixel format for the device context
int iPixelFormat = ChoosePixelFormat(offDC, &pfd);
assert(iPixelFormat != 0);
// make that the pixel format of the device context
int ret = SetPixelFormat(offDC, iPixelFormat, &pfd);
assert(ret == TRUE);
// make a valid context for OpenGL rendering
HGLRC hglRC = wglCreateContext(offDC);
assert(hglRC);
ret = wglMakeCurrent(offDC, hglRC);
assert(ret == TRUE);
#endif
// cfr. help: OpenGL/Programming tip/OpenGL Correctness Tips
glViewport(0, 0, rasterWidth, rasterHeight);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, rasterWidth, 0, rasterHeight);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.375, 0.375, 0.0);
#ifndef USE_MESA
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
// draw background
glRasterPos2d(0, 0);
glDrawPixels(ras->getLx(), ras->getLy(), GL_BGRA_EXT, GL_UNSIGNED_BYTE, ras->getRawData());
#endif
// do OpenGL draw
assert(vimg);
tglDraw(rd, vimg.getPointer());
// force to finish
glFlush();
#ifdef USE_MESA
OSMesaDestroyContext(ctx);
#else
// set info in out raster
TDimension size = ras->getSize();
if (ras->getWrap() == rasterWidth)
memcpy(ras->getRawData(), offData, ras->getPixelSize() * size.lx * size.ly);
else {
TRaster32P temp(ras->getLx(), ras->getLy());
memcpy(temp->getRawData(), offData, ras->getPixelSize() * size.lx * size.ly);
ras->copy(temp);
}
ret = wglMakeCurrent(offDC, NULL);
assert(ret == TRUE);
wglDeleteContext(hglRC);
// release object
SelectObject(offDC, oldobj);
DeleteObject(offDIB);
DeleteObject(offDC);
#endif
ras->unlock();
}
// end of WIN32
#elif defined(__sgi) || defined(LINUX)
//=============================================================================
namespace
{
GLXContext ctx;
XVisualInfo *visinfo;
GC gc;
Window make_rgb_window(Display *dpy,
unsigned int width, unsigned int height)
{
const int sbAttrib[] = {GLX_RGBA,
GLX_RED_SIZE, 1,
GLX_GREEN_SIZE, 1,
GLX_BLUE_SIZE, 1,
None};
const int dbAttrib[] = {GLX_RGBA,
GLX_RED_SIZE, 1,
GLX_GREEN_SIZE, 1,
GLX_BLUE_SIZE, 1,
GLX_DOUBLEBUFFER,
None};
int scrnum;
XSetWindowAttributes attr;
TUINT32 mask;
Window root;
Window win;
scrnum = DefaultScreen(dpy);
root = RootWindow(dpy, scrnum);
visinfo = glXChooseVisual(dpy, scrnum, (int *)sbAttrib);
if (!visinfo) {
visinfo = glXChooseVisual(dpy, scrnum, (int *)dbAttrib);
if (!visinfo) {
printf("Error: couldn't get an RGB visual\n");
exit(1);
}
}
/* window attributes */
attr.background_pixel = 0;
attr.border_pixel = 0;
/* TODO: share root colormap if possible */
attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone);
attr.event_mask = StructureNotifyMask | ExposureMask;
mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
win = XCreateWindow(dpy, root, 0, 0, width, height,
0, visinfo->depth, InputOutput,
visinfo->visual, mask, &attr);
/* make an X GC so we can do XCopyArea later */
gc = XCreateGC(dpy, win, 0, NULL);
/* need indirect context */
ctx = glXCreateContext(dpy, visinfo, NULL, False);
if (!ctx) {
printf("Error: glXCreateContext failed\n");
exit(-1);
}
printf("Direct rendering: %s\n", glXIsDirect(dpy, ctx) ? "Yes" : "No");
return win;
}
GLXPixmap make_pixmap(Display *dpy, Window win,
unsigned int width, unsigned int height,
Pixmap *pixmap)
{
Pixmap pm;
GLXPixmap glxpm;
XWindowAttributes attr;
pm = XCreatePixmap(dpy, win, width, height, visinfo->depth);
if (!pm) {
printf("Error: XCreatePixmap failed\n");
exit(-1);
}
XGetWindowAttributes(dpy, win, &attr);
/*
* IMPORTANT:
* Use the glXCreateGLXPixmapMESA funtion when using Mesa because
* Mesa needs to know the colormap associated with a pixmap in order
* to render correctly. This is because Mesa allows RGB rendering
* into any kind of visual, not just TrueColor or DirectColor.
*/
#ifdef PROBLEMI_CON_IL_DRIVER_NVIDIA // GLX_MESA_pixmap_colormap //
if (strstr(glXQueryExtensionsString(dpy, 0), "GLX_MESA_pixmap_colormap")) {
/* stand-alone Mesa, specify the colormap */
glxpm = glXCreateGLXPixmapMESA(dpy, visinfo, pm, attr.colormap);
} else {
glxpm = glXCreateGLXPixmap(dpy, visinfo, pm);
}
#else
/* This will work with Mesa too if the visual is TrueColor or DirectColor */
glxpm = glXCreateGLXPixmap(dpy, visinfo, pm);
#endif
if (!glxpm) {
printf("Error: GLXCreateGLXPixmap failed\n");
exit(-1);
}
*pixmap = pm;
return glxpm;
}
}
//void offscreenRender(TRaster32P& ras, const TVectorImageP& vimg, const TAffine& aff)
void hardRenderVectorImage(const TVectorRenderData &rd, TRaster32P &ras, const TVectorImageP &vimg)
{
Display *dpy;
Window win;
Pixmap pm;
GLXPixmap glxpm;
ras->lock();
dpy = XOpenDisplay(NULL);
win = make_rgb_window(dpy, ras->getLx(), ras->getLy());
glxpm = make_pixmap(dpy, win, ras->getLx(), ras->getLy(), &pm);
GLXContext oldctx = glXGetCurrentContext();
GLXDrawable olddrw = glXGetCurrentDrawable();
glXMakeCurrent(dpy, glxpm, ctx);
//printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
// cfr. help: OpenGL/Programming tip/OpenGL Correctness Tips
glViewport(0, 0, ras->getLx(), ras->getLy());
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, ras->getLx(), 0, ras->getLy());
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.375, 0.375, 0.0);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
// draw background
glRasterPos2d(0, 0);
glDrawPixels(ras->getLx(), ras->getLy(), GL_RGBA, GL_UNSIGNED_BYTE, ras->getRawData());
// do OpenGL draw
assert(vimg);
tglDraw(rd, vimg.getPointer());
glFlush();
#if defined(__sgi)
glReadPixels(0, 0,
ras->getLx(), ras->getLy(),
GL_ABGR_EXT,
GL_UNSIGNED_BYTE,
ras->getRawData());
#elif defined(LINUX)
glReadPixels(0, 0,
ras->getLx(), ras->getLy(),
GL_RGBA,
GL_UNSIGNED_BYTE,
ras->getRawData());
#endif
Bool ret = glXMakeCurrent(dpy, olddrw, oldctx);
#ifdef DEBUG
if (!ret) {
std::cerr << __FUNCTION__
<< " error in glXMakeCurrent olddrw=" << olddrw
<< " oldctx=" << oldctx << std::endl;
}
#endif
ras->unlock();
}
#endif