void Renderer::renderRenderData(RenderState& rstate, RenderData* render_data) { if (!(rstate.render_mask & render_data->render_mask())) return; // Set the states setRenderStates(render_data, rstate); if (render_data->mesh() != 0) { GL(renderMesh(rstate, render_data)); } // Restoring to Default. // TODO: There's a lot of redundant state changes. If on every render face culling is being set there's no need to // restore defaults. Possibly later we could add a OpenGL state wrapper to avoid redundant api calls. restoreRenderStates(render_data); }
HRESULT Renderer::Initiate(HWND hwnd, int width, int height, bool fullscreen, bool vsync, unsigned int refRate) { m_hWnd = hwnd; // create the IDirect3D9 object m_pD3D = Direct3DCreate9(D3D_SDK_VERSION); if (m_pD3D == NULL) return E_FAIL; // get the display mode D3DDISPLAYMODE d3ddm; m_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm); // set the presentation parameters D3DPRESENT_PARAMETERS d3dpp; ZeroMemory(&d3dpp, sizeof(d3dpp)); d3dpp.BackBufferWidth = width; d3dpp.BackBufferHeight = height; d3dpp.BackBufferCount = 1; d3dpp.BackBufferFormat = d3ddm.Format; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.Windowed = !fullscreen; d3dpp.EnableAutoDepthStencil = true; d3dpp.AutoDepthStencilFormat = D3DFMT_D16; d3dpp.FullScreen_RefreshRateInHz = refRate; if(vsync) d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE; else d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; // create the device if (FAILED(m_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, D3DCREATE_FPU_PRESERVE | D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &m_pD3DDevice))) { //Fallback to software rendering. if (FAILED(m_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, hwnd, D3DCREATE_FPU_PRESERVE | D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &m_pD3DDevice))) { return E_FAIL; } } m_pD3DDevice->GetRenderTarget(0, &m_pOriginalBackBuffer); m_pD3DDevice->GetDepthStencilSurface(&m_pOriginalDepthStencil); //Set default render attributes. m_bDepthBufferRead = true; m_bDepthBufferWrite = true; m_bBlendEnable = true; m_fConstantOpacity = 1.0f; m_bZEnable = true; m_bFogEnable = false; m_nWidth = width; m_nHeight = height; m_nTargetHeight = height; m_nTargetWidth = width; m_bRenderToBackBuffer = true; restoreRenderStates(); gTextureManager = new TextureManager(); m_listVertexBuffer = NULL; m_listIndexBuffer = NULL; int vert_count; int byte_count; int ind_count; HRESULT hres; int sprite_count = 3 * (int)GetCoordOffsetInv() * (int)GetCoordOffsetInv(); vert_count=6;//BillboardSprite::GetNumVerticesStatic(); byte_count = vert_count*sizeof(RenderVertexTL) * sprite_count; m_nLengthVertexBuffer = vert_count * sprite_count; hres = m_pD3DDevice->CreateVertexBuffer( byte_count, //length D3DUSAGE_WRITEONLY, //usage flags RenderVertexTL::FVF, //FVF D3DPOOL_MANAGED, //Pool &m_listVertexBuffer, //vertex buffer to be used. NULL //should be null? ); if(FAILED(hres)) { switch(hres) { case D3DERR_INVALIDCALL: DEBUGPRINTF("Invalid call in CreateVertexBuffer\n"); break; case D3DERR_OUTOFVIDEOMEMORY: DEBUGPRINTF("Out of video memory for CreateVertexBuffer\n"); break; case E_OUTOFMEMORY: DEBUGPRINTF("Out of memory for CreateVertexBuffer\n"); break; } DEBUGPRINTF("%d bytes into vertex buffer fails\n", hres); return E_FAIL; } ind_count=BillboardSprite::GetNumIndicesStatic(); byte_count = ind_count*sizeof(int) * sprite_count; m_nLengthIndexBuffer = ind_count * sprite_count; hres = m_pD3DDevice->CreateIndexBuffer( byte_count, //length D3DUSAGE_WRITEONLY, //usage flags D3DFMT_INDEX16, //format of indices D3DPOOL_MANAGED, //Pool &m_listIndexBuffer, //vertex buffer to be used. NULL //should be null? ); if(FAILED(hres)) { switch(hres) { case D3DERR_INVALIDCALL: DEBUGPRINTF("Invalid call in CreateVertexBuffer\n"); break; case D3DERR_OUTOFVIDEOMEMORY: DEBUGPRINTF("Out of video memory for CreateVertexBuffer\n"); break; case E_OUTOFMEMORY: DEBUGPRINTF("Out of memory for CreateVertexBuffer\n"); break; } DEBUGPRINTF("%d bytes into vertex buffer fails\n", hres); return E_FAIL; } DEBUGPRINTF("Size of input: %d\n", sizeof(RenderVertexTL[4])); m_nCurrentSprite = 0; m_uNumTriangles = 0; return S_OK; }
void LanczosFilter::performPaint(EffectWindowImpl* w, int mask, QRegion region, WindowPaintData& data) { if (effects->compositingType() == KWin::OpenGLCompositing && (data.xScale() < 0.9 || data.yScale() < 0.9) && KGlobalSettings::graphicEffectsLevel() & KGlobalSettings::SimpleAnimationEffects) { if (!m_inited) init(); const QRect screenRect = Workspace::self()->clientArea(ScreenArea, w->screen(), w->desktop()); // window geometry may not be bigger than screen geometry to fit into the FBO if (m_shader && w->width() <= screenRect.width() && w->height() <= screenRect.height()) { double left = 0; double top = 0; double right = w->width(); double bottom = w->height(); foreach (const WindowQuad & quad, data.quads) { // we need this loop to include the decoration padding left = qMin(left, quad.left()); top = qMin(top, quad.top()); right = qMax(right, quad.right()); bottom = qMax(bottom, quad.bottom()); } double width = right - left; double height = bottom - top; if (width > screenRect.width() || height > screenRect.height()) { // window with padding does not fit into the framebuffer // so cut of the shadow left = 0; top = 0; width = w->width(); height = w->height(); } int tx = data.xTranslation() + w->x() + left * data.xScale(); int ty = data.yTranslation() + w->y() + top * data.yScale(); int tw = width * data.xScale(); int th = height * data.yScale(); const QRect textureRect(tx, ty, tw, th); const bool hardwareClipping = !(QRegion(textureRect)-region).isEmpty(); int sw = width; int sh = height; GLTexture *cachedTexture = static_cast< GLTexture*>(w->data(LanczosCacheRole).value<void*>()); if (cachedTexture) { if (cachedTexture->width() == tw && cachedTexture->height() == th) { cachedTexture->bind(); if (hardwareClipping) { glEnable(GL_SCISSOR_TEST); } if (ShaderManager::instance()->isValid()) { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); const qreal rgb = data.brightness() * data.opacity(); const qreal a = data.opacity(); GLShader *shader = ShaderManager::instance()->pushShader(ShaderManager::SimpleShader); shader->setUniform(GLShader::Offset, QVector2D(0, 0)); shader->setUniform(GLShader::ModulationConstant, QVector4D(rgb, rgb, rgb, a)); shader->setUniform(GLShader::Saturation, data.saturation()); shader->setUniform(GLShader::AlphaToOne, 0); cachedTexture->render(region, textureRect, hardwareClipping); ShaderManager::instance()->popShader(); glDisable(GL_BLEND); } else { prepareRenderStates(cachedTexture, data.opacity(), data.brightness(), data.saturation()); cachedTexture->render(region, textureRect, hardwareClipping); restoreRenderStates(cachedTexture, data.opacity(), data.brightness(), data.saturation()); } if (hardwareClipping) { glDisable(GL_SCISSOR_TEST); } cachedTexture->unbind(); m_timer.start(5000, this); return; } else { // offscreen texture not matching - delete delete cachedTexture; cachedTexture = 0; w->setData(LanczosCacheRole, QVariant()); } } WindowPaintData thumbData = data; thumbData.setXScale(1.0); thumbData.setYScale(1.0); thumbData.setXTranslation(-w->x() - left); thumbData.setYTranslation(-w->y() - top); thumbData.setBrightness(1.0); thumbData.setOpacity(1.0); thumbData.setSaturation(1.0); // Bind the offscreen FBO and draw the window on it unscaled updateOffscreenSurfaces(); GLRenderTarget::pushRenderTarget(m_offscreenTarget); glClearColor(0.0, 0.0, 0.0, 0.0); glClear(GL_COLOR_BUFFER_BIT); w->sceneWindow()->performPaint(mask, infiniteRegion(), thumbData); // Create a scratch texture and copy the rendered window into it GLTexture tex(sw, sh); tex.setFilter(GL_LINEAR); tex.setWrapMode(GL_CLAMP_TO_EDGE); tex.bind(); glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, m_offscreenTex->height() - sh, sw, sh); // Set up the shader for horizontal scaling float dx = sw / float(tw); int kernelSize; m_shader->createKernel(dx, &kernelSize); m_shader->createOffsets(kernelSize, sw, Qt::Horizontal); m_shader->bind(); m_shader->setUniforms(); // Draw the window back into the FBO, this time scaled horizontally glClear(GL_COLOR_BUFFER_BIT); QVector<float> verts; QVector<float> texCoords; verts.reserve(12); texCoords.reserve(12); texCoords << 1.0 << 0.0; verts << tw << 0.0; // Top right texCoords << 0.0 << 0.0; verts << 0.0 << 0.0; // Top left texCoords << 0.0 << 1.0; verts << 0.0 << sh; // Bottom left texCoords << 0.0 << 1.0; verts << 0.0 << sh; // Bottom left texCoords << 1.0 << 1.0; verts << tw << sh; // Bottom right texCoords << 1.0 << 0.0; verts << tw << 0.0; // Top right GLVertexBuffer *vbo = GLVertexBuffer::streamingBuffer(); vbo->reset(); vbo->setData(6, 2, verts.constData(), texCoords.constData()); vbo->render(GL_TRIANGLES); // At this point we don't need the scratch texture anymore tex.unbind(); tex.discard(); // create scratch texture for second rendering pass GLTexture tex2(tw, sh); tex2.setFilter(GL_LINEAR); tex2.setWrapMode(GL_CLAMP_TO_EDGE); tex2.bind(); glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, m_offscreenTex->height() - sh, tw, sh); // Set up the shader for vertical scaling float dy = sh / float(th); m_shader->createKernel(dy, &kernelSize); m_shader->createOffsets(kernelSize, m_offscreenTex->height(), Qt::Vertical); m_shader->setUniforms(); // Now draw the horizontally scaled window in the FBO at the right // coordinates on the screen, while scaling it vertically and blending it. glClear(GL_COLOR_BUFFER_BIT); verts.clear(); verts << tw << 0.0; // Top right verts << 0.0 << 0.0; // Top left verts << 0.0 << th; // Bottom left verts << 0.0 << th; // Bottom left verts << tw << th; // Bottom right verts << tw << 0.0; // Top right vbo->setData(6, 2, verts.constData(), texCoords.constData()); vbo->render(GL_TRIANGLES); tex2.unbind(); tex2.discard(); m_shader->unbind(); // create cache texture GLTexture *cache = new GLTexture(tw, th); cache->setFilter(GL_LINEAR); cache->setWrapMode(GL_CLAMP_TO_EDGE); cache->bind(); glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, m_offscreenTex->height() - th, tw, th); GLRenderTarget::popRenderTarget(); if (hardwareClipping) { glEnable(GL_SCISSOR_TEST); } if (ShaderManager::instance()->isValid()) { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); const qreal rgb = data.brightness() * data.opacity(); const qreal a = data.opacity(); GLShader *shader = ShaderManager::instance()->pushShader(ShaderManager::SimpleShader); shader->setUniform(GLShader::Offset, QVector2D(0, 0)); shader->setUniform(GLShader::ModulationConstant, QVector4D(rgb, rgb, rgb, a)); shader->setUniform(GLShader::Saturation, data.saturation()); shader->setUniform(GLShader::AlphaToOne, 0); cache->render(region, textureRect, hardwareClipping); ShaderManager::instance()->popShader(); glDisable(GL_BLEND); } else { prepareRenderStates(cache, data.opacity(), data.brightness(), data.saturation()); cache->render(region, textureRect, hardwareClipping); restoreRenderStates(cache, data.opacity(), data.brightness(), data.saturation()); } if (hardwareClipping) { glDisable(GL_SCISSOR_TEST); } cache->unbind(); w->setData(LanczosCacheRole, QVariant::fromValue(static_cast<void*>(cache))); // Delete the offscreen surface after 5 seconds m_timer.start(5000, this); return; } } // if ( effects->compositingType() == KWin::OpenGLCompositing )