void D3DPostProcessor::PostProcessEFB(const TargetRectangle& src_rect, const TargetSize& src_size) { // Apply normal post-process process, but to the EFB buffers. // Uses the current viewport as the "visible" region to post-process. // In D3D, the viewport rectangle must fit within the render target. TargetRectangle target_rect; TargetSize target_size(src_size.width, src_size.height); target_rect.left = src_rect.left >= 0 ? src_rect.left : 0; target_rect.top = src_rect.top >= 0 ? src_rect.top : 0; target_rect.right = src_rect.right <= src_size.width ? src_rect.right : src_size.width; target_rect.bottom = src_rect.bottom <= src_size.height ? src_rect.bottom : src_size.height; // Source and target textures, if MSAA is enabled, this needs to be resolved D3DTexture2D* color_texture = FramebufferManager::GetResolvedEFBColorTexture(); D3DTexture2D* depth_texture = nullptr; if (m_requires_depth_buffer) { depth_texture = FramebufferManager::GetResolvedEFBDepthTexture(); } // Invoke post process process PostProcess(nullptr, nullptr, nullptr, target_rect, target_size, reinterpret_cast<uintptr_t>(color_texture), target_rect, target_size, reinterpret_cast<uintptr_t>(depth_texture)); // Copy back to EFB buffer when multisampling is enabled if (g_ActiveConfig.iMultisamples > 1) CopyTexture(target_rect, reinterpret_cast<uintptr_t>(FramebufferManager::GetEFBColorTexture()), target_rect, reinterpret_cast<uintptr_t>(color_texture), target_size, -1, false, true); g_renderer->RestoreAPIState(); }
static bool check_qimage( mlt_properties frame_properties ) { mlt_producer producer = static_cast<mlt_producer>( mlt_properties_get_data( frame_properties, "_producer_qtext", NULL ) ); mlt_properties producer_properties = MLT_PRODUCER_PROPERTIES( producer ); QImage* qImg = static_cast<QImage*>( mlt_properties_get_data( producer_properties, "_qimg", NULL ) ); QSize target_size( mlt_properties_get_int( frame_properties, "rescale_width" ), mlt_properties_get_int( frame_properties, "rescale_height" ) ); QSize native_size( mlt_properties_get_int( frame_properties, "meta.media.width" ), mlt_properties_get_int( frame_properties, "meta.media.height" ) ); // Check if the last image signature is different from the path signature // for this frame. char* last_img_sig = mlt_properties_get( producer_properties, "_img_sig" ); char* path_sig = mlt_properties_get( frame_properties, "_path_sig" ); if( !last_img_sig || strcmp( path_sig, last_img_sig ) ) { mlt_properties_set( producer_properties, "_img_sig", path_sig ); return true; } // Check if the last image size matches the requested image size QSize output_size = target_size; if( output_size.isEmpty() ) { output_size = native_size; } if( output_size != qImg->size() ) { return true; } return false; }
static void generate_qimage( mlt_properties frame_properties ) { mlt_producer producer = static_cast<mlt_producer>( mlt_properties_get_data( frame_properties, "_producer_qtext", NULL ) ); mlt_properties producer_properties = MLT_PRODUCER_PROPERTIES( producer ); QImage* qImg = static_cast<QImage*>( mlt_properties_get_data( producer_properties, "_qimg", NULL ) ); QSize target_size( mlt_properties_get_int( frame_properties, "rescale_width" ), mlt_properties_get_int( frame_properties, "rescale_height" ) ); QSize native_size( mlt_properties_get_int( frame_properties, "meta.media.width" ), mlt_properties_get_int( frame_properties, "meta.media.height" ) ); QPainterPath* qPath = static_cast<QPainterPath*>( mlt_properties_get_data( frame_properties, "_qpath", NULL ) ); mlt_color bg_color = mlt_properties_get_color( frame_properties, "_bgcolour" ); mlt_color fg_color = mlt_properties_get_color( frame_properties, "_fgcolour" ); mlt_color ol_color = mlt_properties_get_color( frame_properties, "_olcolour" ); int outline = mlt_properties_get_int( frame_properties, "_outline" ); qreal sx = 1.0; qreal sy = 1.0; // Create a new image and set up scaling if( !target_size.isEmpty() && target_size != native_size ) { *qImg = QImage( target_size, QImage::Format_ARGB32 ); sx = (qreal)target_size.width() / (qreal)native_size.width(); sy = (qreal)target_size.height() / (qreal)native_size.height(); } else { *qImg = QImage( native_size, QImage::Format_ARGB32 ); } qImg->fill( QColor( bg_color.r, bg_color.g, bg_color.b, bg_color.a ).rgba() ); // Draw the text QPainter painter( qImg ); // Scale the painter rather than the image for better looking results. painter.scale( sx, sy ); painter.setRenderHints( QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::HighQualityAntialiasing ); QPen pen; pen.setWidth( outline ); if( outline ) { pen.setColor( QColor( ol_color.r, ol_color.g, ol_color.b, ol_color.a ) ); } else { pen.setColor( QColor( bg_color.r, bg_color.g, bg_color.b, bg_color.a ) ); } painter.setPen( pen ); QBrush brush( QColor( fg_color.r, fg_color.g, fg_color.b, fg_color.a ) ); painter.setBrush( brush ); painter.drawPath( *qPath ); }
void D3DPostProcessor::PostProcessEFBToTexture(uintptr_t dst_texture) { // Apply normal post-process process, but to the EFB buffers. // Uses the current viewport as the "visible" region to post-process. TargetRectangle target_rect = { 0, 0, g_renderer->GetTargetWidth(), g_renderer->GetTargetHeight() }; TargetSize target_size(g_renderer->GetTargetWidth(), g_renderer->GetTargetHeight()); // Source and target textures, if MSAA is enabled, this needs to be resolved D3DTexture2D* color_texture = FramebufferManager::GetResolvedEFBColorTexture(); D3DTexture2D* depth_texture = nullptr; if (m_requires_depth_buffer) { depth_texture = FramebufferManager::GetResolvedEFBDepthTexture(); } D3DTexture2D* real_dst_texture = reinterpret_cast<D3DTexture2D*>(dst_texture); // Invoke post process process PostProcess(nullptr, nullptr, nullptr, target_rect, target_size, reinterpret_cast<uintptr_t>(color_texture), target_rect, target_size, reinterpret_cast<uintptr_t>(depth_texture), dst_texture); g_renderer->RestoreAPIState(); }