2009-09-15 10 views
15

मैं जो हल करता हूं उसे हल करने का प्रयास कर रहा हूं, जो मैंने सोचा था कि एक बहुत ही सरल समस्या होगी। मैं पूरी स्क्रीन सामग्री के साथ एक QPixmap अद्यतन करना चाहता हूं। आप ऐसा करने से इस तरह के एक पिक्समैप प्राप्त कर सकते हैं:X11, XDamage, XRender, और अन्य चालों का उपयोग कर स्क्रीन सामग्री की QPixmap प्रति रखें

QDesktopWidget *w = QApplication::desktop(); 
if (w) 
{ 
    QRect r = w->screenGeometry(); 
    QPixmap p = QPixmap::grabWindow(w->winId(), 0, 0, r.width(), r.height()) 
    QByteArray bitmap; 
} 

इस के साथ समस्या यह है कि QDesktopWidget समाप्त होता है फिर से हथियाने हर बार जब आप इसके लिए पूछना है, भले ही कुछ भी नहीं बदला है X11 सर्वर से पूरे स्क्रीन पिक्समैप।

मुझे इस कोड को तेज़ होने की आवश्यकता है, इसलिए मैं इसे स्वयं करने की कोशिश कर रहा हूं। मेरा शुरुआती बिंदु qx11mirror demo था, हालांकि, मूल रूप से वही काम करता है। जब कुछ बदल गया है, तो यह काम करने के लिए XDamage एक्सटेंशन का उपयोग करता है, लेकिन कैश किए गए पिक्समैप के उस हिस्से को अपडेट करने के लिए क्षतिग्रस्त आयताकार जानकारी का उपयोग करने के बजाय, यह सिर्फ एक "गंदा" ध्वज सेट करता है, जो किसी भी तरह से ताज़ा रीफ्रेश करता है।

तो मैं विंडोज़ के क्षतिग्रस्त हिस्से को अपडेट करने के लिए qx11mirror उदाहरण को संशोधित करने का प्रयास कर रहा हूं, लेकिन मुझे काम करने के लिए कुछ भी नहीं मिल रहा है - मुझे बस एक खाली (काला) पिक्समैप मिलता है। मैं जिस कोड का उपयोग कर रहा हूं वह है:

void QX11Mirror::x11Event(XEvent *event) 
{ 
    if (event->type == m_damageEvent + XDamageNotify) 
    { 
     XDamageNotifyEvent *e = reinterpret_cast<XDamageNotifyEvent*>(event); 

     XWindowAttributes attr; 
     XGetWindowAttributes(QX11Info::display(), m_window, &attr); 
     XRenderPictFormat *format = XRenderFindVisualFormat(QX11Info::display(), attr.visual); 
     bool hasAlpha    = (format->type == PictTypeDirect && format->direct.alphaMask); 
     int x      = attr.x; 
     int y      = attr.y; 
     int width     = attr.width; 
     int height    = attr.height; 

      // debug output so I can see the window pos vs the damaged area: 
     qDebug() << "repainting dirty area:" << x << y << width << height << "vs" << e->area.x << e->area.y << e->area.width << e->area.height; 

     XRenderPictureAttributes pa; 
     pa.subwindow_mode = IncludeInferiors; // Don't clip child widgets  
     Picture picture = XRenderCreatePicture(QX11Info::display(), 
               m_window, 
               format, 
               CPSubwindowMode, 
               &pa); 

     XserverRegion region = XFixesCreateRegionFromWindow(QX11Info::display(), 
                  m_window, WindowRegionBounding); 

     XFixesTranslateRegion(QX11Info::display(), region, -x, -y); 
     XFixesSetPictureClipRegion(QX11Info::display(), picture, 0, 0, region); 
     XFixesDestroyRegion(QX11Info::display(), region); 


     //QPixmap dest(width, height); 
     XRenderComposite(QX11Info::display(),      // display 
         hasAlpha ? PictOpOver : PictOpSrc,   // operation mode 
         picture,         // src drawable 
         None,          // src mask 
         dest.x11PictureHandle(),     // dest drawable 
         e->area.x,         // src X 
         e->area.y,         // src Y 
         0,           // mask X 
         0,           // mask Y 
         e->area.x,         // dest X 
         e->area.y,         // dest Y 
         e->area.width,        // width 
         e->area.height);       // height 

      m_px = dest; 
     XDamageSubtract(QX11Info::display(), e->damage, None, None); 
      emit windowChanged(); 

    } 
    else if (event->type == ConfigureNotify) 
    { 
     XConfigureEvent *e = &event->xconfigure; 
     m_position = QRect(e->x, e->y, e->width, e->height); 
     emit positionChanged(m_position); 
    } 
} 

क्या कोई मुझे सही दिशा में इंगित कर सकता है? XRender, XDamage, और अन्य X11 एक्सटेंशन के लिए ड्यूमेटेनेशन बहुत खराब है। XCopyArea

निम्न पाठ here से लिया से अधिक XRender प्रयोग करने के लिए

कारण।

खिड़की के लिए जीसी बनाने और एक्सकॉपीएरिया() का उपयोग विंडो की सामग्री की प्रतिलिपि बनाने के लिए पूरी तरह से संभव है यदि आप कोर प्रोटोकॉल का उपयोग करना चाहते हैं, लेकिन चूंकि समग्र एक्सटेंशन नए दृश्यों को उजागर करता है (अल्फा चैनलों वाले), इस बात की कोई गारंटी नहीं है कि स्रोत खींचने योग्य प्रारूप का प्रारूप गंतव्य से मेल खाता है। कोर प्रोटोकॉल के साथ स्थिति के परिणामस्वरूप एक त्रुटि त्रुटि होगी, जो कुछ Xrender एक्सटेंशन के साथ नहीं होगा।

इसके अतिरिक्त कोर प्रोटोकॉल को अल्फा चैनलों की कोई समझ नहीं है, जिसका अर्थ यह है कि यह नए एआरजीबी दृश्य का उपयोग करने वाली खिड़कियों को मिश्रित नहीं कर सकता है। जब स्रोत और गंतव्य का एक ही प्रारूप होता है, तो X11R6.8 के रूप में कोर प्रोटोकॉल का उपयोग करने के लिए कोई प्रदर्शन लाभ भी नहीं होता है। यह रिलीज नए समग्र एक्सटेंशन का समर्थन करने वाला पहला भी है।

तो निष्कर्ष में कोई कमी नहीं है, और इन परिचालनों के लिए कोर प्रोटोकॉल पर Xrender चुनने के केवल फायदे हैं।

+0

XCopyArea के बजाय XRender का उपयोग क्यों करें? XRender त्रुटि प्रवण है (यदि आप इसे सही तरीके से सही नहीं करते हैं, तो यह काम नहीं करेगा ..) – ypnos

+0

मुझे पता चला है कि स्क्रीन को अपडेट करने का प्रयास केवल क्षतिग्रस्त हिस्सों को अपडेट करना अभ्यास में इतना अच्छा काम नहीं करता है। उदाहरण के लिए, ओपनजीएल अनुप्रयोग कभी भी क्षति की रिपोर्ट नहीं करते हैं। मुझे लगता है कि स्क्रीन को पुनः प्राप्त करना आपकी सबसे अच्छी शर्त है। – ldog

+0

यदि आप इसे स्मार्ट करते हैं तो आप स्क्रीन को वास्तविक समय (10-20 फ्रेम प्रति सेकंड) में पुनः प्राप्त कर सकते हैं। – ldog

उत्तर

3

सबसे पहले आपको क्यूएक्स 11 मिरर :: डैमेज रिपोर्ट नॉटएक्वायटी से एक्सडैमेजपोर्टपोर्टिंगबॉक्स में डैमेजक्रेट को कॉल में क्षतिपूर्ति रिपोर्ट बदलने की जरूरत है।

अगला आपको XRenderComposite पर कॉल करने से पहले dest.detach() को कॉल करने की आवश्यकता है। हालांकि आपको वास्तव में सदस्य चर के रूप में m_px और dest दोनों की आवश्यकता नहीं है - आप बस m__px का उपयोग कर सकते हैं।

वहाँ भी है कि उदाहरण में XRenderFreePicture का कोई गायब कॉल जो XRenderComposite करने के लिए कॉल के बाद जाना चाहिए:

XRenderFreePicture(QX11Info::display(), picture); 

आप QX11Mirror में सभी कोड QX11Mirror :: पिक्समैप नकल करने की जरूरत नहीं है :: x11Event । इसके बजाय b_ से qRect तक m_dirty के प्रकार को बदलें, फिर X11Event अद्यतन m_dirty को XDamageNotifyEvent से आयताकार के साथ बदलें, यानी। ई> क्षेत्र। फिर QX11Mirror में: m_dirty सत्य होने की जांच करने के बजाय पिक्समैप, जांचें कि m_dirty खाली आयताकार नहीं है या नहीं।फिर आप आयत को x_dirty से XRenderComposite से पास कर देंगे।

संपादित करें:

dest.detach कुंजी सा है - कि बिना आप इसे काम करने के लिए कभी नहीं मिलेगा।

संबंधित मुद्दे