void djvOpenGlTest::members() { DJV_DEBUG("djvOpenGlTest::members"); djvImageContext context; QScopedPointer<djvOpenGlContext> openGlContext( context.openGlContextFactory()->create()); djvOpenGlContextScope contextScope(openGlContext.data()); QScopedPointer<djvOpenGlOffscreenBuffer> buffer( new djvOpenGlOffscreenBuffer(djvPixelDataInfo(100, 100, djvPixel::RGBA_U8))); djvOpenGlOffscreenBufferScope bufferScope(buffer.data()); DJV_DEBUG_PRINT("buffer = " << buffer->info()); DJV_DEBUG_PRINT("buffer id = " << buffer->id()); DJV_DEBUG_PRINT("buffer texture = " << buffer->texture()); { djvOpenGlUtil::ortho(djvVector2i(100, 100)); DJV_ASSERT(GL_NO_ERROR == ::glGetError()); djvOpenGlUtil::color(djvColor(0.5)); DJV_ASSERT(GL_NO_ERROR == ::glGetError()); djvOpenGlUtil::drawBox(djvBox2i(25, 25, 50, 50)); DJV_ASSERT(GL_NO_ERROR == ::glGetError()); djvOpenGlUtil::drawBox(djvBox2f(50.0, 50.0, 50.0, 50.0)); DJV_ASSERT(GL_NO_ERROR == ::glGetError()); djvVector2f uv[4] = { djvVector2f(0.0, 0.0), djvVector2f(0.1, 0.0), djvVector2f(0.1, 1.0), djvVector2f(0.0, 1.0) }; djvOpenGlUtil::drawBox(djvBox2i(25, 25, 50, 50), uv); DJV_ASSERT(GL_NO_ERROR == ::glGetError()); djvOpenGlUtil::drawBox(djvBox2f(50.0, 50.0, 50.0, 50.0), uv); DJV_ASSERT(GL_NO_ERROR == ::glGetError()); } { for (int i = 0; i < djvPixel::PIXEL_COUNT; ++i) { DJV_ASSERT(djvOpenGlUtil::format(static_cast<djvPixel::PIXEL>(i))); DJV_ASSERT(djvOpenGlUtil::type(static_cast<djvPixel::PIXEL>(i))); } } }
void djvOpenGlImage::draw( const djvPixelData & data, const djvOpenGlImageOptions & options, djvOpenGlImageState * state) throw (djvError) { //DJV_DEBUG("djvOpenGlImage::draw"); //DJV_DEBUG_PRINT("data = " << data); //DJV_DEBUG_PRINT("color profile = " << options.colorProfile); RestoreState restoreState; djvOpenGlImageState defaultState; if (! state) { state = &defaultState; } const djvPixelDataInfo & info = data.info(); const int proxyScale = options.proxyScale ? djvPixelDataUtil::proxyScale(info.proxy) : 1; const djvVector2i scale = djvVectorUtil::ceil<double, int>( options.xform.scale * djvVector2f(info.size * proxyScale)); const djvVector2i scaleTmp(scale.x, data.h()); //DJV_DEBUG_PRINT("scale = " << scale); //DJV_DEBUG_PRINT("scale tmp = " << scaleTmp); // Initialize. const djvOpenGlImageFilter::FILTER filter = info.size == scale ? djvOpenGlImageFilter::NEAREST : (djvVectorUtil::area(scale) < djvVectorUtil::area(info.size) ? options.filter.min : options.filter.mag); //DJV_DEBUG_PRINT("filter min = " << options.filter.min); //DJV_DEBUG_PRINT("filter mag = " << options.filter.mag); //DJV_DEBUG_PRINT("filter = " << filter); if (! state->_init || state->_info != info || state->_options != options) { switch (filter) { case djvOpenGlImageFilter::NEAREST: case djvOpenGlImageFilter::LINEAR: { //DJV_DEBUG_PRINT("init single pass"); state->_texture->init( data.info(), djvOpenGlImageFilter::toGl(filter), djvOpenGlImageFilter::toGl(filter)); state->_shader->init( sourceVertex, sourceFragment( options.colorProfile.type, options.displayProfile, options.channel, false, 0, false)); } break; case djvOpenGlImageFilter::BOX: case djvOpenGlImageFilter::TRIANGLE: case djvOpenGlImageFilter::BELL: case djvOpenGlImageFilter::BSPLINE: case djvOpenGlImageFilter::LANCZOS3: case djvOpenGlImageFilter::CUBIC: case djvOpenGlImageFilter::MITCHELL: { //DJV_DEBUG_PRINT("init two pass"); state->_texture->init( data.info(), GL_NEAREST, GL_NEAREST); // Initialize horizontal pass. djvPixelData contrib; scaleContrib( data.w(), scale.x, filter, contrib); state->_scaleXContrib->init( contrib, GL_NEAREST, GL_NEAREST); state->_scaleXShader->init( sourceVertex, sourceFragment( options.colorProfile.type, djvOpenGlImageDisplayProfile(), static_cast<djvOpenGlImageOptions::CHANNEL>(0), true, contrib.h(), true)); // Initialize vertical pass. scaleContrib( data.h(), scale.y, filter, contrib); state->_scaleYContrib->init( contrib, GL_NEAREST, GL_NEAREST); state->_scaleYShader->init( sourceVertex, sourceFragment( static_cast<djvColorProfile::PROFILE>(0), options.displayProfile, options.channel, true, contrib.h(), false)); } break; default: break; } state->_init = true; state->_info = info; state->_options = options; } // Render. const djvPixelDataInfo::Mirror mirror( info.mirror.x ? (! options.xform.mirror.x) : options.xform.mirror.x, info.mirror.y ? (! options.xform.mirror.y) : options.xform.mirror.y); //DJV_DEBUG_PRINT("mirror = " << mirror.x << " " << mirror.y); switch (filter) { case djvOpenGlImageFilter::NEAREST: case djvOpenGlImageFilter::LINEAR: { //DJV_DEBUG_PRINT("draw single pass"); state->_shader->bind(); // Initialize color and display profiles. colorProfileInit( options, state->_shader->program(), *state->_lutColorProfile); displayProfileInit( options, state->_shader->program(), *state->_lutDisplayProfile); // Draw. activeTexture(GL_TEXTURE0); uniform1i(state->_shader->program(), "inTexture", 0); state->_texture->copy(data); state->_texture->bind(); DJV_DEBUG_OPEN_GL(glPushMatrix()); const djvMatrix3f m = djvOpenGlImageXform::xformMatrix(options.xform); //DJV_DEBUG_PRINT("m = " << m); DJV_DEBUG_OPEN_GL(glLoadMatrixd(djvMatrixUtil::matrix4(m).e)); quad(info.size, mirror, proxyScale); DJV_DEBUG_OPEN_GL(glPopMatrix()); } break; case djvOpenGlImageFilter::BOX: case djvOpenGlImageFilter::TRIANGLE: case djvOpenGlImageFilter::BELL: case djvOpenGlImageFilter::BSPLINE: case djvOpenGlImageFilter::LANCZOS3: case djvOpenGlImageFilter::CUBIC: case djvOpenGlImageFilter::MITCHELL: { //DJV_DEBUG_PRINT("draw two pass"); // Horizontal pass. djvOpenGlOffscreenBuffer buffer( djvPixelDataInfo(scaleTmp, data.pixel())); { djvOpenGlOffscreenBufferScope bufferScope(&buffer); state->_scaleXShader->bind(); colorProfileInit( options, state->_scaleXShader->program(), *state->_lutColorProfile); activeTexture(GL_TEXTURE0); uniform1i(state->_scaleXShader->program(), "inTexture", 0); state->_texture->copy(data); state->_texture->bind(); activeTexture(GL_TEXTURE1); uniform1i( state->_scaleXShader->program(), "inScaleContrib", 1); state->_scaleXContrib->bind(); glPushAttrib(GL_TRANSFORM_BIT | GL_VIEWPORT_BIT); glMatrixMode(GL_PROJECTION); glPushMatrix(); glMatrixMode(GL_MODELVIEW); glPushMatrix(); djvOpenGlUtil::ortho(scaleTmp); glViewport(0, 0, scaleTmp.x, scaleTmp.y); quad(scaleTmp, mirror); glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); glPopAttrib(); } // Vertical pass. state->_scaleYShader->bind(); displayProfileInit( options, state->_scaleYShader->program(), *state->_lutDisplayProfile); activeTexture(GL_TEXTURE0); uniform1i(state->_scaleYShader->program(), "inTexture", 0); DJV_DEBUG_OPEN_GL(glBindTexture(GL_TEXTURE_2D, buffer.texture())); activeTexture(GL_TEXTURE1); uniform1i(state->_scaleYShader->program(), "inScaleContrib", 1); state->_scaleYContrib->bind(); djvOpenGlImageXform xform = options.xform; xform.scale = djvVector2f(1.0); const djvMatrix3f m = djvOpenGlImageXform::xformMatrix(xform); DJV_DEBUG_OPEN_GL(glPushMatrix()); DJV_DEBUG_OPEN_GL(glLoadMatrixd(djvMatrixUtil::matrix4(m).e)); quad(scale); DJV_DEBUG_OPEN_GL(glPopMatrix()); } break; default: break; } }